Annotation of embedaddon/dnsmasq/src/auth.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
1.1 misho 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, or
6: (at your option) version 3 dated 29 June, 2007.
7:
8: This program is distributed in the hope that it will be useful,
9: but WITHOUT ANY WARRANTY; without even the implied warranty of
10: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11: GNU General Public License for more details.
12:
13: You should have received a copy of the GNU General Public License
14: along with this program. If not, see <http://www.gnu.org/licenses/>.
15: */
16:
17: #include "dnsmasq.h"
18:
19: #ifdef HAVE_AUTH
20:
1.1.1.2 ! misho 21: static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
1.1 misho 22: {
1.1.1.2 ! misho 23: struct addrlist *subnet;
1.1 misho 24:
25: for (subnet = zone->subnet; subnet; subnet = subnet->next)
26: {
1.1.1.2 ! misho 27: if (!(subnet->flags & ADDRLIST_IPV6))
1.1 misho 28: {
1.1.1.2 ! misho 29: struct in_addr netmask, addr = addr_u->addr.addr4;
! 30:
! 31: if (!(flag & F_IPV4))
! 32: continue;
1.1 misho 33:
1.1.1.2 ! misho 34: netmask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
1.1 misho 35:
1.1.1.2 ! misho 36: if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
1.1 misho 37: return subnet;
38: }
39: #ifdef HAVE_IPV6
1.1.1.2 ! misho 40: else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
1.1 misho 41: return subnet;
42: #endif
43:
44: }
45: return NULL;
46: }
47:
1.1.1.2 ! misho 48: static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
1.1 misho 49: {
1.1.1.2 ! misho 50: /* No zones specified, no filter */
! 51: if (!zone->subnet)
! 52: return 1;
1.1 misho 53:
1.1.1.2 ! misho 54: return find_subnet(zone, flag, addr_u) != NULL;
1.1 misho 55: }
56:
1.1.1.2 ! misho 57: int in_zone(struct auth_zone *zone, char *name, char **cut)
1.1 misho 58: {
59: size_t namelen = strlen(name);
60: size_t domainlen = strlen(zone->domain);
61:
62: if (cut)
63: *cut = NULL;
64:
65: if (namelen >= domainlen &&
66: hostname_isequal(zone->domain, &name[namelen - domainlen]))
67: {
68:
69: if (namelen == domainlen)
70: return 1;
71:
72: if (name[namelen - domainlen - 1] == '.')
73: {
74: if (cut)
75: *cut = &name[namelen - domainlen - 1];
76: return 1;
77: }
78: }
79:
80: return 0;
81: }
82:
83:
1.1.1.2 ! misho 84: size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
1.1 misho 85: {
86: char *name = daemon->namebuff;
87: unsigned char *p, *ansp;
88: int qtype, qclass;
89: int nameoffset, axfroffset = 0;
90: int q, anscount = 0, authcount = 0;
91: struct crec *crecp;
1.1.1.2 ! misho 92: int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
1.1 misho 93: struct auth_zone *zone = NULL;
1.1.1.2 ! misho 94: struct addrlist *subnet = NULL;
1.1 misho 95: char *cut;
96: struct mx_srv_record *rec, *move, **up;
97: struct txt_record *txt;
98: struct interface_name *intr;
99: struct naptr *na;
100: struct all_addr addr;
101: struct cname *a;
102:
103: if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
104: return 0;
1.1.1.2 ! misho 105:
1.1 misho 106: /* determine end of question section (we put answers there) */
107: if (!(ansp = skip_questions(header, qlen)))
108: return 0; /* bad packet */
109:
110: /* now process each question, answers go in RRs after the question */
111: p = (unsigned char *)(header+1);
112:
113: for (q = ntohs(header->qdcount); q != 0; q--)
114: {
115: unsigned short flag = 0;
116: int found = 0;
117:
118: /* save pointer to name for copying into answers */
119: nameoffset = p - (unsigned char *)header;
120:
121: /* now extract name as .-concatenated string into name */
122: if (!extract_name(header, qlen, &p, name, 1, 4))
123: return 0; /* bad packet */
124:
125: GETSHORT(qtype, p);
126: GETSHORT(qclass, p);
127:
128: if (qclass != C_IN)
129: {
130: auth = 0;
131: continue;
132: }
133:
134: if (qtype == T_PTR)
135: {
136: if (!(flag = in_arpa_name_2_addr(name, &addr)))
137: continue;
138:
1.1.1.2 ! misho 139: if (!local_query)
1.1 misho 140: {
1.1.1.2 ! misho 141: for (zone = daemon->auth_zones; zone; zone = zone->next)
! 142: if ((subnet = find_subnet(zone, flag, &addr)))
! 143: break;
! 144:
! 145: if (!zone)
1.1 misho 146: {
1.1.1.2 ! misho 147: auth = 0;
! 148: continue;
1.1 misho 149: }
1.1.1.2 ! misho 150: }
1.1 misho 151:
1.1.1.2 ! misho 152: intr = NULL;
! 153:
! 154: if (flag == F_IPV4)
! 155: for (intr = daemon->int_names; intr; intr = intr->next)
! 156: {
! 157: struct addrlist *addrlist;
! 158:
! 159: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 160: if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
! 161: break;
! 162:
! 163: if (addrlist)
! 164: break;
! 165: else
! 166: while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
! 167: intr = intr->next;
! 168: }
! 169: #ifdef HAVE_IPV6
! 170: else if (flag == F_IPV6)
! 171: for (intr = daemon->int_names; intr; intr = intr->next)
! 172: {
! 173: struct addrlist *addrlist;
! 174:
! 175: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 176: if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
! 177: break;
! 178:
! 179: if (addrlist)
! 180: break;
! 181: else
! 182: while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
! 183: intr = intr->next;
! 184: }
! 185: #endif
! 186:
! 187: if (intr)
! 188: {
! 189: if (in_zone(zone, intr->name, NULL))
! 190: {
! 191: found = 1;
! 192: log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
! 193: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 194: daemon->auth_ttl, NULL,
! 195: T_PTR, C_IN, "d", intr->name))
! 196: anscount++;
1.1 misho 197: }
198: }
1.1.1.2 ! misho 199:
1.1 misho 200: if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
201: do {
202: strcpy(name, cache_get_name(crecp));
203:
204: if (crecp->flags & F_DHCP && !option_bool(OPT_DHCP_FQDN))
205: {
206: char *p = strchr(name, '.');
207: if (p)
208: *p = 0; /* must be bare name */
209:
210: /* add external domain */
211: strcat(name, ".");
212: strcat(name, zone->domain);
213: log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
214: found = 1;
215: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
216: daemon->auth_ttl, NULL,
217: T_PTR, C_IN, "d", name))
218: anscount++;
219: }
220: else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
221: {
222: log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
223: found = 1;
224: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
225: daemon->auth_ttl, NULL,
226: T_PTR, C_IN, "d", name))
227: anscount++;
228: }
229: else
230: continue;
231:
232: } while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
233:
1.1.1.2 ! misho 234: if (found)
! 235: nxdomain = 0;
! 236: else
! 237: log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
1.1 misho 238:
239: continue;
240: }
241:
242: cname_restart:
243: for (zone = daemon->auth_zones; zone; zone = zone->next)
244: if (in_zone(zone, name, &cut))
245: break;
246:
247: if (!zone)
248: {
249: auth = 0;
250: continue;
251: }
252:
253: for (rec = daemon->mxnames; rec; rec = rec->next)
254: if (!rec->issrv && hostname_isequal(name, rec->name))
255: {
256: nxdomain = 0;
257:
258: if (qtype == T_MX)
259: {
260: found = 1;
261: log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
262: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
263: NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
264: anscount++;
265: }
266: }
267:
268: for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
269: if (rec->issrv && hostname_isequal(name, rec->name))
270: {
271: nxdomain = 0;
272:
273: if (qtype == T_SRV)
274: {
275: found = 1;
276: log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
277: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
278: NULL, T_SRV, C_IN, "sssd",
279: rec->priority, rec->weight, rec->srvport, rec->target))
280:
281: anscount++;
282: }
283:
284: /* unlink first SRV record found */
285: if (!move)
286: {
287: move = rec;
288: *up = rec->next;
289: }
290: else
291: up = &rec->next;
292: }
293: else
294: up = &rec->next;
295:
296: /* put first SRV record back at the end. */
297: if (move)
298: {
299: *up = move;
300: move->next = NULL;
301: }
302:
303: for (txt = daemon->rr; txt; txt = txt->next)
304: if (hostname_isequal(name, txt->name))
305: {
306: nxdomain = 0;
307: if (txt->class == qtype)
308: {
309: found = 1;
310: log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
311: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
312: NULL, txt->class, C_IN, "t", txt->len, txt->txt))
313: anscount++;
314: }
315: }
316:
317: for (txt = daemon->txt; txt; txt = txt->next)
318: if (txt->class == C_IN && hostname_isequal(name, txt->name))
319: {
320: nxdomain = 0;
321: if (qtype == T_TXT)
322: {
323: found = 1;
324: log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
325: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
326: NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
327: anscount++;
328: }
329: }
330:
331: for (na = daemon->naptr; na; na = na->next)
332: if (hostname_isequal(name, na->name))
333: {
334: nxdomain = 0;
335: if (qtype == T_NAPTR)
336: {
337: found = 1;
338: log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
339: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
340: NULL, T_NAPTR, C_IN, "sszzzd",
341: na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
342: anscount++;
343: }
344: }
1.1.1.2 ! misho 345:
! 346: if (qtype == T_A)
! 347: flag = F_IPV4;
! 348:
! 349: #ifdef HAVE_IPV6
! 350: if (qtype == T_AAAA)
! 351: flag = F_IPV6;
! 352: #endif
! 353:
1.1 misho 354: for (intr = daemon->int_names; intr; intr = intr->next)
355: if (hostname_isequal(name, intr->name))
356: {
1.1.1.2 ! misho 357: struct addrlist *addrlist;
! 358:
1.1 misho 359: nxdomain = 0;
1.1.1.2 ! misho 360:
! 361: if (flag)
! 362: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 363: if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
! 364: (local_query || filter_zone(zone, flag, &addrlist->addr)))
! 365: {
! 366: found = 1;
! 367: log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
! 368: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 369: daemon->auth_ttl, NULL, qtype, C_IN,
! 370: qtype == T_A ? "4" : "6", &addrlist->addr))
! 371: anscount++;
! 372: }
! 373: }
1.1 misho 374:
375: for (a = daemon->cnames; a; a = a->next)
376: if (hostname_isequal(name, a->alias) )
377: {
378: log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
379: strcpy(name, a->target);
380: if (!strchr(name, '.'))
381: {
382: strcat(name, ".");
383: strcat(name, zone->domain);
384: }
385: found = 1;
386: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1.1.1.2 ! misho 387: daemon->auth_ttl, &nameoffset,
1.1 misho 388: T_CNAME, C_IN, "d", name))
389: anscount++;
390:
391: goto cname_restart;
392: }
393:
394: if (!cut)
395: {
396: nxdomain = 0;
397:
398: if (qtype == T_SOA)
399: {
1.1.1.2 ! misho 400: auth = soa = 1; /* inhibits auth section */
1.1 misho 401: found = 1;
402: log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
403: }
404: else if (qtype == T_AXFR)
405: {
406: struct iname *peers;
407:
408: if (peer_addr->sa.sa_family == AF_INET)
409: peer_addr->in.sin_port = 0;
410: #ifdef HAVE_IPV6
411: else
412: peer_addr->in6.sin6_port = 0;
413: #endif
414:
415: for (peers = daemon->auth_peers; peers; peers = peers->next)
416: if (sockaddr_isequal(peer_addr, &peers->addr))
417: break;
418:
419: /* Refuse all AXFR unless --auth-sec-servers is set */
420: if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
421: {
422: if (peer_addr->sa.sa_family == AF_INET)
423: inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
424: #ifdef HAVE_IPV6
425: else
426: inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
427: #endif
428:
429: my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
430: return 0;
431: }
432:
1.1.1.2 ! misho 433: auth = 1;
1.1 misho 434: soa = 1; /* inhibits auth section */
435: ns = 1; /* ensure we include NS records! */
436: axfr = 1;
437: found = 1;
438: axfroffset = nameoffset;
439: log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
440: }
441: else if (qtype == T_NS)
442: {
1.1.1.2 ! misho 443: auth = 1;
1.1 misho 444: ns = 1; /* inhibits auth section */
445: found = 1;
446: log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
447: }
448: }
449:
450: if (!option_bool(OPT_DHCP_FQDN) && cut)
451: {
452: *cut = 0; /* remove domain part */
453:
454: if (!strchr(name, '.') && (crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
455: {
456: if (crecp->flags & F_DHCP)
457: do
458: {
459: nxdomain = 0;
460: if ((crecp->flags & flag) &&
1.1.1.2 ! misho 461: (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
1.1 misho 462: {
463: *cut = '.'; /* restore domain part */
464: log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
465: *cut = 0; /* remove domain part */
466: found = 1;
467: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
468: daemon->auth_ttl, NULL, qtype, C_IN,
469: qtype == T_A ? "4" : "6", &crecp->addr))
470: anscount++;
471: }
472: } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
473: }
474:
475: *cut = '.'; /* restore domain part */
476: }
477:
478: if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
479: {
480: if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
481: do
482: {
483: nxdomain = 0;
1.1.1.2 ! misho 484: if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
1.1 misho 485: {
486: log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
487: found = 1;
488: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
489: daemon->auth_ttl, NULL, qtype, C_IN,
490: qtype == T_A ? "4" : "6", &crecp->addr))
491: anscount++;
492: }
493: } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
494: }
495:
496: if (!found)
497: log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
498:
499: }
500:
501: /* Add auth section */
502: if (auth && zone)
503: {
504: char *authname;
505: int newoffset, offset = 0;
506:
507: if (!subnet)
508: authname = zone->domain;
509: else
510: {
511: /* handle NS and SOA for PTR records */
512:
513: authname = name;
514:
1.1.1.2 ! misho 515: if (!(subnet->flags & ADDRLIST_IPV6))
1.1 misho 516: {
1.1.1.2 ! misho 517: in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
1.1 misho 518: char *p = name;
519:
1.1.1.2 ! misho 520: if (subnet->prefixlen >= 24)
1.1 misho 521: p += sprintf(p, "%d.", a & 0xff);
522: a = a >> 8;
1.1.1.2 ! misho 523: if (subnet->prefixlen >= 16 )
1.1 misho 524: p += sprintf(p, "%d.", a & 0xff);
525: a = a >> 8;
526: p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
527:
528: }
529: #ifdef HAVE_IPV6
530: else
531: {
532: char *p = name;
533: int i;
534:
535: for (i = subnet->prefixlen-1; i >= 0; i -= 4)
536: {
1.1.1.2 ! misho 537: int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
1.1 misho 538: p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
539: }
540: p += sprintf(p, "ip6.arpa");
541:
542: }
543: #endif
544: }
545:
546: /* handle NS and SOA in auth section or for explicit queries */
547: newoffset = ansp - (unsigned char *)header;
548: if (((anscount == 0 && !ns) || soa) &&
549: add_resource_record(header, limit, &trunc, 0, &ansp,
550: daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
551: authname, daemon->authserver, daemon->hostmaster,
552: daemon->soa_sn, daemon->soa_refresh,
553: daemon->soa_retry, daemon->soa_expiry,
554: daemon->auth_ttl))
555: {
556: offset = newoffset;
557: if (soa)
558: anscount++;
559: else
560: authcount++;
561: }
562:
563: if (anscount != 0 || ns)
564: {
565: struct name_list *secondary;
566:
567: newoffset = ansp - (unsigned char *)header;
568: if (add_resource_record(header, limit, &trunc, -offset, &ansp,
569: daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
570: {
571: if (offset == 0)
572: offset = newoffset;
573: if (ns)
574: anscount++;
575: else
576: authcount++;
577: }
578:
579: if (!subnet)
580: for (secondary = daemon->secondary_forward_server; secondary; secondary = secondary->next)
581: if (add_resource_record(header, limit, &trunc, offset, &ansp,
582: daemon->auth_ttl, NULL, T_NS, C_IN, "d", secondary->name))
583: {
584: if (ns)
585: anscount++;
586: else
587: authcount++;
588: }
589: }
590:
591: if (axfr)
592: {
593: for (rec = daemon->mxnames; rec; rec = rec->next)
594: if (in_zone(zone, rec->name, &cut))
595: {
596: if (cut)
597: *cut = 0;
598:
599: if (rec->issrv)
600: {
601: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
602: NULL, T_SRV, C_IN, "sssd", cut ? rec->name : NULL,
603: rec->priority, rec->weight, rec->srvport, rec->target))
604:
605: anscount++;
606: }
607: else
608: {
609: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
610: NULL, T_MX, C_IN, "sd", cut ? rec->name : NULL, rec->weight, rec->target))
611: anscount++;
612: }
613:
614: /* restore config data */
615: if (cut)
616: *cut = '.';
617: }
618:
619: for (txt = daemon->rr; txt; txt = txt->next)
620: if (in_zone(zone, txt->name, &cut))
621: {
622: if (cut)
623: *cut = 0;
624:
625: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
626: NULL, txt->class, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
627: anscount++;
628:
629: /* restore config data */
630: if (cut)
631: *cut = '.';
632: }
633:
634: for (txt = daemon->txt; txt; txt = txt->next)
635: if (txt->class == C_IN && in_zone(zone, txt->name, &cut))
636: {
637: if (cut)
638: *cut = 0;
639:
640: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
641: NULL, T_TXT, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
642: anscount++;
643:
644: /* restore config data */
645: if (cut)
646: *cut = '.';
647: }
648:
649: for (na = daemon->naptr; na; na = na->next)
650: if (in_zone(zone, na->name, &cut))
651: {
652: if (cut)
653: *cut = 0;
654:
655: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
656: NULL, T_NAPTR, C_IN, "sszzzd", cut ? na->name : NULL,
657: na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
658: anscount++;
659:
660: /* restore config data */
661: if (cut)
662: *cut = '.';
663: }
664:
665: for (intr = daemon->int_names; intr; intr = intr->next)
1.1.1.2 ! misho 666: if (in_zone(zone, intr->name, &cut))
1.1 misho 667: {
1.1.1.2 ! misho 668: struct addrlist *addrlist;
! 669:
1.1 misho 670: if (cut)
671: *cut = 0;
672:
1.1.1.2 ! misho 673: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 674: if (!(addrlist->flags & ADDRLIST_IPV6) &&
! 675: (local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) &&
! 676: add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
! 677: daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
! 678: anscount++;
! 679:
! 680: #ifdef HAVE_IPV6
! 681: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 682: if ((addrlist->flags & ADDRLIST_IPV6) &&
! 683: (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
! 684: add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
! 685: daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
! 686: anscount++;
! 687: #endif
1.1 misho 688:
689: /* restore config data */
690: if (cut)
691: *cut = '.';
692: }
1.1.1.2 ! misho 693:
1.1 misho 694: for (a = daemon->cnames; a; a = a->next)
695: if (in_zone(zone, a->alias, &cut))
696: {
697: strcpy(name, a->target);
698: if (!strchr(name, '.'))
699: {
700: strcat(name, ".");
701: strcat(name, zone->domain);
702: }
703:
704: if (cut)
705: *cut = 0;
706:
707: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
708: daemon->auth_ttl, NULL,
709: T_CNAME, C_IN, "d", cut ? a->alias : NULL, name))
710: anscount++;
711: }
712:
713: cache_enumerate(1);
714: while ((crecp = cache_enumerate(0)))
715: {
716: if ((crecp->flags & (F_IPV4 | F_IPV6)) &&
717: !(crecp->flags & (F_NEG | F_NXDOMAIN)) &&
718: (crecp->flags & F_FORWARD))
719: {
720: if ((crecp->flags & F_DHCP) && !option_bool(OPT_DHCP_FQDN))
721: {
722: char *cache_name = cache_get_name(crecp);
1.1.1.2 ! misho 723: if (!strchr(cache_name, '.') &&
! 724: (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
1.1 misho 725: {
726: qtype = T_A;
727: #ifdef HAVE_IPV6
728: if (crecp->flags & F_IPV6)
729: qtype = T_AAAA;
730: #endif
731: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
732: daemon->auth_ttl, NULL, qtype, C_IN,
733: (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
734: anscount++;
735: }
736: }
737:
738: if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
739: {
740: strcpy(name, cache_get_name(crecp));
1.1.1.2 ! misho 741: if (in_zone(zone, name, &cut) &&
! 742: (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
1.1 misho 743: {
744: qtype = T_A;
745: #ifdef HAVE_IPV6
746: if (crecp->flags & F_IPV6)
747: qtype = T_AAAA;
748: #endif
749: if (cut)
750: *cut = 0;
751:
752: if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
753: daemon->auth_ttl, NULL, qtype, C_IN,
754: (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
755: anscount++;
756: }
757: }
758: }
759: }
760:
761: /* repeat SOA as last record */
762: if (add_resource_record(header, limit, &trunc, axfroffset, &ansp,
763: daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
764: daemon->authserver, daemon->hostmaster,
765: daemon->soa_sn, daemon->soa_refresh,
766: daemon->soa_retry, daemon->soa_expiry,
767: daemon->auth_ttl))
768: anscount++;
769:
770: }
771:
772: }
773:
774: /* done all questions, set up header and return length of result */
775: /* clear authoritative and truncated flags, set QR flag */
776: header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
1.1.1.2 ! misho 777:
! 778: if (local_query)
! 779: {
! 780: /* set RA flag */
! 781: header->hb4 |= HB4_RA;
! 782: }
! 783: else
! 784: {
! 785: /* clear RA flag */
! 786: header->hb4 &= ~HB4_RA;
! 787: }
1.1 misho 788:
789: /* authoritive */
790: if (auth)
791: header->hb3 |= HB3_AA;
792:
793: /* truncation */
794: if (trunc)
795: header->hb3 |= HB3_TC;
796:
1.1.1.2 ! misho 797: if ((auth || local_query) && nxdomain)
1.1 misho 798: SET_RCODE(header, NXDOMAIN);
799: else
800: SET_RCODE(header, NOERROR); /* no error */
801: header->ancount = htons(anscount);
802: header->nscount = htons(authcount);
803: header->arcount = htons(0);
804: return ansp - (unsigned char *)header;
805: }
806:
807: #endif
808:
809:
810:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>