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