1/* dnsmasq is Copyright (c) 2000 Simon Kelley
2
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License as published by
5   the Free Software Foundation; version 2 dated June, 1991.
6
7   This program is distributed in the hope that it will be useful,
8   but WITHOUT ANY WARRANTY; without even the implied warranty of
9   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10   GNU General Public License for more details.
11*/
12
13#include "dnsmasq.h"
14
15static int extract_name(HEADER *header, unsigned int plen, unsigned char **pp,
16			unsigned char *name, int isExtract)
17{
18  unsigned char *cp = name, *p = *pp, *p1 = NULL;
19  unsigned int j, l, hops = 0;
20  int retvalue = 1;
21
22  while ((l = *p++))
23    {
24      unsigned int label_type = l & 0xc0;
25      if (label_type == 0xc0) /* pointer */
26	{
27	  if (p - (unsigned char *)header + 1u >= plen)
28	    return 0;
29
30	  /* get offset */
31	  l = (l&0x3f) << 8;
32	  l |= *p++;
33	  if (l >= (unsigned int)plen)
34	    return 0;
35
36	  if (!p1) /* first jump, save location to go back to */
37	    p1 = p;
38
39	  hops++; /* break malicious infinite loops */
40	  if (hops > 255)
41	    return 0;
42
43	  p = l + (unsigned char *)header;
44	}
45      else if (label_type == 0x80)
46	return 0; /* reserved */
47      else if (label_type == 0x40)
48	{ /* ELT */
49	  unsigned int count, digs;
50
51	  if ((l & 0x3f) != 1)
52	    return 0; /* we only understand bitstrings */
53
54	  if (!isExtract)
55	    return 0; /* Cannot compare bitsrings */
56
57	  count = *p++;
58	  if (count == 0)
59	    count = 256;
60	  digs = ((count-1)>>2)+1;
61
62	  /* output is \[x<hex>/siz]. which is digs+9 chars */
63	  if (cp - name + digs + 9 >= MAXDNAME)
64	    return 0;
65	  if (p - (unsigned char *)header + ((count-1)>>3) + 1u >= plen)
66	    return 0;
67
68	  *cp++ = '\\';
69	  *cp++ = '[';
70	  *cp++ = 'x';
71	  for (j=0; j<digs; j++)
72	    {
73	      unsigned int dig;
74	      if (j%2 == 0)
75		dig = *p >> 4;
76	      else
77		dig = *p++ & 0x0f;
78
79	      *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
80	    }
81	  cp += sprintf(cp, "/%d]", count);
82	  /* do this here to overwrite the zero char from sprintf */
83	  *cp++ = '.';
84	}
85      else
86	{ /* label_type = 0 -> label. */
87	  if (cp - name + l + 1 >= MAXDNAME)
88	    return 0;
89	  if (p - (unsigned char *)header + 1u >= plen)
90	    return 0;
91	  for(j=0; j<l; j++, p++)
92	    if (isExtract)
93	      {
94		if (legal_char(*p))
95		  *cp++ = *p;
96		else
97		  return 0;
98	      }
99	    else
100	      {
101		unsigned char c1 = *cp, c2 = *p;
102
103		if (c1 == 0)
104		  retvalue = 2;
105		else
106		  {
107		    cp++;
108		    if (c1 >= 'A' && c1 <= 'Z')
109		      c1 += 'a' - 'A';
110		    if (c2 >= 'A' && c2 <= 'Z')
111		      c2 += 'a' - 'A';
112
113		    if (c1 != c2)
114		      retvalue =  2;
115		  }
116	      }
117
118	  if (isExtract)
119	    *cp++ = '.';
120	  else
121	    if (*cp != 0 && *cp++ != '.')
122	      retvalue = 2;
123	}
124
125      if ((unsigned int)(p - (unsigned char *)header) >= plen)
126	return 0;
127    }
128
129  if (isExtract)
130    *--cp = 0; /* terminate: lose final period */
131
132  if (p1) /* we jumped via compression */
133    *pp = p1;
134  else
135    *pp = p;
136
137  return retvalue;
138}
139
140/* Max size of input string (for IPv6) is 75 chars.) */
141#define MAXARPANAME 75
142static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
143{
144  int j;
145  char name[MAXARPANAME+1], *cp1;
146  unsigned char *addr = (unsigned char *)addrp;
147  char *lastchunk = NULL, *penchunk = NULL;
148
149  if (strlen(namein) > MAXARPANAME)
150    return 0;
151
152  memset(addrp, 0, sizeof(struct all_addr));
153
154  /* turn name into a series of asciiz strings */
155  /* j counts no of labels */
156  for(j = 1,cp1 = name; *namein; cp1++, namein++)
157    if (*namein == '.')
158      {
159	penchunk = lastchunk;
160        lastchunk = cp1 + 1;
161	*cp1 = 0;
162	j++;
163      }
164    else
165      *cp1 = *namein;
166
167  *cp1 = 0;
168
169  if (j<3)
170    return 0;
171
172  if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr"))
173    {
174      /* IP v4 */
175      /* address arives as a name of the form
176	 www.xxx.yyy.zzz.in-addr.arpa
177	 some of the low order address octets might be missing
178	 and should be set to zero. */
179      for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
180	{
181	  /* check for digits only (weeds out things like
182	     50.0/24.67.28.64.in-addr.arpa which are used
183	     as CNAME targets according to RFC 2317 */
184	  char *cp;
185	  for (cp = cp1; *cp; cp++)
186	    if (!isdigit((int)*cp))
187	      return 0;
188
189	  addr[3] = addr[2];
190	  addr[2] = addr[1];
191	  addr[1] = addr[0];
192	  addr[0] = atoi(cp1);
193	}
194
195      return F_IPV4;
196    }
197#ifdef HAVE_IPV6
198  else if (hostname_isequal(penchunk, "ip6") &&
199	   (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa")))
200    {
201      /* IP v6:
202         Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
203    	 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
204
205	 Note that most of these the various reprentations are obsolete and
206	 left-over from the many DNS-for-IPv6 wars. We support all the formats
207	 that we can since there is no reason not to.
208      */
209
210      if (*name == '\\' && *(name+1) == '[' &&
211	  (*(name+2) == 'x' || *(name+2) == 'X'))
212	{
213	  for (j = 0, cp1 = name+3; *cp1 && isxdigit(*cp1) && j < 32; cp1++, j++)
214	    {
215	      char xdig[2];
216	      xdig[0] = *cp1;
217	      xdig[1] = 0;
218	      if (j%2)
219		addr[j/2] |= strtol(xdig, NULL, 16);
220	      else
221		addr[j/2] = strtol(xdig, NULL, 16) << 4;
222	    }
223
224	  if (*cp1 == '/' && j == 32)
225	    return F_IPV6;
226	}
227      else
228	{
229	  for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
230	    {
231	      if (*(cp1+1) || !isxdigit((int)*cp1))
232		return 0;
233
234	      for (j = sizeof(struct all_addr)-1; j>0; j--)
235		addr[j] = (addr[j] >> 4) | (addr[j-1] << 4);
236	      addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
237	    }
238
239	  return F_IPV6;
240	}
241    }
242#endif
243
244  return 0;
245}
246
247static unsigned char *skip_name(unsigned char *ansp, HEADER *header, unsigned int plen)
248{
249  while(1)
250    {
251      unsigned int label_type = (*ansp) & 0xc0;
252
253      if ((unsigned int)(ansp - (unsigned char *)header) >= plen)
254	return NULL;
255
256      if (label_type == 0xc0)
257	{
258	  /* pointer for compression. */
259	  ansp += 2;
260	  break;
261	}
262      else if (label_type == 0x80)
263	return NULL; /* reserved */
264      else if (label_type == 0x40)
265	{
266	  /* Extended label type */
267	  unsigned int count;
268
269	  if (((*ansp++) & 0x3f) != 1)
270	    return NULL; /* we only understand bitstrings */
271
272	  count = *(ansp++); /* Bits in bitstring */
273
274	  if (count == 0) /* count == 0 means 256 bits */
275	    ansp += 32;
276	  else
277	    ansp += ((count-1)>>3)+1;
278	}
279      else
280	{ /* label type == 0 Bottom six bits is length */
281	  unsigned int len = (*ansp++) & 0x3f;
282	  if (len == 0)
283	    break; /* zero length label marks the end. */
284
285	  ansp += len;
286	}
287    }
288
289  return ansp;
290}
291
292static unsigned char *skip_questions(HEADER *header, unsigned int plen)
293{
294  int q, qdcount = ntohs(header->qdcount);
295  unsigned char *ansp = (unsigned char *)(header+1);
296
297  for (q = 0; q<qdcount; q++)
298    {
299      if (!(ansp = skip_name(ansp, header, plen)))
300	return NULL;
301      ansp += 4; /* class and type */
302    }
303  if ((unsigned int)(ansp - (unsigned char *)header) > plen)
304     return NULL;
305
306  return ansp;
307}
308
309int resize_packet(HEADER *header, unsigned int plen, unsigned char *pheader, unsigned int hlen)
310{
311  int i;
312  unsigned char *ansp = skip_questions(header, plen);
313  unsigned short rdlen;
314
315  if (!ansp)
316    return 0;
317
318  for (i = 0;
319       i < (ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount));
320       i++)
321    {
322      if (!(ansp = skip_name(ansp, header, plen)))
323	return 0;
324      ansp += 8; /* type, class, TTL */
325      GETSHORT(rdlen, ansp);
326      if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
327	return 0;
328      ansp += rdlen;
329    }
330
331  /* restore pseudoheader */
332  if (pheader && ntohs(header->arcount) == 0)
333    {
334      /* must use memmove, may overlap */
335      memmove(ansp, pheader, hlen);
336      header->arcount = htons(1);
337      ansp += hlen;
338    }
339
340  return ansp - (unsigned char *)header;
341}
342
343unsigned char *find_pseudoheader(HEADER *header, unsigned int plen, unsigned int *len, unsigned char **p)
344{
345  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
346     also return length of pseudoheader in *len and pointer to the UDP size in *p */
347
348  int i, arcount = ntohs(header->arcount);
349  unsigned char *ansp;
350  unsigned short rdlen, type;
351
352  if (arcount == 0 || !(ansp = skip_questions(header, plen)))
353    return NULL;
354
355  for (i = 0; i < (ntohs(header->ancount) + ntohs(header->nscount)); i++)
356    {
357      if (!(ansp = skip_name(ansp, header, plen)))
358	return NULL;
359      ansp += 8; /* type, class, TTL */
360      GETSHORT(rdlen, ansp);
361      if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
362	return NULL;
363      ansp += rdlen;
364    }
365
366  for (i = 0; i < arcount; i++)
367    {
368      unsigned char *save, *start = ansp;
369      if (!(ansp = skip_name(ansp, header, plen)))
370	return NULL;
371
372      GETSHORT(type, ansp);
373      save = ansp;
374      ansp += 6; /* class, TTL */
375      GETSHORT(rdlen, ansp);
376      if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
377	return NULL;
378       ansp += rdlen;
379       if (type == T_OPT)
380	{
381	  if (len)
382	    *len = ansp - start;
383	  if (p)
384	    *p = save;
385	  return start;
386	}
387    }
388
389  return NULL;
390}
391
392
393/* is addr in the non-globally-routed IP space? */
394static int private_net(struct all_addr *addrp)
395{
396  struct in_addr addr = *(struct in_addr *)addrp;
397  if (inet_netof(addr) == 0xA ||
398      (inet_netof(addr) >= 0xAC10 && inet_netof(addr) < 0xAC20) ||
399      (inet_netof(addr) >> 8) == 0xC0A8)
400    return 1;
401  else
402    return 0;
403}
404
405static unsigned char *add_text_record(unsigned int nameoffset, unsigned char *p,
406				      unsigned long ttl, unsigned short pref,
407				      unsigned short type, char *name)
408{
409  unsigned char *sav, *cp;
410  int j;
411
412  PUTSHORT(nameoffset | 0xc000, p);
413  PUTSHORT(type, p);
414  PUTSHORT(C_IN, p);
415  PUTLONG(ttl, p); /* TTL */
416
417  sav = p;
418  PUTSHORT(0, p); /* dummy RDLENGTH */
419
420  if (pref)
421    PUTSHORT(pref, p);
422
423  while (*name)
424    {
425      cp = p++;
426      for (j=0; *name && (*name != '.'); name++, j++)
427	*p++ = *name;
428      *cp = j;
429      if (*name)
430	name++;
431    }
432  *p++ = 0;
433  j = p - sav - 2;
434  PUTSHORT(j, sav); /* Real RDLENGTH */
435
436  return p;
437}
438
439/* On receiving an NXDOMAIN or NODATA reply, determine which names are known
440   not to exist for negative caching. name if a working buffer passed in. */
441void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now, unsigned short flags)
442{
443  unsigned char *p;
444  int i, found_soa = 0;
445  int qtype, qclass, rdlen;
446  unsigned long ttl, minttl = 0;
447
448  /* there may be more than one question with some questions
449     answered. We don't generate negative entries from those. */
450  if (ntohs(header->ancount) != 0)
451    return;
452
453  if (!(p = skip_questions(header, qlen)))
454    return; /* bad packet */
455
456  /* we first need to find SOA records, to get min TTL, then we
457     add a NEG cache entry for each question. */
458
459  for (i=0; i<ntohs(header->nscount); i++)
460    {
461      if (!extract_name(header, qlen, &p, name, 1))
462	return; /* bad packet */
463
464      GETSHORT(qtype, p);
465      GETSHORT(qclass, p);
466      GETLONG(ttl, p);
467      GETSHORT(rdlen, p);
468
469      if ((qclass == C_IN) && (qtype == T_SOA))
470	{
471	  int dummy;
472	  /* MNAME */
473	  if (!extract_name(header, qlen, &p, name, 1))
474	    return;
475	  /* RNAME */
476	  if (!extract_name(header, qlen, &p, name, 1))
477	    return;
478	  GETLONG(dummy, p); /* SERIAL */
479	  GETLONG(dummy, p); /* REFRESH */
480	  GETLONG(dummy, p); /* RETRY */
481	  GETLONG(dummy, p); /* EXPIRE */
482	  if (!found_soa)
483	    {
484	      found_soa = 1;
485	      minttl = ttl;
486	    }
487	  else if (ttl < minttl)
488	    minttl = ttl;
489	  GETLONG(ttl, p); /* minTTL */
490	  if (ttl < minttl)
491	    minttl = ttl;
492	}
493      else
494	p += rdlen;
495
496      if ((unsigned int)(p - (unsigned char *)header) > qlen)
497	return; /* bad packet */
498    }
499
500  if (!found_soa)
501    return; /* failed to find SOA */
502
503  cache_start_insert();
504
505  p = (unsigned char *)(header+1);
506
507  for (i=0; i<ntohs(header->qdcount); i++)
508    {
509      struct all_addr addr;
510      int is_arpa;
511
512      if (!extract_name(header, qlen, &p, name, 1))
513	return; /* bad packet */
514
515      GETSHORT(qtype, p);
516      GETSHORT(qclass, p);
517
518      if (qclass == C_IN && qtype == T_PTR && (is_arpa = in_arpa_name_2_addr(name, &addr)))
519	cache_insert(name, &addr, now, minttl , is_arpa | F_REVERSE | flags);
520      else if (qclass == C_IN && qtype == T_A)
521	cache_insert(name, NULL, now, minttl, F_IPV4 | F_FORWARD | flags);
522#ifdef HAVE_IPV6
523      else if (qclass == C_IN && qtype == T_AAAA)
524	cache_insert(name, NULL, now, minttl, F_IPV6 | F_FORWARD | flags);
525#endif
526    }
527
528  cache_end_insert();
529}
530
531static void dns_doctor(HEADER *header, struct doctor *doctor, struct in_addr *addr)
532{
533  for (; doctor; doctor = doctor->next)
534    if (is_same_net(doctor->in, *addr, doctor->mask))
535      {
536	addr->s_addr &= ~doctor->mask.s_addr;
537	addr->s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
538	/* Since we munged the data, the server it came from is no longer authoritative */
539	header->nscount = htons(0);
540	header->arcount = htons(0);
541	break;
542      }
543}
544
545void extract_addresses(HEADER *header, unsigned int qlen, char *name,
546		       time_t now, struct doctor *doctors)
547{
548  unsigned char *p, *psave, *endrr;
549  int qtype, qclass, rdlen;
550  unsigned long ttl;
551  int i;
552
553  /* skip over questions */
554  if (!(p = skip_questions(header, qlen)))
555    return; /* bad packet */
556
557  cache_start_insert();
558
559  psave = p;
560
561  for (i=0; i<ntohs(header->ancount); i++)
562    {
563      unsigned char *origname = p;
564      if (!extract_name(header, qlen, &p, name, 1))
565	return; /* bad packet */
566
567      GETSHORT(qtype, p);
568      GETSHORT(qclass, p);
569      GETLONG(ttl, p);
570      GETSHORT(rdlen, p);
571
572      endrr = p + rdlen;
573      if ((unsigned int)(endrr - (unsigned char *)header) > qlen)
574	return; /* bad packet */
575
576      if (qclass != C_IN)
577	{
578	  p = endrr;
579	  continue;
580	}
581
582      if (qtype == T_A) /* A record. */
583	{
584	  dns_doctor(header, doctors, (struct in_addr *)p);
585	  cache_insert(name, (struct all_addr *)p, now,
586		       ttl, F_IPV4 | F_FORWARD);
587	}
588#ifdef HAVE_IPV6
589      else if (qtype == T_AAAA) /* IPV6 address record. */
590	cache_insert(name, (struct all_addr *)p, now,
591		     ttl, F_IPV6 | F_FORWARD);
592#endif
593      else if (qtype == T_PTR)
594	{
595  /* PTR record */
596	  struct all_addr addr;
597	  int name_encoding = in_arpa_name_2_addr(name, &addr);
598	  if (name_encoding)
599	    {
600	      if (!extract_name(header, qlen, &p, name, 1))
601		return; /* bad packet */
602	      cache_insert(name, &addr, now,
603			   ttl, name_encoding | F_REVERSE);
604	    }
605	}
606      else if (qtype == T_CNAME)
607	{
608	  /* CNAME, search whole answer section again */
609	  unsigned char *endrr1;
610	  unsigned long cttl;
611	  int j;
612	  unsigned char *targp = p;
613
614	  p = psave; /* rewind p */
615	  for (j=0; j<ntohs(header->ancount); j++)
616	    {
617	      int res;
618	      unsigned char *tmp = targp;
619	      /* copy since it gets altered by extract_name */
620	      /* get CNAME target each time round */
621	      if (!extract_name(header, qlen, &tmp, name, 1))
622		return; /* bad packet */
623	      /* compare this name with target of CNAME in name buffer */
624	      if (!(res = extract_name(header, qlen, &p, name, 0)))
625		return; /* bad packet */
626
627	      GETSHORT(qtype, p);
628	      GETSHORT(qclass, p);
629	      GETLONG(cttl, p);
630	      GETSHORT(rdlen, p);
631
632	      endrr1 = p+rdlen;
633	      if ((unsigned int)(endrr1 - (unsigned char *)header) > qlen)
634		return; /* bad packet */
635
636	      /* is this RR name same as target of CNAME */
637	      if ((qclass != C_IN) || (res == 2))
638		{
639		  p = endrr1;
640		  continue;
641		}
642
643	      /* match, use name of CNAME, data from this RR
644		 use min TTL of two */
645
646	      if (ttl < cttl)
647		cttl = ttl;
648
649	      /* get orig. name back again */
650	      tmp = origname;
651	      if (!extract_name(header, qlen, &tmp, name, 1))
652		return;
653
654	      if (qtype == T_A) /* A record. */
655		{
656		  dns_doctor(header, doctors, (struct in_addr *)p);
657		  cache_insert(name, (struct all_addr *)p, now,
658			       cttl, F_IPV4 | F_FORWARD);
659		}
660#ifdef HAVE_IPV6
661	      else if (qtype == T_AAAA) /* IPV6 address record. */
662		cache_insert(name, (struct all_addr *)p, now,
663			     cttl, F_IPV6 | F_FORWARD);
664#endif
665	      else if (qtype == T_PTR)
666		{
667		  /* PTR record extract address from CNAME name */
668		  struct all_addr addr;
669		  int name_encoding = in_arpa_name_2_addr(name, &addr);
670		  if (name_encoding)
671		    {
672		      if (!extract_name(header, qlen, &p, name, 1))
673			return; /* bad packet */
674		      cache_insert(name, &addr, now, cttl,
675				   name_encoding | F_REVERSE);
676		    }
677		}
678	      p = endrr1;
679	    }
680	}
681      p = endrr;
682    }
683
684  cache_end_insert();
685}
686
687/* If the packet holds exactly one query
688   return 1 and leave the name from the query in name. */
689
690unsigned short extract_request(HEADER *header,unsigned int qlen, char *name, unsigned short *typep)
691{
692  unsigned char *p = (unsigned char *)(header+1);
693  int qtype, qclass;
694
695  if (typep)
696    *typep = 0;
697
698  if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
699    return 0; /* must be exactly one query. */
700
701  if (!extract_name(header, qlen, &p, name, 1))
702    return 0; /* bad packet */
703
704  GETSHORT(qtype, p);
705  GETSHORT(qclass, p);
706
707  if (qclass == C_IN)
708    {
709      if (typep)
710	*typep = qtype;
711
712      if (qtype == T_A)
713	return F_IPV4;
714      if (qtype == T_AAAA)
715	return F_IPV6;
716      if (qtype == T_ANY)
717	return  F_IPV4 | F_IPV6;
718    }
719
720  return F_QUERY;
721}
722
723
724int setup_reply(HEADER *header, unsigned int qlen,
725		struct all_addr *addrp, unsigned short flags, unsigned long ttl)
726{
727  unsigned char *p = skip_questions(header, qlen);
728
729  header->qr = 1; /* response */
730  header->aa = 0; /* authoritive */
731  header->ra = 1; /* recursion if available */
732  header->tc = 0; /* not truncated */
733  header->nscount = htons(0);
734  header->arcount = htons(0);
735  header->ancount = htons(0); /* no answers unless changed below */
736  if (flags == F_NEG)
737    header->rcode = SERVFAIL; /* couldn't get memory */
738  else if (flags == F_NOERR || flags == F_QUERY)
739    header->rcode = NOERROR; /* empty domain */
740  else if (flags == F_NXDOMAIN)
741    header->rcode = NXDOMAIN;
742  else if (p && flags == F_IPV4)
743    { /* we know the address */
744      header->rcode = NOERROR;
745      header->ancount = htons(1);
746      header->aa = 1;
747      PUTSHORT (sizeof(HEADER) | 0xc000, p);
748      PUTSHORT(T_A, p);
749      PUTSHORT(C_IN, p);
750      PUTLONG(ttl, p); /* TTL */
751      PUTSHORT(INADDRSZ, p);
752      memcpy(p, addrp, INADDRSZ);
753      p += INADDRSZ;
754    }
755#ifdef HAVE_IPV6
756  else if (p && flags == F_IPV6)
757    {
758      header->rcode = NOERROR;
759      header->ancount = htons(1);
760      header->aa = 1;
761      PUTSHORT (sizeof(HEADER) | 0xc000, p);
762      PUTSHORT(T_AAAA, p);
763      PUTSHORT(C_IN, p);
764      PUTLONG(ttl, p); /* TTL */
765      PUTSHORT(IN6ADDRSZ, p);
766      memcpy(p, addrp, IN6ADDRSZ);
767      p += IN6ADDRSZ;
768    }
769#endif
770  else /* nowhere to forward to */
771    header->rcode = REFUSED;
772
773  return p - (unsigned char *)header;
774}
775
776/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
777int check_for_local_domain(char *name, time_t now, struct mx_record *mx)
778{
779  struct crec *crecp;
780
781  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4|F_IPV6)) &&
782      (crecp->flags & (F_HOSTS | F_DHCP)))
783    return 1;
784
785  for (; mx; mx = mx->next)
786    if (hostname_isequal(name, mx->mxname))
787      return 1;
788
789  return 0;
790}
791
792/* Is the packet a reply with the answer address equal to addr?
793   If so mung is into an NXDOMAIN reply and also put that information
794   in the cache. */
795int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
796			     struct bogus_addr *baddr, time_t now)
797{
798  unsigned char *p;
799  int i, qtype, qclass, rdlen;
800  unsigned long ttl;
801  struct bogus_addr *baddrp;
802
803  /* skip over questions */
804  if (!(p = skip_questions(header, qlen)))
805    return 0; /* bad packet */
806
807  for (i=0; i<ntohs(header->ancount); i++)
808    {
809      if (!extract_name(header, qlen, &p, name, 1))
810	return 0; /* bad packet */
811
812      GETSHORT(qtype, p);
813      GETSHORT(qclass, p);
814      GETLONG(ttl, p);
815      GETSHORT(rdlen, p);
816
817      if (qclass == C_IN && qtype == T_A)
818	for (baddrp = baddr; baddrp; baddrp = baddrp->next)
819	  if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
820	    {
821	      /* Found a bogus address. Mangle the packet into an NXDOMAIN reply */
822	      header->aa = 0;
823	      header->ra = 1; /* recursion if available */
824	      header->nscount = htons(0);
825	      header->arcount = htons(0);
826	      header->ancount = htons(0);
827	      header->rcode = NXDOMAIN;
828
829	      cache_start_insert();
830	      cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
831	      cache_end_insert();
832
833	      return 1;
834	    }
835
836      p += rdlen;
837    }
838
839  return 0;
840}
841
842/* return zero if we can't answer from cache, or packet size if we can */
843int answer_request(HEADER *header, char *limit, unsigned int qlen, struct daemon *daemon, time_t now)
844{
845  char *name = daemon->namebuff;
846  unsigned char *p, *ansp, *pheader;
847  int qtype, qclass, is_arpa;
848  struct all_addr addr;
849  unsigned int nameoffset;
850  unsigned short flag;
851  int qdcount = ntohs(header->qdcount);
852  int q, ans, anscount;
853  int dryrun = 0, sec_reqd = 0;
854  struct crec *crecp;
855  int nxdomain, auth;
856
857  if (!qdcount || header->opcode != QUERY )
858    return 0;
859
860  /* If there is an RFC2671 pseudoheader then it will be overwritten by
861     partial replies, so we have to do a dry run to see if we can answer
862     the query. We check to see if the do bit is set, if so we always
863     forward rather than answering from the cache, which doesn't include
864     security information. */
865
866  if (find_pseudoheader(header, qlen, NULL, &pheader))
867    {
868      unsigned short udpsz, ext_rcode, flags;
869      unsigned char *psave = pheader;
870
871      GETSHORT(udpsz, pheader);
872      GETSHORT(ext_rcode, pheader);
873      GETSHORT(flags, pheader);
874
875      sec_reqd = flags & 0x8000; /* do bit */
876
877      /* If our client is advertising a larger UDP packet size
878	 than we allow, trim it so that we don't get an overlarge
879	 response from upstream */
880
881      if (udpsz > daemon->edns_pktsz)
882	PUTSHORT(daemon->edns_pktsz, psave);
883
884      dryrun = 1;
885    }
886
887 rerun:
888  /* determine end of question section (we put answers there) */
889  if (!(ansp = skip_questions(header, qlen)))
890    return 0; /* bad packet */
891
892  /* now process each question, answers go in RRs after the question */
893  p = (unsigned char *)(header+1);
894  nxdomain = 0, auth = 1, anscount = 0;
895
896  for (q=0; q<qdcount; q++)
897    {
898      /* save pointer to name for copying into answers */
899      nameoffset = p - (unsigned char *)header;
900
901      /* now extract name as .-concatenated string into name */
902      if (!extract_name(header, qlen, &p, name, 1))
903	return 0; /* bad packet */
904
905      /* see if it's w.z.y.z.in-addr.arpa format */
906
907      is_arpa = in_arpa_name_2_addr(name, &addr);
908
909      GETSHORT(qtype, p);
910      GETSHORT(qclass, p);
911
912      ans = 0; /* have we answered this question */
913
914      if (qclass == C_CHAOS && qtype == T_TXT)
915	/* special query to get version. */
916	{
917	  ans = 1;
918	  if (!dryrun)
919	    {
920	      int len;
921	      if (hostname_isequal(name, "version.bind"))
922		sprintf(name, "dnsmasq-%s", VERSION);
923	      else if (hostname_isequal(name, "authors.bind"))
924		sprintf(name, "Simon Kelley");
925	      else if (hostname_isequal(name, "copyright.bind"))
926		sprintf(name, COPYRIGHT);
927	      else
928		*name = 0;
929	      len = strlen(name);
930	      PUTSHORT(nameoffset | 0xc000, ansp);
931	      PUTSHORT(T_TXT, ansp);
932	      PUTSHORT(C_CHAOS, ansp);
933	      PUTLONG(0, ansp);
934	      PUTSHORT(len+1, ansp);
935	      *ansp++ = len;
936	      memcpy(ansp, name, len);
937	      ansp += len;
938	      anscount++;
939	    }
940	  }
941      else if (qclass == C_IN)
942	{
943	  if ((daemon->options & OPT_FILTER) &&
944	      (qtype == T_SOA || qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
945	    {
946	      ans = 1;
947	      log_query(F_CONFIG | F_NEG, name, &addr, 0);
948	    }
949	  else
950	    {
951	      if (qtype == T_PTR || qtype == T_ANY)
952		{
953		  if (!(crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
954		    {
955		      if (is_arpa == F_IPV4 && (daemon->options & OPT_BOGUSPRIV) && private_net(&addr))
956			{
957			  /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
958			  ans = 1;
959			  if (!dryrun)
960			    {
961			      log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, name, &addr, 0);
962			      nxdomain = 1;
963			    }
964			}
965		    }
966		  else do
967		    {
968		      /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
969		      if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
970			continue;
971
972		      if (crecp->flags & F_NEG)
973			{
974			  ans = 1;
975			  if (!dryrun)
976			    {
977			      log_query(crecp->flags & ~F_FORWARD, name, &addr, 0);
978			      auth = 0;
979			      if (crecp->flags & F_NXDOMAIN)
980				nxdomain = 1;
981			    }
982			}
983		      else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
984			{
985			  ans = 1;
986			  if (!dryrun)
987			    {
988			      unsigned long ttl;
989			      /* Return 0 ttl for DHCP entries, which might change
990				 before the lease expires. */
991			      if  (crecp->flags & (F_IMMORTAL | F_DHCP))
992				ttl = daemon->local_ttl;
993			      else
994				ttl = crecp->ttd - now;
995
996			      if (!(crecp->flags & (F_HOSTS | F_DHCP)))
997				auth = 0;
998
999			      ansp = add_text_record(nameoffset, ansp, ttl, 0, T_PTR,
1000						     cache_get_name(crecp));
1001
1002			      log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 0);
1003			      anscount++;
1004
1005			      /* if last answer exceeded packet size, give up */
1006			      if (((unsigned char *)limit - ansp) < 0)
1007				return 0;
1008			    }
1009			}
1010		    } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
1011		}
1012
1013	      for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
1014		{
1015		  unsigned short type = T_A;
1016		  int addrsz = INADDRSZ;
1017
1018		  if (flag == F_IPV6)
1019		    {
1020#ifdef HAVE_IPV6
1021		      type = T_AAAA;
1022		      addrsz = IN6ADDRSZ;
1023#else
1024		      break;
1025#endif
1026		    }
1027
1028		  if (qtype != type && qtype != T_ANY)
1029		    continue;
1030
1031		  crecp = NULL;
1032		  while ((crecp = cache_find_by_name(crecp, name, now, flag)))
1033		    {
1034		      /* don't answer wildcard queries with data not from /etc/hosts
1035			 or DHCP leases */
1036		      if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
1037			continue;
1038
1039		      if (crecp->flags & F_NEG)
1040			{
1041			  ans = 1;
1042			  if (!dryrun)
1043			    {
1044			      log_query(crecp->flags, name, NULL, 0);
1045			      auth = 0;
1046			      if (crecp->flags & F_NXDOMAIN)
1047				nxdomain = 1;
1048			    }
1049			}
1050		      else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
1051			{
1052			  ans = 1;
1053			  if (!dryrun)
1054			    {
1055			      unsigned long ttl;
1056
1057			      if  (crecp->flags & (F_IMMORTAL | F_DHCP))
1058				ttl = daemon->local_ttl;
1059			      else
1060				ttl = crecp->ttd - now;
1061
1062			      if (!(crecp->flags & (F_HOSTS | F_DHCP)))
1063				auth = 0;
1064			      log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr, 0);
1065
1066			      /* copy question as first part of answer (use compression) */
1067			      PUTSHORT(nameoffset | 0xc000, ansp);
1068			      PUTSHORT(type, ansp);
1069			      PUTSHORT(C_IN, ansp);
1070			      PUTLONG(ttl, ansp); /* TTL */
1071
1072			      PUTSHORT(addrsz, ansp);
1073			      memcpy(ansp, &crecp->addr, addrsz);
1074			      ansp += addrsz;
1075			      anscount++;
1076
1077			      if (((unsigned char *)limit - ansp) < 0)
1078				return 0;
1079			    }
1080			}
1081		    }
1082		}
1083
1084	      if (qtype == T_MX || qtype == T_ANY)
1085		{
1086		  struct mx_record *mx;
1087		  for (mx = daemon->mxnames; mx; mx = mx->next)
1088		    if (hostname_isequal(name, mx->mxname))
1089		      break;
1090		  if (mx)
1091		    {
1092		      ans = 1;
1093		      if (!dryrun)
1094			{
1095			  ansp = add_text_record(nameoffset, ansp, daemon->local_ttl, 1, T_MX,
1096						 mx->mxtarget ? mx->mxtarget : daemon->mxtarget);
1097			  anscount++;
1098			}
1099		    }
1100		  else if ((daemon->options & (OPT_SELFMX | OPT_LOCALMX)) &&
1101			   cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
1102		    {
1103		      ans = 1;
1104		      if (!dryrun)
1105			{
1106			  ansp = add_text_record(nameoffset, ansp, daemon->local_ttl, 1, T_MX,
1107						 (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget);
1108			  anscount++;
1109			}
1110		    }
1111		}
1112
1113	      if (qtype == T_MAILB)
1114		ans = 1, nxdomain = 1;
1115
1116	    }
1117	}
1118
1119      if (!ans || ((unsigned char *)limit - ansp) < 0)
1120	return 0; /* failed to answer a question */
1121    }
1122
1123  if (dryrun)
1124    {
1125      dryrun = 0;
1126      goto rerun;
1127    }
1128
1129  /* done all questions, set up header and return length of result */
1130  header->qr = 1; /* response */
1131  header->aa = auth; /* authoritive - only hosts and DHCP derived names. */
1132  header->ra = 1; /* recursion if available */
1133  header->tc = 0; /* truncation */
1134  if (anscount == 0 && nxdomain)
1135    header->rcode = NXDOMAIN;
1136  else
1137    header->rcode = NOERROR; /* no error */
1138  header->ancount = htons(anscount);
1139  header->nscount = htons(0);
1140  header->arcount = htons(0);
1141  return ansp - (unsigned char *)header;
1142}
1143
1144/* foxconn wklin added start, 09/05/2007 @mpoe */
1145#ifdef MULTIPLE_PPPOE
1146typedef struct {
1147    int param_count;
1148    int param_len[32];
1149    void *param[32];
1150} acos_t;
1151
1152unsigned long acos_ip = 0 ;
1153static void acos_set_ipaddr(struct in_addr *p)
1154{
1155    acos_t param;
1156    int fd;
1157    unsigned long refresh_tick = 0;
1158    unsigned long ipaddr = 0;
1159
1160    fd = open("/dev/acos_nat_cli", O_RDWR);
1161    if (!fd)
1162        return;
1163
1164    ipaddr = ntohl(p->s_addr);
1165    memset((char *)&param, 0, sizeof(acos_t));
1166    param.param_count = 2;
1167    param.param[0] = (void *)&ipaddr;
1168    param.param_len[0] = sizeof(unsigned long);
1169    param.param[1] = (void *)&refresh_tick;
1170    param.param_len[1] = sizeof(unsigned long);
1171    /* Foxconn modified by Max Ding, 01/13/2009 for multi-language */
1172    //if (0 > ioctl(fd, _IOR(120, 98, char *), &param))
1173    if (0 > ioctl(fd, _IOR(100, 110, char *), &param))
1174        fprintf(stderr, "error setting ipaddress %08x.\n", ipaddr);
1175
1176    close(fd);
1177    return;
1178}
1179
1180void extract_set_addr(HEADER *header, unsigned int qlen)
1181{
1182    unsigned char *p, *psave, *endrr;
1183    int qtype, qclass, rdlen;
1184    unsigned long ttl;
1185    int i;
1186
1187    unsigned long *pTTL;
1188
1189    /* skip over questions */
1190    if (!(p = skip_questions(header, qlen)))
1191        return; /* bad packet */
1192
1193    psave = p;
1194
1195    for (i=0; i<ntohs(header->ancount); i++)
1196    {
1197        unsigned char name[256];
1198        if (!extract_name(header, qlen, &p, &name[0], 1))
1199          return; /* bad packet */
1200
1201        GETSHORT(qtype, p);
1202        GETSHORT(qclass, p);
1203        pTTL = p;
1204        GETLONG(ttl, p);
1205        GETSHORT(rdlen, p);
1206
1207        endrr = p + rdlen;
1208        if ((unsigned int)(endrr - (unsigned char *)header) > qlen)
1209            return;
1210
1211        if (qclass != C_IN)
1212	    {
1213	        p = endrr;
1214	        continue;
1215	    }
1216
1217        if (qtype == T_A) { /* A record. */
1218            *pTTL = 0;
1219            /*   Add a unsigned long variable acos_ip to avoid the 4-bytes align issue.      weal @ April 14 */
1220            memcpy(&acos_ip, p, 4);
1221            acos_set_ipaddr((struct in_addr *)&acos_ip);
1222        }
1223        p = endrr;
1224    }
1225    return;
1226}
1227#endif /* MULTIPLE_PPPOE */
1228/* foxconn wklin added end, 09/05/2007 @mpoe */
1229