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