Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/dnsd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.983  
changed lines
  Added in v.984