udhcpc: allow -O OPT take numeric params
[oweals/busybox.git] / networking / dnsd.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini DNS server implementation for busybox
4  *
5  * Copyright (C) 2005 Roberto A. Foglietta (me@roberto.foglietta.name)
6  * Copyright (C) 2005 Odd Arild Olsen (oao at fibula dot no)
7  * Copyright (C) 2003 Paul Sheer
8  *
9  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10  *
11  * Odd Arild Olsen started out with the sheerdns [1] of Paul Sheer and rewrote
12  * it into a shape which I believe is both easier to understand and maintain.
13  * I also reused the input buffer for output and removed services he did not
14  * need.  [1] http://threading.2038bug.com/sheerdns/
15  *
16  * Some bugfix and minor changes was applied by Roberto A. Foglietta who made
17  * the first porting of oao' scdns to busybox also.
18  */
19
20 //usage:#define dnsd_trivial_usage
21 //usage:       "[-dvs] [-c CONFFILE] [-t TTL_SEC] [-p PORT] [-i ADDR]"
22 //usage:#define dnsd_full_usage "\n\n"
23 //usage:       "Small static DNS server daemon\n"
24 //usage:     "\nOptions:"
25 //usage:     "\n        -c FILE Config file"
26 //usage:     "\n        -t SEC  TTL"
27 //usage:     "\n        -p PORT Listen on PORT"
28 //usage:     "\n        -i ADDR Listen on ADDR"
29 //usage:     "\n        -d      Daemonize"
30 //usage:     "\n        -v      Verbose"
31 //usage:     "\n        -s      Send successful replies only. Use this if you want"
32 //usage:     "\n                to use /etc/resolv.conf with two nameserver lines:"
33 //usage:     "\n                        nameserver DNSD_SERVER"
34 //usage:     "\n                        nameserver NORNAL_DNS_SERVER"
35
36 #include "libbb.h"
37 #include <syslog.h>
38
39 //#define DEBUG 1
40 #define DEBUG 0
41
42 enum {
43         /* can tweak this */
44         DEFAULT_TTL = 120,
45
46         /* cannot get bigger packets than 512 per RFC1035. */
47         MAX_PACK_LEN = 512,
48         IP_STRING_LEN = sizeof(".xxx.xxx.xxx.xxx"),
49         MAX_NAME_LEN = IP_STRING_LEN - 1 + sizeof(".in-addr.arpa"),
50         REQ_A = 1,
51         REQ_PTR = 12,
52 };
53
54 /* the message from client and first part of response msg */
55 struct dns_head {
56         uint16_t id;
57         uint16_t flags;
58         uint16_t nquer;
59         uint16_t nansw;
60         uint16_t nauth;
61         uint16_t nadd;
62 };
63 /* Structure used to access type and class fields.
64  * They are totally unaligned, but gcc 4.3.4 thinks that pointer of type uint16_t*
65  * is 16-bit aligned and replaces 16-bit memcpy (in move_from_unaligned16 macro)
66  * with aligned halfword access on arm920t!
67  * Oh well. Slapping PACKED everywhere seems to help: */
68 struct type_and_class {
69         uint16_t type PACKED;
70         uint16_t class PACKED;
71 } PACKED;
72 /* element of known name, ip address and reversed ip address */
73 struct dns_entry {
74         struct dns_entry *next;
75         uint32_t ip;
76         char rip[IP_STRING_LEN]; /* length decimal reversed IP */
77         char name[1];
78 };
79
80 #define OPT_verbose (option_mask32 & 1)
81 #define OPT_silent  (option_mask32 & 2)
82
83
84 /*
85  * Insert length of substrings instead of dots
86  */
87 static void undot(char *rip)
88 {
89         int i = 0;
90         int s = 0;
91
92         while (rip[i])
93                 i++;
94         for (--i; i >= 0; i--) {
95                 if (rip[i] == '.') {
96                         rip[i] = s;
97                         s = 0;
98                 } else {
99                         s++;
100                 }
101         }
102 }
103
104 /*
105  * Read hostname/IP records from file
106  */
107 static struct dns_entry *parse_conf_file(const char *fileconf)
108 {
109         char *token[2];
110         parser_t *parser;
111         struct dns_entry *m, *conf_data;
112         struct dns_entry **nextp;
113
114         conf_data = NULL;
115         nextp = &conf_data;
116
117         parser = config_open(fileconf);
118         while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
119                 struct in_addr ip;
120                 uint32_t v32;
121
122                 if (inet_aton(token[1], &ip) == 0) {
123                         bb_error_msg("error at line %u, skipping", parser->lineno);
124                         continue;
125                 }
126
127                 if (OPT_verbose)
128                         bb_error_msg("name:%s, ip:%s", token[0], token[1]);
129
130                 /* sizeof(*m) includes 1 byte for m->name[0] */
131                 m = xzalloc(sizeof(*m) + strlen(token[0]) + 1);
132                 /*m->next = NULL;*/
133                 *nextp = m;
134                 nextp = &m->next;
135
136                 m->name[0] = '.';
137                 strcpy(m->name + 1, token[0]);
138                 undot(m->name);
139                 m->ip = ip.s_addr; /* in network order */
140                 v32 = ntohl(m->ip);
141                 /* inverted order */
142                 sprintf(m->rip, ".%u.%u.%u.%u",
143                         (uint8_t)(v32),
144                         (uint8_t)(v32 >> 8),
145                         (uint8_t)(v32 >> 16),
146                         (v32 >> 24)
147                 );
148                 undot(m->rip);
149         }
150         config_close(parser);
151         return conf_data;
152 }
153
154 /*
155  * Look query up in dns records and return answer if found.
156  */
157 static char *table_lookup(struct dns_entry *d,
158                 uint16_t type,
159                 char* query_string)
160 {
161         while (d) {
162                 unsigned len = d->name[0];
163                 /* d->name[len] is the last (non NUL) char */
164 #if DEBUG
165                 char *p, *q;
166                 q = query_string + 1;
167                 p = d->name + 1;
168                 fprintf(stderr, "%d/%d p:%s q:%s %d\n",
169                         (int)strlen(p), len,
170                         p, q, (int)strlen(q)
171                 );
172 #endif
173                 if (type == htons(REQ_A)) {
174                         /* search by host name */
175                         if (len != 1 || d->name[1] != '*') {
176 /* we are lax, hope no name component is ever >64 so that length
177  * (which will be represented as 'A','B'...) matches a lowercase letter.
178  * Actually, I think false matches are hard to construct.
179  * Example.
180  * [31] len is represented as '1', [65] as 'A', [65+32] as 'a'.
181  * [65]   <65 same chars>[31]<31 same chars>NUL
182  * [65+32]<65 same chars>1   <31 same chars>NUL
183  * This example seems to be the minimal case when false match occurs.
184  */
185                                 if (strcasecmp(d->name, query_string) != 0)
186                                         goto next;
187                         }
188                         return (char *)&d->ip;
189 #if DEBUG
190                         fprintf(stderr, "Found IP:%x\n", (int)d->ip);
191 #endif
192                         return 0;
193                 }
194                 /* search by IP-address */
195                 if ((len != 1 || d->name[1] != '*')
196                 /* we assume (do not check) that query_string
197                  * ends in ".in-addr.arpa" */
198                  && strncmp(d->rip, query_string, strlen(d->rip)) == 0
199                 ) {
200 #if DEBUG
201                         fprintf(stderr, "Found name:%s\n", d->name);
202 #endif
203                         return d->name;
204                 }
205  next:
206                 d = d->next;
207         }
208
209         return NULL;
210 }
211
212 /*
213  * Decode message and generate answer
214  */
215 /* RFC 1035
216 ...
217 Whenever an octet represents a numeric quantity, the left most bit
218 in the diagram is the high order or most significant bit.
219 That is, the bit labeled 0 is the most significant bit.
220 ...
221
222 4.1.1. Header section format
223       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
224     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
225     |                      ID                       |
226     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
227     |QR|   OPCODE  |AA|TC|RD|RA| 0  0  0|   RCODE   |
228     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
229     |                    QDCOUNT                    |
230     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
231     |                    ANCOUNT                    |
232     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
233     |                    NSCOUNT                    |
234     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
235     |                    ARCOUNT                    |
236     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
237 ID      16 bit random identifier assigned by querying peer.
238         Used to match query/response.
239 QR      message is a query (0), or a response (1).
240 OPCODE  0   standard query (QUERY)
241         1   inverse query (IQUERY)
242         2   server status request (STATUS)
243 AA      Authoritative Answer - this bit is valid in responses.
244         Responding name server is an authority for the domain name
245         in question section. Answer section may have multiple owner names
246         because of aliases.  The AA bit corresponds to the name which matches
247         the query name, or the first owner name in the answer section.
248 TC      TrunCation - this message was truncated.
249 RD      Recursion Desired - this bit may be set in a query and
250         is copied into the response.  If RD is set, it directs
251         the name server to pursue the query recursively.
252         Recursive query support is optional.
253 RA      Recursion Available - this be is set or cleared in a
254         response, and denotes whether recursive query support is
255         available in the name server.
256 RCODE   Response code.
257         0   No error condition
258         1   Format error
259         2   Server failure - server was unable to process the query
260             due to a problem with the name server.
261         3   Name Error - meaningful only for responses from
262             an authoritative name server. The referenced domain name
263             does not exist.
264         4   Not Implemented.
265         5   Refused.
266 QDCOUNT number of entries in the question section.
267 ANCOUNT number of records in the answer section.
268 NSCOUNT number of records in the authority records section.
269 ARCOUNT number of records in the additional records section.
270
271 4.1.2. Question section format
272
273 The section contains QDCOUNT (usually 1) entries, each of this format:
274       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
275     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
276     /                     QNAME                     /
277     /                                               /
278     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
279     |                     QTYPE                     |
280     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
281     |                     QCLASS                    |
282     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
283 QNAME   a domain name represented as a sequence of labels, where
284         each label consists of a length octet followed by that
285         number of octets. The domain name terminates with the
286         zero length octet for the null label of the root. Note
287         that this field may be an odd number of octets; no
288         padding is used.
289 QTYPE   a two octet type of the query.
290           1 a host address [REQ_A const]
291           2 an authoritative name server
292           3 a mail destination (Obsolete - use MX)
293           4 a mail forwarder (Obsolete - use MX)
294           5 the canonical name for an alias
295           6 marks the start of a zone of authority
296           7 a mailbox domain name (EXPERIMENTAL)
297           8 a mail group member (EXPERIMENTAL)
298           9 a mail rename domain name (EXPERIMENTAL)
299          10 a null RR (EXPERIMENTAL)
300          11 a well known service description
301          12 a domain name pointer [REQ_PTR const]
302          13 host information
303          14 mailbox or mail list information
304          15 mail exchange
305          16 text strings
306        0x1c IPv6?
307         252 a request for a transfer of an entire zone
308         253 a request for mailbox-related records (MB, MG or MR)
309         254 a request for mail agent RRs (Obsolete - see MX)
310         255 a request for all records
311 QCLASS  a two octet code that specifies the class of the query.
312           1 the Internet
313         (others are historic only)
314         255 any class
315
316 4.1.3. Resource Record format
317
318 The answer, authority, and additional sections all share the same format:
319 a variable number of resource records, where the number of records
320 is specified in the corresponding count field in the header.
321 Each resource record has this format:
322       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
323     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
324     /                                               /
325     /                      NAME                     /
326     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
327     |                      TYPE                     |
328     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
329     |                     CLASS                     |
330     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
331     |                      TTL                      |
332     |                                               |
333     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
334     |                   RDLENGTH                    |
335     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
336     /                     RDATA                     /
337     /                                               /
338     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
339 NAME    a domain name to which this resource record pertains.
340 TYPE    two octets containing one of the RR type codes.  This
341         field specifies the meaning of the data in the RDATA field.
342 CLASS   two octets which specify the class of the data in the RDATA field.
343 TTL     a 32 bit unsigned integer that specifies the time interval
344         (in seconds) that the record may be cached.
345 RDLENGTH a 16 bit integer, length in octets of the RDATA field.
346 RDATA   a variable length string of octets that describes the resource.
347         The format of this information varies according to the TYPE
348         and CLASS of the resource record.
349         If the TYPE is A and the CLASS is IN, it's a 4 octet IP address.
350
351 4.1.4. Message compression
352
353 In order to reduce the size of messages, domain names coan be compressed.
354 An entire domain name or a list of labels at the end of a domain name
355 is replaced with a pointer to a prior occurance of the same name.
356
357 The pointer takes the form of a two octet sequence:
358     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
359     | 1  1|                OFFSET                   |
360     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
361 The first two bits are ones.  This allows a pointer to be distinguished
362 from a label, since the label must begin with two zero bits because
363 labels are restricted to 63 octets or less.  The OFFSET field specifies
364 an offset from the start of the message (i.e., the first octet
365 of the ID field in the domain header).
366 A zero offset specifies the first byte of the ID field, etc.
367 Domain name in a message can be represented as either:
368    - a sequence of labels ending in a zero octet
369    - a pointer
370    - a sequence of labels ending with a pointer
371  */
372 static int process_packet(struct dns_entry *conf_data,
373                 uint32_t conf_ttl,
374                 uint8_t *buf)
375 {
376         struct dns_head *head;
377         struct type_and_class *unaligned_type_class;
378         const char *err_msg;
379         char *query_string;
380         char *answstr;
381         uint8_t *answb;
382         uint16_t outr_rlen;
383         uint16_t outr_flags;
384         uint16_t type;
385         uint16_t class;
386         int query_len;
387
388         head = (struct dns_head *)buf;
389         if (head->nquer == 0) {
390                 bb_error_msg("packet has 0 queries, ignored");
391                 return 0; /* don't reply */
392         }
393         if (head->flags & htons(0x8000)) { /* QR bit */
394                 bb_error_msg("response packet, ignored");
395                 return 0; /* don't reply */
396         }
397         /* QR = 1 "response", RCODE = 4 "Not Implemented" */
398         outr_flags = htons(0x8000 | 4);
399         err_msg = NULL;
400
401         /* start of query string */
402         query_string = (void *)(head + 1);
403         /* caller guarantees strlen is <= MAX_PACK_LEN */
404         query_len = strlen(query_string) + 1;
405         /* may be unaligned! */
406         unaligned_type_class = (void *)(query_string + query_len);
407         query_len += sizeof(*unaligned_type_class);
408         /* where to append answer block */
409         answb = (void *)(unaligned_type_class + 1);
410
411         /* OPCODE != 0 "standard query"? */
412         if ((head->flags & htons(0x7800)) != 0) {
413                 err_msg = "opcode != 0";
414                 goto empty_packet;
415         }
416         move_from_unaligned16(class, &unaligned_type_class->class);
417         if (class != htons(1)) { /* not class INET? */
418                 err_msg = "class != 1";
419                 goto empty_packet;
420         }
421         move_from_unaligned16(type, &unaligned_type_class->type);
422         if (type != htons(REQ_A) && type != htons(REQ_PTR)) {
423                 /* we can't handle this query type */
424 //TODO: happens all the time with REQ_AAAA (0x1c) requests - implement those?
425                 err_msg = "type is !REQ_A and !REQ_PTR";
426                 goto empty_packet;
427         }
428
429         /* look up the name */
430         answstr = table_lookup(conf_data, type, query_string);
431 #if DEBUG
432         /* Shows lengths instead of dots, unusable for !DEBUG */
433         bb_error_msg("'%s'->'%s'", query_string, answstr);
434 #endif
435         outr_rlen = 4;
436         if (answstr && type == htons(REQ_PTR)) {
437                 /* returning a host name */
438                 outr_rlen = strlen(answstr) + 1;
439         }
440         if (!answstr
441          || (unsigned)(answb - buf) + query_len + 4 + 2 + outr_rlen > MAX_PACK_LEN
442         ) {
443                 /* QR = 1 "response"
444                  * AA = 1 "Authoritative Answer"
445                  * RCODE = 3 "Name Error" */
446                 err_msg = "name is not found";
447                 outr_flags = htons(0x8000 | 0x0400 | 3);
448                 goto empty_packet;
449         }
450
451         /* Append answer Resource Record */
452         memcpy(answb, query_string, query_len); /* name, type, class */
453         answb += query_len;
454         move_to_unaligned32((uint32_t *)answb, htonl(conf_ttl));
455         answb += 4;
456         move_to_unaligned16((uint16_t *)answb, htons(outr_rlen));
457         answb += 2;
458         memcpy(answb, answstr, outr_rlen);
459         answb += outr_rlen;
460
461         /* QR = 1 "response",
462          * AA = 1 "Authoritative Answer",
463          * TODO: need to set RA bit 0x80? One user says nslookup complains
464          * "Got recursion not available from SERVER, trying next server"
465          * "** server can't find HOSTNAME"
466          * RCODE = 0 "success"
467          */
468         if (OPT_verbose)
469                 bb_error_msg("returning positive reply");
470         outr_flags = htons(0x8000 | 0x0400 | 0);
471         /* we have one answer */
472         head->nansw = htons(1);
473
474  empty_packet:
475         if ((outr_flags & htons(0xf)) != 0) { /* not a positive response */
476                 if (OPT_verbose) {
477                         bb_error_msg("%s, %s",
478                                 err_msg,
479                                 OPT_silent ? "dropping query" : "sending error reply"
480                         );
481                 }
482                 if (OPT_silent)
483                         return 0;
484         }
485         head->flags |= outr_flags;
486         head->nauth = head->nadd = 0;
487         head->nquer = htons(1); // why???
488
489         return answb - buf;
490 }
491
492 int dnsd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
493 int dnsd_main(int argc UNUSED_PARAM, char **argv)
494 {
495         const char *listen_interface = "0.0.0.0";
496         const char *fileconf = "/etc/dnsd.conf";
497         struct dns_entry *conf_data;
498         uint32_t conf_ttl = DEFAULT_TTL;
499         char *sttl, *sport;
500         len_and_sockaddr *lsa, *from, *to;
501         unsigned lsa_size;
502         int udps, opts;
503         uint16_t port = 53;
504         /* Ensure buf is 32bit aligned (we need 16bit, but 32bit can't hurt) */
505         uint8_t buf[MAX_PACK_LEN + 1] ALIGN4;
506
507         opts = getopt32(argv, "vsi:c:t:p:d", &listen_interface, &fileconf, &sttl, &sport);
508         //if (opts & (1 << 0)) // -v
509         //if (opts & (1 << 1)) // -s
510         //if (opts & (1 << 2)) // -i
511         //if (opts & (1 << 3)) // -c
512         if (opts & (1 << 4)) // -t
513                 conf_ttl = xatou_range(sttl, 1, 0xffffffff);
514         if (opts & (1 << 5)) // -p
515                 port = xatou_range(sport, 1, 0xffff);
516         if (opts & (1 << 6)) { // -d
517                 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
518                 openlog(applet_name, LOG_PID, LOG_DAEMON);
519                 logmode = LOGMODE_SYSLOG;
520         }
521
522         conf_data = parse_conf_file(fileconf);
523
524         lsa = xdotted2sockaddr(listen_interface, port);
525         udps = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0);
526         xbind(udps, &lsa->u.sa, lsa->len);
527         socket_want_pktinfo(udps); /* needed for recv_from_to to work */
528         lsa_size = LSA_LEN_SIZE + lsa->len;
529         from = xzalloc(lsa_size);
530         to = xzalloc(lsa_size);
531
532         {
533                 char *p = xmalloc_sockaddr2dotted(&lsa->u.sa);
534                 bb_error_msg("accepting UDP packets on %s", p);
535                 free(p);
536         }
537
538         while (1) {
539                 int r;
540                 /* Try to get *DEST* address (to which of our addresses
541                  * this query was directed), and reply from the same address.
542                  * Or else we can exhibit usual UDP ugliness:
543                  * [ip1.multihomed.ip2] <=  query to ip1  <= peer
544                  * [ip1.multihomed.ip2] => reply from ip2 => peer (confused) */
545                 memcpy(to, lsa, lsa_size);
546                 r = recv_from_to(udps, buf, MAX_PACK_LEN + 1, 0, &from->u.sa, &to->u.sa, lsa->len);
547                 if (r < 12 || r > MAX_PACK_LEN) {
548                         bb_error_msg("packet size %d, ignored", r);
549                         continue;
550                 }
551                 if (OPT_verbose)
552                         bb_error_msg("got UDP packet");
553                 buf[r] = '\0'; /* paranoia */
554                 r = process_packet(conf_data, conf_ttl, buf);
555                 if (r <= 0)
556                         continue;
557                 send_to_from(udps, buf, r, 0, &from->u.sa, &to->u.sa, lsa->len);
558         }
559         return 0;
560 }