1: /* 2: * Copyright (c) 1986, 1988 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)ns_resp.c 4.50 (Berkeley) 4/7/88"; 15: #endif /* not lint */ 16: 17: #include <stdio.h> 18: #include <sys/param.h> 19: #include <sys/time.h> 20: #include <sys/socket.h> 21: #include <sys/file.h> 22: #include <netinet/in.h> 23: #include <syslog.h> 24: #include <arpa/nameser.h> 25: #include "ns.h" 26: #include "db.h" 27: 28: extern int debug; 29: extern FILE *ddt; 30: extern int errno; 31: extern u_char *dnptrs[]; 32: extern time_t retrytime(); 33: extern struct fwdinfo *fwdtab; 34: extern struct sockaddr_in from_addr; /* Source addr of last packet */ 35: extern int needs_prime_cache; 36: extern int priming; 37: 38: struct qinfo *sysquery(); 39: 40: ns_resp(msg, msglen) 41: u_char *msg; 42: int msglen; 43: { 44: register struct qinfo *qp; 45: register HEADER *hp; 46: register struct qserv *qs; 47: register struct databuf *ns, *ns2; 48: register u_char *cp; 49: struct databuf *nsp[NSMAX], **nspp; 50: int i, c, n, ancount, aucount, nscount, arcount; 51: int type, class, dbflags; 52: int cname = 0; /* flag for processing cname response */ 53: int count, founddata, foundname; 54: int buflen; 55: int newmsglen; 56: char name[MAXDNAME], *dname; 57: char *fname; 58: u_char newmsg[BUFSIZ]; 59: u_char **dpp, *tp; 60: time_t rtrip; 61: 62: struct hashbuf *htp; 63: struct namebuf *np; 64: struct netinfo *lp; 65: extern struct netinfo *local(); 66: extern int nsid; 67: extern int addcount; 68: 69: #ifdef STATS 70: stats[S_RESPONSES].cnt++; 71: #endif 72: hp = (HEADER *) msg; 73: if ((qp = qfindid(hp->id)) == NULL ) { 74: #ifdef DEBUG 75: if (debug > 1) 76: fprintf(ddt,"DUP? dropped (id %d)\n", ntohs(hp->id)); 77: #endif 78: #ifdef STATS 79: stats[S_DUPRESP].cnt++; 80: #endif 81: return; 82: } 83: 84: #ifdef DEBUG 85: if (debug >= 2) 86: fprintf(ddt,"%s response nsid=%d id=%d\n", 87: qp->q_system ? "SYSTEM" : "USER", 88: ntohs(qp->q_nsid), ntohs(qp->q_id)); 89: #endif 90: 91: /* 92: * Here we handle bad responses from servers. 93: * Several possibilities come to mind: 94: * The server is sick and returns SERVFAIL 95: * The server returns some garbage opcode (its sick) 96: * The server can't understand our query and return FORMERR 97: * In all these cases, we simply drop the packet and force 98: * a retry. This will make him look bad due to unresponsiveness. 99: * Be sure not to include authoritative NXDOMAIN 100: */ 101: if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN) 102: || (hp->rcode == NXDOMAIN && !hp->aa) 103: || hp->opcode != QUERY) { 104: #ifdef DEBUG 105: if (debug >= 2) 106: fprintf(ddt,"resp: error (ret %d, op %d), dropped\n", 107: hp->rcode, hp->opcode); 108: #endif 109: #ifdef STATS 110: stats[S_BADRESPONSES].cnt++; 111: #endif 112: return; 113: } 114: 115: #ifdef ALLOW_UPDATES 116: if ( (hp->rcode == NOERROR) && 117: (hp->opcode == UPDATEA || hp->opcode == UPDATED || 118: hp->opcode == UPDATEDA || hp->opcode == UPDATEM || 119: hp->opcode == UPDATEMA) ) { 120: /* 121: * Update the secondary's copy, now that the primary 122: * successfully completed the update. Zone doesn't matter 123: * for dyn. update -- doupdate calls findzone to find it 124: */ 125: doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + sizeof(HEADER), 126: 0, (struct databuf *)0, 0); 127: #ifdef DEBUG 128: if (debug >= 3) 129: fprintf(ddt,"resp: leaving, UPDATE*\n"); 130: #endif 131: /* return code filled in by doupdate */ 132: goto return_msg; 133: } 134: #endif ALLOW_UPDATES 135: 136: /* 137: * If we were using nameservers, find the qinfo pointer and update 138: * the rtt and fact that we have called on this server before. 139: */ 140: if (qp->q_fwd == (struct fwdinfo *)0) { 141: struct timeval *stp; 142: 143: for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) 144: if (bcmp((char *)&qs->ns_addr.sin_addr, 145: &from_addr.sin_addr, sizeof(struct in_addr)) == 0) 146: break; 147: if (n >= qp->q_naddr) { 148: #ifdef DEBUG 149: if (debug) 150: fprintf(ddt, "Response from unexpected source %s\n", 151: inet_ntoa(from_addr.sin_addr)); 152: #endif DEBUG 153: #ifdef STATS 154: stats[S_MARTIANS].cnt++; 155: #endif 156: /* assume response to have come from last query */ 157: qs = &qp->q_addr[qp->q_curaddr]; 158: } 159: stp = &qs->stime; 160: 161: /* Handle response from different (untried) interface */ 162: if (stp->tv_sec == 0) { 163: ns = qs->ns; 164: while (qs > qp->q_addr && 165: (qs->stime.tv_sec == 0 || qs->ns != ns)) 166: qs--; 167: *stp = qs->stime; 168: #ifdef DEBUG 169: if (debug) 170: fprintf(ddt, 171: "Response from unused address %s, assuming %s\n", 172: inet_ntoa(from_addr.sin_addr), 173: inet_ntoa(qs->ns_addr.sin_addr)); 174: #endif DEBUG 175: } 176: 177: /* compute query round trip time */ 178: rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 + 179: (tt.tv_usec - stp->tv_usec) / 1000); 180: 181: #ifdef DEBUG 182: if (debug > 2) 183: fprintf(ddt,"stime %ld/%ld now %ld/%ld rtt %ld\n", 184: stp->tv_sec, stp->tv_usec, 185: tt.tv_sec, tt.tv_usec, rtrip); 186: #endif 187: ns = qs->nsdata; 188: /* 189: * Don't update nstime if this doesn't look 190: * like an address databuf now. XXX 191: */ 192: if (ns->d_type == T_A && ns->d_class == qs->ns->d_class) { 193: if (ns->d_nstime == 0) 194: ns->d_nstime = rtrip; 195: else 196: ns->d_nstime = ns->d_nstime * ALPHA + 197: (1-ALPHA) * rtrip; 198: /* prevent floating point overflow, limit to 1000 sec */ 199: if (ns->d_nstime > 1000000L) 200: ns->d_nstime = 1000000L; 201: } 202: 203: /* 204: * Record the source so that we do not use this NS again. 205: */ 206: if(qp->q_nusedns < NSMAX) { 207: qp->q_usedns[qp->q_nusedns++] = qs->ns; 208: #ifdef DEBUG 209: if(debug > 1) 210: fprintf(ddt, "NS #%d addr %s used, rtt %Ld\n", 211: n, inet_ntoa(qs->ns_addr.sin_addr), 212: ns->d_nstime); 213: #endif DEBUG 214: } 215: 216: /* 217: * Penalize those who had earlier chances but failed 218: * by multiplying round-trip times by BETA (>1). 219: * Improve nstime for unused addresses by applying GAMMA. 220: * The GAMMA factor makes unused entries slowly 221: * improve, so they eventually get tried again. 222: * GAMMA should be slightly less than 1. 223: * Watch out for records that may have timed out 224: * and are no longer the correct type. XXX 225: */ 226: 227: for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) { 228: ns2 = qs->nsdata; 229: if (ns2 == ns) 230: continue; 231: if (ns2->d_type != T_A || 232: ns2->d_class != qs->ns->d_class) /* XXX */ 233: continue; 234: if (qs->stime.tv_sec) { 235: if (ns2->d_nstime == 0) 236: ns2->d_nstime = rtrip * BETA; 237: else 238: ns2->d_nstime = 239: ns2->d_nstime * BETA + (1-ALPHA) * rtrip; 240: if (ns2->d_nstime > 1000000L) 241: ns2->d_nstime = 1000000L; 242: } else 243: ns2->d_nstime = ns2->d_nstime * GAMMA; 244: #ifdef DEBUG 245: if(debug > 1) 246: fprintf(ddt, "NS #%d %s rtt now %ld\n", n, 247: inet_ntoa(qs->ns_addr.sin_addr), 248: ns2->d_nstime); 249: #endif DEBUG 250: } 251: } 252: 253: /* 254: * Skip query section 255: */ 256: addcount = 0; 257: cp = msg + sizeof(HEADER); 258: dpp = dnptrs; 259: *dpp++ = msg; 260: if ((*cp & INDIR_MASK) == 0) 261: *dpp++ = cp; 262: *dpp = NULL; 263: if (hp->qdcount) { 264: n = dn_skipname(cp, msg + msglen); 265: if (n <= 0) 266: goto formerr; 267: cp += n; 268: GETSHORT(type, cp); 269: GETSHORT(class, cp); 270: if (cp - msg > msglen) 271: goto formerr; 272: } 273: 274: /* 275: * Save answers, authority, and additional records for future use. 276: */ 277: ancount = ntohs(hp->ancount); 278: aucount = ntohs(hp->nscount); 279: arcount = ntohs(hp->arcount); 280: nscount = 0; 281: tp = cp; 282: #ifdef DEBUG 283: if (debug >= 3) 284: fprintf(ddt,"resp: ancount %d, aucount %d, arcount %d\n", 285: ancount, aucount, arcount); 286: #endif 287: 288: /* 289: * If there's an answer, check if it's a CNAME response; 290: * if no answer but aucount > 0, see if there is an NS 291: * or just an SOA. (NOTE: ancount might be 1 with a CNAME, 292: * and NS records may still be in the authority section; 293: * we don't bother counting them, as we only use nscount 294: * if ancount == 0.) 295: */ 296: if (ancount == 1 || (ancount == 0 && aucount > 0)) { 297: c = aucount; 298: do { 299: if (tp - msg >= msglen) 300: goto formerr; 301: n = dn_skipname(tp, msg + msglen); 302: if (n <= 0) 303: goto formerr; 304: tp += n; /* name */ 305: GETSHORT(i, tp); /* type */ 306: tp += sizeof(u_short); /* class */ 307: tp += sizeof(u_long); /* ttl */ 308: GETSHORT(count, tp); /* dlen */ 309: if (tp - msg > msglen - count) 310: goto formerr; 311: tp += count; 312: if (ancount && i == T_CNAME) { 313: cname++; 314: #ifdef DEBUG 315: if (debug) 316: fprintf(ddt,"CNAME - needs more processing\n"); 317: #endif 318: if (!qp->q_cmsglen) { 319: qp->q_cmsg = qp->q_msg; 320: qp->q_cmsglen = qp->q_msglen; 321: qp->q_msg = NULL; 322: qp->q_msglen = 0; 323: } 324: } 325: /* 326: * See if authority record is a nameserver. 327: */ 328: if (ancount == 0 && i == T_NS) 329: nscount++; 330: } while (--c > 0); 331: tp = cp; 332: } 333: 334: /* 335: * Add the info received in the response to the Data Base 336: */ 337: c = ancount + aucount + arcount; 338: #ifdef notdef 339: /* 340: * If the request was for a CNAME that doesn't exist, 341: * but the name is valid, fetch any other data for the name. 342: * DON'T do this now, as it will requery if data are already 343: * in the cache (maybe later with negative caching). 344: */ 345: if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR && 346: !qp->q_system) { 347: #ifdef DEBUG 348: if (debug >= 3) 349: fprintf(ddt,"resp: leaving, no CNAME\n"); 350: #endif 351: /* Cause us to put it in the cache later */ 352: prime(class, T_ANY, qp); 353: 354: /* Nothing to store, just give user the answer */ 355: goto return_msg; 356: } 357: #endif /* notdef */ 358: 359: nspp = nsp; 360: if (qp->q_system) 361: dbflags = DB_NOTAUTH | DB_NODATA; 362: else 363: dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS; 364: for (i = 0; i < c; i++) { 365: struct databuf *ns3; 366: 367: if (cp >= msg + msglen) 368: goto formerr; 369: ns3 = 0; 370: if ((n = doupdate(msg, msglen, cp, 0, &ns3, dbflags)) < 0) { 371: #ifdef DEBUG 372: if (debug) 373: fprintf(ddt,"resp: leaving, doupdate failed\n"); 374: #endif 375: /* return code filled in by doupdate */ 376: goto return_msg; 377: } 378: /* 379: * Remember nameservers from the authority section 380: * for referrals. 381: * (This is usually overwritten by findns below(?). XXX 382: */ 383: if (ns3 && i >= ancount && i < ancount + aucount && 384: nspp < &nsp[NSMAX-1]) 385: *nspp++ = ns3; 386: cp += n; 387: } 388: 389: if (qp->q_system && ancount) { 390: if (qp->q_system == PRIMING_CACHE) 391: check_root(); 392: #ifdef DEBUG 393: if (debug > 2) 394: fprintf(ddt,"resp: leaving, SYSQUERY ancount %d\n", ancount); 395: #endif 396: qremove(qp); 397: return; 398: } 399: 400: if (cp > msg + msglen) 401: goto formerr; 402: 403: /* 404: * If there are addresses and this is a local query, 405: * sort them appropriately for the local context. 406: */ 407: if (ancount > 1 && (lp = local(&qp->q_from)) != NULL) 408: sort_response(tp, ancount, lp, msg + msglen); 409: 410: /* 411: * An answer to a C_ANY query or a successful answer to a 412: * regular query with no indirection, then just return answer. 413: */ 414: if ((type == C_ANY && ancount) || 415: (!cname && !qp->q_cmsglen && ancount)) { 416: #ifdef DEBUG 417: if (debug >= 3) 418: fprintf(ddt,"resp: got as much answer as there is\n"); 419: #endif 420: goto return_msg; 421: } 422: 423: /* 424: * Eventually we will want to cache this negative answer. 425: */ 426: if (ancount == 0 && (hp->aa || qp->q_fwd) && nscount == 0) { 427: /* We have an authoritative NO */ 428: #ifdef DEBUG 429: if (debug >= 3) 430: fprintf(ddt,"resp: leaving auth NO\n"); 431: #endif 432: if (qp->q_cmsglen) { 433: msg = (u_char *)qp->q_cmsg; 434: msglen = qp->q_cmsglen; 435: hp = (HEADER *)msg; 436: } 437: goto return_msg; 438: } 439: 440: /* 441: * All messages in here need further processing. i.e. they 442: * are either CNAMEs or we got referred again. 443: */ 444: count = 0; 445: founddata = 0; 446: foundname = 0; 447: dname = name; 448: if (!cname && qp->q_cmsglen && ancount) { 449: #ifdef DEBUG 450: if (debug) 451: fprintf(ddt,"Cname second pass\n"); 452: #endif 453: newmsglen = qp->q_cmsglen; 454: bcopy(qp->q_cmsg, newmsg, newmsglen); 455: } else { 456: newmsglen = msglen; 457: bcopy(msg, newmsg, newmsglen); 458: } 459: hp = (HEADER *) newmsg; 460: hp->ancount = 0; 461: hp->nscount = 0; 462: hp->arcount = 0; 463: dnptrs[0] = newmsg; 464: dnptrs[1] = NULL; 465: cp = newmsg + sizeof(HEADER); 466: if (cname) 467: cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ; 468: if ((n = dn_expand(newmsg, newmsg + newmsglen, 469: cp, dname, sizeof(name))) < 0) { 470: #ifdef DEBUG 471: if (debug) 472: fprintf(ddt,"dn_expand failed\n" ); 473: #endif 474: goto servfail; 475: } 476: cp = newmsg + sizeof(HEADER) + 477: (cname ? dn_skipname(cp, newmsg + newmsglen) : n) + QFIXEDSZ; 478: buflen = sizeof(newmsg) - (cp - newmsg); 479: 480: try_again: 481: #ifdef DEBUG 482: if (debug) 483: fprintf(ddt,"resp: nlookup(%s) type=%d\n",dname, type); 484: #endif 485: fname = ""; 486: htp = hashtab; /* lookup relative to root */ 487: np = nlookup(dname, &htp, &fname, 0); 488: #ifdef DEBUG 489: if (debug) 490: fprintf(ddt,"resp: %s '%s' as '%s' (cname=%d)\n", 491: np == NULL ? "missed" : "found", dname, fname, cname); 492: #endif 493: if (np == NULL || fname != dname) 494: goto fetch_ns; 495: 496: foundname++; 497: count = cp - newmsg; 498: n = finddata(np, class, type, hp, &dname, &buflen, &count); 499: if (n == 0) 500: goto fetch_ns; /* NO data available */ 501: cp += n; 502: buflen -= n; 503: hp->ancount += count; 504: if (fname != dname && type != T_CNAME && type != T_ANY) { 505: cname++; 506: goto try_again; 507: } 508: founddata = 1; 509: 510: #ifdef DEBUG 511: if (debug >= 3) { 512: fprintf(ddt,"resp: foundname = %d count = %d ", foundname, count); 513: fprintf(ddt,"founddata = %d cname = %d\n", founddata, cname); 514: } 515: #endif 516: 517: fetch_ns: 518: hp->ancount = htons(hp->ancount); 519: /* 520: * Look for name servers to refer to and fill in the authority 521: * section or record the address for forwarding the query 522: * (recursion desired). 523: */ 524: switch (findns(&np, class, nsp, &count)) { 525: case NXDOMAIN: /* shouldn't happen */ 526: #ifdef DEBUG 527: if (debug >= 3) 528: fprintf(ddt,"req: leaving (%s, rcode %d)\n", 529: dname, hp->rcode); 530: #endif 531: if (!foundname) 532: hp->rcode = NXDOMAIN; 533: if (class != C_ANY) { 534: hp->aa = 1; 535: /* 536: * should return SOA if founddata == 0, 537: * but old named's are confused by an SOA 538: * in the auth. section if there's no error. 539: */ 540: if (foundname == 0 && np) { 541: n = doaddauth(hp, cp, buflen, np, nsp[0]); 542: cp += n; 543: buflen -= n; 544: } 545: } 546: goto return_newmsg; 547: 548: case SERVFAIL: 549: goto servfail; 550: } 551: 552: if (founddata) { 553: hp = (HEADER *)newmsg; 554: n = add_data(np, nsp, cp, buflen); 555: if (n < 0) { 556: hp->tc = 1; 557: n = (-n); 558: } 559: cp += n; 560: buflen -= n; 561: hp->nscount = htons((u_short)count); 562: goto return_newmsg; 563: } 564: 565: /* 566: * If we get here, we don't have the answer yet and are about 567: * to iterate to try and get it. First, infinite loop avoidance. 568: */ 569: if (qp->q_nqueries++ > MAXQUERIES) { 570: #ifdef DEBUG 571: if (debug) 572: fprintf(ddt,"resp: MAXQUERIES exceeded (%s, class %d, type %d)\n", 573: dname, class, type); 574: #endif 575: syslog(LOG_NOTICE, 576: "MAXQUERIES exceeded, possible data loop in resolving (%s)", 577: dname); 578: goto servfail; 579: } 580: 581: /* Reset the query control structure */ 582: qp->q_naddr = 0; 583: qp->q_curaddr = 0; 584: qp->q_fwd = fwdtab; 585: qp->q_addr[0].stime = tt; 586: if (nslookup(nsp, qp) == 0) { 587: #ifdef DEBUG 588: if (debug >= 3) 589: fprintf(ddt,"resp: no addrs found for NS's\n"); 590: #endif 591: goto servfail; 592: } 593: if (cname) { 594: if (qp->q_cname++ == MAXCNAMES) { 595: #ifdef DEBUG 596: if (debug >= 3) 597: fprintf(ddt,"resp: leaving, MAXCNAMES exceeded\n"); 598: #endif 599: goto servfail; 600: } 601: #ifdef DEBUG 602: if (debug) 603: fprintf(ddt,"q_cname = %d\n",qp->q_cname); 604: if (debug >= 3) 605: fprintf(ddt,"resp: building recursive query; nslookup\n"); 606: #endif 607: if (qp->q_msg) 608: (void) free(qp->q_msg); 609: if ((qp->q_msg = malloc(BUFSIZ)) == NULL) { 610: #ifdef DEBUG 611: if (debug) 612: fprintf(ddt,"resp: malloc error\n"); 613: #endif 614: goto servfail; 615: } 616: qp->q_msglen = res_mkquery(QUERY, dname, class, 617: type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ); 618: hp = (HEADER *) qp->q_msg; 619: hp->rd = 0; 620: } else 621: hp = (HEADER *)qp->q_msg; 622: hp->id = qp->q_nsid = htons((u_short)++nsid); 623: unsched(qp); 624: schedretry(qp, retrytime(qp)); 625: #ifdef DEBUG 626: if (debug) 627: fprintf(ddt,"resp: forw -> %s %d (%d) nsid=%d id=%d %ldms\n", 628: inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr), 629: ds, ntohs(Q_NEXTADDR(qp,0)->sin_port), 630: ntohs(qp->q_nsid), ntohs(qp->q_id), 631: qp->q_addr[0].nsdata->d_nstime); 632: if ( debug >= 10) 633: fp_query(msg, ddt); 634: #endif 635: if (sendto(ds, qp->q_msg, qp->q_msglen, 0, 636: (struct sockaddr *)Q_NEXTADDR(qp,0), 637: sizeof(struct sockaddr_in)) < 0) { 638: #ifdef DEBUG 639: if (debug >= 5) 640: fprintf(ddt, "sendto error = %d\n", errno); 641: #endif 642: } 643: #ifdef STATS 644: stats[S_OUTPKTS].cnt++; 645: #endif 646: #ifdef DEBUG 647: if (debug >= 3) 648: fprintf(ddt,"resp: Query sent.\n"); 649: #endif 650: return; 651: 652: formerr: 653: #ifdef DEBUG 654: if (debug) 655: fprintf(ddt,"FORMERR resp() from %s size err %d, msglen %d\n", 656: inet_ntoa(from_addr.sin_addr), 657: cp-msg, msglen); 658: #endif 659: syslog(LOG_INFO, "Malformed response from %s\n", 660: inet_ntoa(from_addr.sin_addr)); 661: #ifdef STATS 662: stats[S_RESPFORMERR].cnt++; 663: #endif 664: return; 665: 666: return_msg: 667: #ifdef STATS 668: stats[S_RESPOK].cnt++; 669: #endif 670: /* The "standard" return code */ 671: hp->qr = 1; 672: hp->id = qp->q_id; 673: hp->rd = 1; 674: hp->ra = 1; 675: (void) send_msg(msg, msglen, qp); 676: qremove(qp); 677: return; 678: 679: return_newmsg: 680: #ifdef STATS 681: stats[S_RESPOK].cnt++; 682: #endif 683: if (addcount) { 684: n = doaddinfo(hp, cp, buflen); 685: cp += n; 686: buflen -= n; 687: } 688: 689: hp->id = qp->q_id; 690: hp->rd = 1; 691: hp->ra = 1; 692: hp->qr = 1; 693: (void) send_msg(newmsg, cp - newmsg, qp); 694: qremove(qp); 695: return; 696: 697: servfail: 698: #ifdef STATS 699: stats[S_RESPFAIL].cnt++; 700: #endif 701: hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg); 702: hp->rcode = SERVFAIL; 703: hp->id = qp->q_id; 704: hp->rd = 1; 705: hp->ra = 1; 706: hp->qr = 1; 707: (void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp); 708: qremove(qp); 709: return; 710: } 711: 712: /* 713: * Decode the resource record 'rrp' and update the database. 714: * If savens is true, record pointer for forwarding queries a second time. 715: */ 716: doupdate(msg, msglen, rrp, zone, savens, flags) 717: char *msg ; 718: u_char *rrp; 719: struct databuf **savens; 720: int msglen, zone, flags; 721: { 722: register u_char *cp; 723: register int n; 724: int class, type, dlen, n1; 725: u_long ttl; 726: struct databuf *dp; 727: char dname[MAXDNAME]; 728: u_char *cp1; 729: u_char data[BUFSIZ]; 730: register HEADER *hp = (HEADER *) msg; 731: 732: #ifdef DEBUG 733: if (debug > 2) 734: fprintf(ddt,"doupdate(zone %d, savens %x, flags %x)\n", 735: zone, savens, flags); 736: #endif 737: 738: cp = rrp; 739: if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0) { 740: hp->rcode = FORMERR; 741: return (-1); 742: } 743: cp += n; 744: GETSHORT(type, cp); 745: GETSHORT(class, cp); 746: GETLONG(ttl, cp); 747: GETSHORT(dlen, cp); 748: #ifdef DEBUG 749: if (debug > 2) 750: fprintf(ddt,"doupdate: dname %s type %d class %d ttl %ld\n", 751: dname, type, class, ttl); 752: #endif 753: /* 754: * Convert the resource record data into the internal 755: * database format. 756: */ 757: switch (type) { 758: case T_A: 759: case T_WKS: 760: case T_HINFO: 761: case T_UINFO: 762: case T_UID: 763: case T_GID: 764: #ifdef ALLOW_T_UNSPEC 765: case T_UNSPEC: 766: #endif ALLOW_T_UNSPEC 767: cp1 = cp; 768: n = dlen; 769: cp += n; 770: break; 771: 772: case T_CNAME: 773: case T_MB: 774: case T_MG: 775: case T_MR: 776: case T_NS: 777: case T_PTR: 778: if ((n = dn_expand(msg, msg + msglen, cp, data, 779: sizeof(data))) < 0) { 780: hp->rcode = FORMERR; 781: return (-1); 782: } 783: cp += n; 784: cp1 = data; 785: n = strlen(data) + 1; 786: break; 787: 788: case T_MINFO: 789: case T_SOA: 790: if ((n = dn_expand(msg, msg + msglen, cp, data, 791: sizeof(data))) < 0) { 792: hp->rcode = FORMERR; 793: return (-1); 794: } 795: cp += n; 796: cp1 = data + (n = strlen(data) + 1); 797: n1 = sizeof(data) - n; 798: if (type == T_SOA) 799: n1 -= 5 * sizeof(u_long); 800: if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) { 801: hp->rcode = FORMERR; 802: return (-1); 803: } 804: cp += n; 805: cp1 += strlen(cp1) + 1; 806: if (type == T_SOA) { 807: bcopy(cp, cp1, n = 5 * sizeof(u_long)); 808: cp += n; 809: cp1 += n; 810: } 811: n = cp1 - data; 812: cp1 = data; 813: break; 814: 815: case T_MX: 816: /* grab preference */ 817: bcopy(cp,data,sizeof(u_short)); 818: cp1 = data + sizeof(u_short); 819: cp += sizeof(u_short); 820: 821: /* get name */ 822: if ((n = dn_expand(msg, msg + msglen, cp, cp1, 823: sizeof(data)-sizeof(u_short))) < 0) 824: return(-1); 825: cp += n; 826: 827: /* compute end of data */ 828: cp1 += strlen(cp1) + 1; 829: /* compute size of data */ 830: n = cp1 - data; 831: cp1 = data; 832: break; 833: 834: default: 835: #ifdef DEBUG 836: if (debug >= 3) 837: fprintf(ddt,"unknown type %d\n", type); 838: #endif 839: return ((cp - rrp) + dlen); 840: } 841: if (n > MAXDATA) { 842: #ifdef DEBUG 843: if (debug) 844: fprintf(ddt, 845: "update type %d: %d bytes is too much data\n", 846: type, n); 847: #endif 848: hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */ 849: return(-1); 850: } 851: 852: #ifdef ALLOW_UPDATES 853: /* 854: * If this is a dynamic update request, process it specially; else, 855: * execute normal update code. 856: */ 857: switch(opcode) { 858: 859: /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */ 860: case UPDATEM: 861: case UPDATEMA: 862: 863: /* 864: * The named code for UPDATED and UPDATEDA is the same except that for 865: * UPDATEDA we we ignore any data that was passed: we just delete all 866: * RRs whose name, type, and class matches 867: */ 868: case UPDATED: 869: case UPDATEDA: 870: if (type == T_SOA) { /* Not allowed */ 871: #ifdef DEBUG 872: if (debug) 873: fprintf(ddt, "UDPATE: REFUSED - SOA delete\n"); 874: #endif 875: hp->rcode = REFUSED; 876: return(-1); 877: } 878: /* 879: * Don't check message length if doing UPDATEM/UPDATEMA, 880: * since the whole message wont have been demarshalled until 881: * we reach the code for UPDATEA 882: */ 883: if ( (opcode == UPDATED) || (opcode == UPDATEDA) ) { 884: if (cp != msg + msglen) { 885: #ifdef DEBUG 886: if (debug) 887: fprintf(ddt,"FORMERR UPDATE message length off\n"); 888: #endif 889: hp->rcode = FORMERR; 890: return(-1); 891: } 892: } 893: if ((zonenum = findzone(dname, class)) == 0) { 894: hp->rcode = NXDOMAIN; 895: return(-1); 896: } 897: if ( (opcode == UPDATED) || (opcode == UPDATEM) ) { 898: /* Make a dp for use in db_update, as old dp */ 899: dp = savedata(class, type, 0, cp1, n); 900: dp->d_zone = zonenum; 901: n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE, 902: hashtab); 903: if (n != OK) { 904: #ifdef DEBUG 905: if (debug) 906: fprintf(ddt,"UPDATE: db_update failed\n"); 907: #endif DEBUG 908: free( (struct databuf *) dp); 909: hp->rcode = NOCHANGE; 910: return(-1); 911: } 912: } else { /* UPDATEDA or UPDATEMA */ 913: int DeletedOne = 0; 914: /* Make a dp for use in db_update, as old dp */ 915: dp = savedata(class, type, 0, NULL, 0); 916: dp->d_zone = zonenum; 917: do { /* Loop and delete all matching RR(s) */ 918: n = db_update(dname, dp, NULL, DB_DELETE, 919: hashtab); 920: if (n != OK) 921: break; 922: DeletedOne++; 923: } while (1); 924: free( (struct databuf *) dp); 925: /* Ok for UPDATEMA not to have deleted any RRs */ 926: if (!DeletedOne && opcode == UPDATEDA) { 927: #ifdef DEBUG 928: if (debug) 929: fprintf(ddt,"UPDATE: db_update failed\n"); 930: #endif DEBUG 931: hp->rcode = NOCHANGE; 932: return(-1); 933: } 934: } 935: if ( (opcode == UPDATED) || (opcode == UPDATEDA) ) 936: return (cp - rrp);; 937: /* 938: * Else unmarshal the RR to be added and continue on to 939: * UPDATEA code for UPDATEM/UPDATEMA 940: */ 941: if ((n = 942: dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) { 943: #ifdef DEBUG 944: if (debug) 945: fprintf(ddt,"FORMERR UPDATE expand name failed\n"); 946: #endif 947: hp->rcode = FORMERR; 948: return(-1); 949: } 950: cp += n; 951: GETSHORT(type, cp); 952: GETSHORT(class, cp); 953: GETLONG(ttl, cp); 954: GETSHORT(n, cp); 955: cp1 = cp; 956: /**** XXX - need bounds checking here ****/ 957: cp += n; 958: 959: case UPDATEA: 960: if (n > MAXDATA) { 961: #ifdef DEBUG 962: if (debug) 963: fprintf(ddt,"UPDATE: too much data\n"); 964: #endif 965: hp->rcode = NOCHANGE; 966: return(-1); 967: } 968: if (cp != msg + msglen) { 969: #ifdef DEBUG 970: if (debug) 971: fprintf(ddt,"FORMERR UPDATE message length off\n"); 972: #endif 973: hp->rcode = FORMERR; 974: return(-1); 975: } 976: if ((zonenum = findzone(dname, class)) == 0) { 977: hp->rcode = NXDOMAIN; 978: return(-1); 979: } 980: dp = savedata(class, type, ttl, cp1, n); 981: dp->d_zone = zonenum; 982: if ((n = db_update(dname, NULL, dp, DB_NODATA, 983: hashtab)) != OK) { 984: #ifdef DEBUG 985: if (debug) 986: fprintf(ddt,"UPDATE: db_update failed\n"); 987: #endif 988: hp->rcode = NOCHANGE; 989: return (-1); 990: } 991: else 992: return (cp - rrp); 993: } 994: #endif ALLOW_UPDATES 995: 996: if (zone == 0) 997: ttl += tt.tv_sec; 998: dp = savedata(class, type, ttl, cp1, n); 999: dp->d_zone = zone; 1000: if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) { 1001: #ifdef DEBUG 1002: if (debug && (n != DATAEXISTS)) 1003: fprintf(ddt,"update failed (%d)\n", n); 1004: else if (debug >= 3) 1005: fprintf(ddt,"update failed (DATAEXISTS)\n"); 1006: #endif 1007: (void) free((char *)dp); 1008: } else if (type == T_NS && savens != NULL) 1009: *savens = dp; 1010: return (cp - rrp); 1011: } 1012: 1013: send_msg(msg, msglen, qp) 1014: char *msg; 1015: int msglen; 1016: struct qinfo *qp; 1017: { 1018: extern struct qinfo *qhead; 1019: #ifdef DEBUG 1020: struct qinfo *tqp; 1021: #endif DEBUG 1022: 1023: if (qp->q_system) 1024: return(1); 1025: #ifdef DEBUG 1026: if (debug) { 1027: fprintf(ddt,"send_msg -> %s (%s %d %d) id=%d\n", 1028: inet_ntoa(qp->q_from.sin_addr), 1029: qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP", qp->q_dfd, 1030: ntohs(qp->q_from.sin_port), 1031: ntohs(qp->q_id)); 1032: } 1033: if (debug>4) 1034: for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) { 1035: fprintf(ddt, "qp %x q_id: %d q_nsid: %d q_msglen: %d ", 1036: tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen); 1037: fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr, 1038: tqp->q_curaddr); 1039: fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next, 1040: qp->q_link); 1041: } 1042: if (debug >= 10) 1043: fp_query(msg, ddt); 1044: #endif DEBUG 1045: if (qp->q_stream == QSTREAM_NULL) { 1046: if (sendto(qp->q_dfd, msg, msglen, 0, 1047: (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) { 1048: #ifdef DEBUG 1049: if (debug) 1050: fprintf(ddt, "sendto error errno= %d\n",errno); 1051: #endif 1052: return(1); 1053: } 1054: #ifdef STATS 1055: stats[S_OUTPKTS].cnt++; 1056: #endif 1057: } else { 1058: (void) writemsg(qp->q_stream->s_rfd, msg, msglen); 1059: qp->q_stream->s_time = tt.tv_sec; 1060: qp->q_stream->s_refcnt--; 1061: } 1062: return(0); 1063: } 1064: 1065: prime(class, type, oqp) 1066: int class, type; 1067: register struct qinfo *oqp; 1068: { 1069: char dname[BUFSIZ]; 1070: 1071: if (oqp->q_msg == NULL) 1072: return; 1073: if (dn_expand(oqp->q_msg, oqp->q_msg + oqp->q_msglen, 1074: oqp->q_msg + sizeof(HEADER), dname, sizeof(dname)) < 0) 1075: return; 1076: #ifdef DEBUG 1077: if (debug >= 2) 1078: fprintf(ddt,"prime: %s\n", dname); 1079: #endif 1080: (void) sysquery(dname, class, type); 1081: } 1082: 1083: 1084: prime_cache() 1085: { 1086: register struct qinfo *qp; 1087: 1088: #ifdef DEBUG 1089: if (debug) 1090: fprintf(ddt,"prime_cache: priming = %d\n", priming); 1091: #endif 1092: #ifdef STATS 1093: stats[S_PRIMECACHE].cnt++; 1094: #endif 1095: if (!priming && fcachetab->h_tab[0] != NULL) { 1096: priming++; 1097: if ((qp = sysquery("", C_IN, T_NS)) == NULL) 1098: priming = 0; 1099: else 1100: qp->q_system = PRIMING_CACHE; 1101: } 1102: needs_prime_cache = 0; 1103: return; 1104: } 1105: 1106: struct qinfo * 1107: sysquery(dname, class, type) 1108: char *dname; 1109: int class, type; 1110: { 1111: extern struct qinfo *qhead; 1112: extern int nsid; 1113: register struct qinfo *qp, *oqp; 1114: register HEADER *hp; 1115: struct namebuf *np; 1116: struct databuf *nsp[NSMAX]; 1117: struct hashbuf *htp; 1118: char *fname; 1119: int count; 1120: 1121: #ifdef DEBUG 1122: if (debug > 2) 1123: fprintf(ddt,"sysquery(%s, %d, %d)\n", dname, class, type); 1124: #endif 1125: #ifdef STATS 1126: stats[S_SYSQUERIES].cnt++; 1127: #endif 1128: htp = hashtab; 1129: if (priming && dname[0] == '\0') 1130: np = NULL; 1131: else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) { 1132: #ifdef DEBUG 1133: if (debug) 1134: fprintf(ddt,"sysquery: nlookup error on %s?\n", dname); 1135: #endif 1136: return(0); 1137: } 1138: 1139: switch (findns(&np, class, nsp, &count)) { 1140: case NXDOMAIN: 1141: case SERVFAIL: 1142: #ifdef DEBUG 1143: if (debug) 1144: fprintf(ddt,"sysquery: findns error on %s?\n", dname); 1145: #endif 1146: return(0); 1147: } 1148: 1149: /* build new qinfo struct */ 1150: qp = qnew(); 1151: qp->q_cmsg = qp->q_msg = NULL; 1152: qp->q_dfd = ds; 1153: qp->q_fwd = fwdtab; 1154: qp->q_addr[0].stime = tt; 1155: qp->q_system++; 1156: 1157: if ((qp->q_msg = malloc(BUFSIZ)) == NULL) { 1158: qfree(qp); 1159: return(0); 1160: } 1161: qp->q_msglen = res_mkquery(QUERY, dname, class, 1162: type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ); 1163: hp = (HEADER *) qp->q_msg; 1164: hp->id = qp->q_nsid = htons((u_short)++nsid); 1165: hp->rd = (qp->q_fwd ? 1 : 0); 1166: 1167: /* First check for an already pending query for this data */ 1168: for (oqp = qhead; oqp!=QINFO_NULL; oqp = oqp->q_link) { 1169: if (oqp != qp && oqp->q_msglen == qp->q_msglen && 1170: bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0) { 1171: #ifdef DEBUG 1172: if (debug >= 3) 1173: fprintf(ddt, "sysquery: duplicate\n"); 1174: #endif 1175: qfree(qp); 1176: return(0); 1177: } 1178: } 1179: 1180: if (nslookup(nsp, qp) == 0) { 1181: #ifdef DEBUG 1182: if (debug) 1183: fprintf(ddt,"resp: no addrs found for NS's\n"); 1184: #endif 1185: qfree(qp); 1186: return(0); 1187: } 1188: 1189: schedretry(qp, retrytime(qp)); 1190: if (qp->q_fwd == 0) 1191: qp->q_addr[0].stime = tt; 1192: 1193: #ifdef DEBUG 1194: if (debug) 1195: fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %ldms\n", 1196: inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr), 1197: qp->q_dfd, ntohs(Q_NEXTADDR(qp,0)->sin_port), 1198: ntohs(qp->q_nsid), ntohs(qp->q_id), 1199: qp->q_addr[0].nsdata->d_nstime); 1200: if ( debug >= 10) 1201: fp_query(qp->q_msg, ddt); 1202: #endif 1203: if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0, 1204: (struct sockaddr *)Q_NEXTADDR(qp,0), 1205: sizeof(struct sockaddr_in)) < 0){ 1206: #ifdef DEBUG 1207: if (debug) 1208: fprintf(ddt, "sendto error errno= %d\n",errno); 1209: #endif 1210: } 1211: #ifdef STATS 1212: stats[S_OUTPKTS].cnt++; 1213: #endif 1214: return(qp); 1215: } 1216: 1217: /* 1218: * Check the list of root servers after receiving a response 1219: * to a query for the root servers. 1220: */ 1221: check_root() 1222: { 1223: register struct databuf *dp, *pdp; 1224: register struct namebuf *np; 1225: int count = 0; 1226: 1227: priming = 0; 1228: for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) 1229: if (np->n_dname[0] == '\0') 1230: break; 1231: if (np == NULL) { 1232: syslog(LOG_ERR, "check_root: Can't find root!\n"); 1233: return; 1234: } 1235: for (dp = np->n_data; dp != NULL; dp = dp->d_next) 1236: if (dp->d_type == T_NS) 1237: count++; 1238: #ifdef DEBUG 1239: if (debug) 1240: fprintf(ddt,"%d root servers\n", count); 1241: #endif 1242: if (count < MINROOTS) { 1243: syslog(LOG_WARNING, 1244: "check_root: %d root servers after query to root server < min", 1245: count); 1246: return; 1247: } 1248: pdp = NULL; 1249: dp = np->n_data; 1250: while (dp != NULL) { 1251: if (dp->d_type == T_NS && dp->d_zone == 0 && 1252: dp->d_ttl < tt.tv_sec) { 1253: #ifdef DEBUG 1254: if (debug) 1255: fprintf(ddt,"deleting old root server '%s'\n", 1256: dp->d_data); 1257: #endif 1258: dp = rm_datum(dp, np, pdp); 1259: /* SHOULD DELETE FROM HINTS ALSO */ 1260: continue; 1261: } 1262: pdp = dp; 1263: dp = dp->d_next; 1264: } 1265: check_ns(); 1266: } 1267: 1268: /* 1269: * Check the root to make sure that for each NS record we have a A RR 1270: */ 1271: check_ns() 1272: { 1273: register struct databuf *dp, *tdp; 1274: register struct namebuf *np, *tnp; 1275: struct hashbuf *htp; 1276: char *dname; 1277: int found_arr; 1278: char *fname; 1279: time_t curtime; 1280: 1281: #ifdef DEBUG 1282: if (debug >= 2) 1283: fprintf(ddt,"check_ns()\n"); 1284: #endif 1285: #ifdef STATS 1286: stats[S_CHECKNS].cnt++; 1287: #endif 1288: 1289: curtime = (u_long) tt.tv_sec; 1290: for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) { 1291: if (np->n_dname[0] != 0) 1292: continue; 1293: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { 1294: if (dp->d_type != T_NS) 1295: continue; 1296: 1297: /* look for A records */ 1298: dname = dp->d_data; 1299: htp = hashtab; 1300: tnp = nlookup(dname, &htp, &fname, 0); 1301: if (tnp == NULL || fname != dname) { 1302: #ifdef DEBUG 1303: if (debug >= 3) 1304: fprintf(ddt,"check_ns: %s: not found %s %x\n", 1305: dname, fname, tnp); 1306: #endif 1307: (void) sysquery(dname, dp->d_class, T_A); 1308: continue; 1309: } 1310: /* look for name server addresses */ 1311: found_arr = 0; 1312: for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) { 1313: if (tdp->d_type != T_A || 1314: tdp->d_class != dp->d_class) 1315: continue; 1316: if ((tdp->d_zone == 0) && 1317: (tdp->d_ttl < curtime)) { 1318: #ifdef DEBUG 1319: if (debug >= 3) 1320: fprintf(ddt,"check_ns: stale entry '%s'\n", 1321: tnp->n_dname); 1322: #endif 1323: /* Cache invalidate the address RR's */ 1324: delete_all(tnp, dp->d_class, T_A); 1325: found_arr = 0; 1326: break; 1327: } 1328: found_arr++; 1329: } 1330: if (!found_arr) 1331: (void) sysquery(dname, dp->d_class, T_A); 1332: } 1333: } 1334: } 1335: 1336: #define MAXCLASS 255 /* belongs elsewhere */ 1337: int norootlogged[MAXCLASS]; 1338: 1339: /* 1340: * Find NS's or an SOA for the given dname (np) and fill in the 1341: * nsp array. Returns OK on success, and SERVFAIL on error. 1342: * We return NXDOMAIN to indicate we are authoritative. 1343: */ 1344: findns(npp, class, nsp, countp) 1345: register struct namebuf **npp; 1346: struct databuf **nsp; 1347: int *countp; 1348: { 1349: register struct namebuf *np = *npp; 1350: register struct databuf *dp; 1351: register struct databuf **nspp; 1352: struct hashbuf *htp = hashtab; 1353: 1354: if (priming && (np == NULL || np->n_dname[0] == '\0')) 1355: htp = fcachetab; 1356: try_again: 1357: if (htp == fcachetab) 1358: needs_prime_cache = 1; 1359: while (np == NULL && htp != NULL) { 1360: #ifdef DEBUG 1361: if (debug > 2) 1362: fprintf(ddt, "findns: using %s\n", htp == hashtab ? 1363: "cache" : "hints"); 1364: #endif 1365: for (np = htp->h_tab[0]; np != NULL; np = np->n_next) 1366: if (np->n_dname[0] == '\0') 1367: break; 1368: htp = (htp == hashtab ? fcachetab : NULL); /* Fallback */ 1369: } 1370: while(np != NULL) { 1371: #ifdef DEBUG 1372: if (debug >= 5) 1373: fprintf(ddt, "findns: np 0x%x\n", np); 1374: #endif 1375: /* Look first for SOA records. */ 1376: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { 1377: if (dp->d_zone != 0 && match(dp, class, T_SOA)) { 1378: #ifdef DEBUG 1379: if (debug >= 3) 1380: fprintf(ddt,"findns: SOA found\n"); 1381: #endif 1382: if (zones[dp->d_zone].z_auth) { 1383: *npp = np; 1384: nsp[0] = dp; 1385: return(NXDOMAIN); 1386: } else 1387: return (SERVFAIL); 1388: } 1389: } 1390: 1391: /* If no SOA records, look for NS records. */ 1392: nspp = &nsp[0]; 1393: *nspp = NULL; 1394: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { 1395: if (dp->d_type != T_NS || 1396: (dp->d_class != class && class != C_ANY)) 1397: continue; 1398: /* 1399: * Don't use records that may become invalid to 1400: * reference later when we do the rtt computation. 1401: * Never delete our safety-belt information! 1402: */ 1403: if ((dp->d_zone == 0) && 1404: (dp->d_ttl < (tt.tv_sec+900)) && 1405: !(dp->d_flags & DB_F_HINT)) { 1406: #ifdef DEBUG 1407: if (debug) 1408: fprintf(ddt,"findns: stale entry '%s'\n", 1409: np->n_dname); 1410: #endif 1411: /* Cache invalidate the NS RR's */ 1412: if (dp->d_ttl < tt.tv_sec) 1413: delete_all(np, class, T_NS); 1414: goto try_parent; 1415: } 1416: if (nspp < &nsp[NSMAX-1]) 1417: *nspp++ = dp; 1418: } 1419: 1420: *countp = nspp - nsp; 1421: if (*countp > 0) { 1422: #ifdef DEBUG 1423: if (debug >= 3) 1424: fprintf(ddt,"findns: %d NS's added for '%s'\n", 1425: *countp, np->n_dname); 1426: #endif 1427: *nspp = NULL; 1428: *npp = np; 1429: return(OK); /* Success, got some NS's */ 1430: } 1431: try_parent: 1432: np = np->n_parent; 1433: } 1434: if (htp) 1435: goto try_again; 1436: #ifdef DEBUG 1437: if (debug) 1438: fprintf(ddt, "findns: No root nameservers for class %d?\n", 1439: class); 1440: #endif 1441: if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) { 1442: norootlogged[class] = 1; 1443: syslog(LOG_ERR, "No root nameservers for class %d\n", class); 1444: } 1445: return(SERVFAIL); 1446: } 1447: 1448: /* 1449: * Extract RR's from the given node that match class and type. 1450: * Return number of bytes added to response. 1451: * If no matching data is found, then 0 is returned. 1452: * Authoritative answer bit is set in response if appropriate. 1453: */ 1454: finddata(np, class, type, hp, dnamep, lenp, countp) 1455: struct namebuf *np; 1456: int class, type; 1457: register HEADER *hp; 1458: char **dnamep; 1459: int *lenp, *countp; 1460: { 1461: register struct databuf *dp; 1462: register char *cp; 1463: int buflen, n, count = 0, foundstale = 0; 1464: 1465: buflen = *lenp; 1466: cp = ((char *)hp) + *countp; 1467: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { 1468: if (!wanted(dp, class, type)) { 1469: #ifdef notdef 1470: if (type == T_CNAME && class == dp->d_class) { 1471: /* any data means no CNAME exists */ 1472: *countp = 0; 1473: return(0); 1474: } 1475: #endif 1476: continue; 1477: } 1478: if (stale(dp)) { 1479: /* 1480: * Don't use stale data. 1481: * Would like to call delete_all here 1482: * and continue, but the data chain would get 1483: * munged; can't restart, as make_rr has side 1484: * effects (leaving pointers in dnptr). 1485: * Just skip this entry for now 1486: * and call delete_all at the end. 1487: */ 1488: #ifdef DEBUG 1489: if (debug >=3) 1490: fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname); 1491: #endif 1492: if (dp->d_zone == 0) 1493: foundstale++; 1494: continue; 1495: } 1496: if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) { 1497: hp->tc = 1; 1498: *countp = count; 1499: return(*lenp - buflen); 1500: } 1501: 1502: cp += n; 1503: buflen -= n; 1504: count++; 1505: #ifdef notdef 1506: /* this isn't right for glue records, aa is set in ns_req */ 1507: if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY) 1508: hp->aa = 1; /* XXX */ 1509: #endif 1510: if (dp->d_type == T_CNAME) { 1511: if (type != T_ANY) { /* or T_NS? */ 1512: *dnamep = dp->d_data; 1513: if (dp->d_zone && zones[dp->d_zone].z_auth && 1514: class != C_ANY) /* XXX */ 1515: hp->aa = 1; /* XXX */ 1516: } 1517: break; 1518: } 1519: } 1520: /* 1521: * Cache invalidate the other RR's of same type 1522: * if some have timed out 1523: */ 1524: if (foundstale) 1525: delete_all(np, class, type); 1526: #ifdef DEBUG 1527: if (debug >=3) 1528: fprintf(ddt,"finddata: added %d class %d type %d RRs\n", 1529: count, class, type); 1530: #endif 1531: *countp = count; 1532: return(*lenp - buflen); 1533: } 1534: 1535: /* 1536: * Do we want this data record based on the class and type? 1537: */ 1538: wanted(dp, class, type) 1539: struct databuf *dp; 1540: int class, type; 1541: { 1542: 1543: #ifdef DEBUG 1544: if (debug > 3) 1545: fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type, 1546: dp->d_class, dp->d_type); 1547: #endif 1548: 1549: if (dp->d_class != class && class != C_ANY) 1550: return (0); 1551: if (type == dp->d_type) 1552: return (1); 1553: switch (dp->d_type) { 1554: case T_ANY: 1555: case T_CNAME: 1556: return (1); 1557: } 1558: switch (type) { 1559: case T_ANY: 1560: return (1); 1561: 1562: case T_MAILB: 1563: switch (dp->d_type) { 1564: case T_MR: 1565: case T_MB: 1566: case T_MG: 1567: case T_MINFO: 1568: return (1); 1569: } 1570: break; 1571: 1572: case T_AXFR: 1573: if (dp->d_type == T_SOA) 1574: return (1); 1575: } 1576: return (0); 1577: } 1578: 1579: /* 1580: * Add RR entries from dpp array to a query/response. 1581: * Return the number of bytes added or negative the amount 1582: * added if truncation was required. Typically you are 1583: * adding NS records to a response. 1584: */ 1585: add_data(np, dpp, cp, buflen) 1586: struct namebuf *np; 1587: struct databuf **dpp; 1588: register char *cp; 1589: int buflen; 1590: { 1591: register struct databuf *dp; 1592: char dname[MAXDNAME]; 1593: register int n, count = 0; 1594: 1595: getname(np, dname, sizeof(dname)); 1596: for(dp = *dpp++; dp != NULL; dp = *dpp++) { 1597: if (stale(dp)) 1598: continue; /* ignore old cache entry */ 1599: if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) 1600: return(-count); /* Truncation */ 1601: cp += n; 1602: buflen -= n; 1603: count += n; 1604: } 1605: return(count); 1606: } 1607: 1608: /* 1609: * This is best thought of as a "cache invalidate" function. 1610: * It is called whenever a piece of data is determined to have 1611: * timed out. It is better to have no information, than to 1612: * have partial information you pass off as complete. 1613: */ 1614: delete_all(np, class, type) 1615: register struct namebuf *np; 1616: int class, type; 1617: { 1618: register struct databuf *dp, *pdp; 1619: 1620: #ifdef DEBUG 1621: if (debug > 2) 1622: fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n", 1623: np->n_dname, np, class, type); 1624: #endif 1625: pdp = NULL; 1626: dp = np->n_data; 1627: while (dp != NULL) { 1628: if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT) 1629: && match(dp, class, type)) { 1630: dp = rm_datum(dp, np, pdp); 1631: continue; 1632: } 1633: pdp = dp; 1634: dp = dp->d_next; 1635: } 1636: }