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