|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ns_req.c 4.3 (Berkeley) 5/30/86"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1986 Regents of the University of California ! 7: * All Rights Reserved ! 8: */ ! 9: ! 10: #include <stdio.h> ! 11: #include <sys/types.h> ! 12: #include <sys/uio.h> ! 13: #include <sys/time.h> ! 14: #include <netinet/in.h> ! 15: #include <syslog.h> ! 16: #include <sys/file.h> ! 17: #include <arpa/nameser.h> ! 18: #include "ns.h" ! 19: #include "db.h" ! 20: ! 21: #define NADDRECS 20 ! 22: ! 23: struct addinfo { ! 24: char *a_dname; /* domain name */ ! 25: u_short a_class; /* class for address */ ! 26: }; ! 27: ! 28: struct addinfo addinfo[NADDRECS]; /* additional info records */ ! 29: int addcount; /* number of names in addinfo */ ! 30: ! 31: char *dnptrs[20]; /* ptrs to dnames in message for dn_comp */ ! 32: ! 33: extern char *malloc(); ! 34: extern int errno; ! 35: /* ! 36: * Process request using database; assemble and send response. ! 37: */ ! 38: ns_req(msg, msglen, buflen, qsp, from) ! 39: char *msg; ! 40: int msglen, buflen; ! 41: struct qstream *qsp; ! 42: struct sockaddr_in *from; ! 43: { ! 44: register HEADER *hp; ! 45: register char *cp; ! 46: register struct namebuf *np; ! 47: register struct databuf *dp; ! 48: struct databuf *tmp; ! 49: struct databuf *pdp; ! 50: struct hashbuf *htp; ! 51: struct zoneinfo *zp; ! 52: char *fname; ! 53: char dnbuf[MAXDNAME], *dname; ! 54: char **dpp; ! 55: char *dnp; ! 56: char *newmsg; ! 57: int n, class, type, count, foundname, founddata, cname = 0; ! 58: int newmsglen; ! 59: u_short id; ! 60: struct databuf *nsp[MAXNS], **nspp; ! 61: struct qinfo *qp; ! 62: time_t curtime; ! 63: extern struct qinfo *qhead; ! 64: extern int nsid; ! 65: ! 66: #ifdef DEBUG ! 67: if (debug > 3) { ! 68: fprintf(ddt,"ns_req()\n"); ! 69: fp_query(msg, ddt); ! 70: } ! 71: #endif ! 72: ! 73: hp = (HEADER *) msg; ! 74: if (hp->qr) { ! 75: ns_resp(msg, msglen); ! 76: return; ! 77: } ! 78: ! 79: cp = msg + sizeof(HEADER); ! 80: hp->rcode = NOERROR; ! 81: dpp = dnptrs; ! 82: *dpp++ = msg; ! 83: addcount = 0; ! 84: ! 85: ! 86: switch (hp->opcode) { ! 87: case QUERY: ! 88: if (ntohs(hp->qdcount) != 1 || ! 89: hp->ancount || hp->nscount || hp->arcount) { ! 90: #ifdef DEBUG ! 91: if (debug) ! 92: fprintf(ddt,"FORMERR Query header counts wrong\n"); ! 93: #endif ! 94: hp->qdcount = 0; ! 95: hp->ancount = 0; ! 96: hp->nscount = 0; ! 97: hp->arcount = 0; ! 98: hp->rcode = FORMERR; ! 99: break; ! 100: } ! 101: /* ! 102: * Get domain name, class, and type. ! 103: */ ! 104: if ((*cp & INDIR_MASK) == 0) ! 105: *dpp++ = cp; /* remember name for compression */ ! 106: *dpp = NULL; ! 107: if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, ! 108: sizeof(dnbuf))) < 0) { ! 109: #ifdef DEBUG ! 110: if (debug) ! 111: fprintf(ddt,"FORMERR Query expand name failed\n"); ! 112: #endif ! 113: hp->rcode = FORMERR; ! 114: break; ! 115: } ! 116: cp += n; ! 117: type = getshort(cp); ! 118: cp += sizeof(u_short); ! 119: class = getshort(cp); ! 120: cp += sizeof(u_short); ! 121: if (cp < msg + msglen) { ! 122: #ifdef DEBUG ! 123: if (debug) ! 124: fprintf(ddt,"FORMERR Query message length off\n"); ! 125: #endif ! 126: hp->rcode = FORMERR; ! 127: break; ! 128: } ! 129: #ifdef DEBUG ! 130: if (cp > msg + msglen) ! 131: if (debug > 5) ! 132: fprintf(ddt,"message length > recived message\n"); ! 133: #endif ! 134: #ifdef notdef ! 135: if (!check_class(quest.qtype->class)) { ! 136: if (debug) ! 137: fprintf(ddt,"FORMERR Query class is wrong\n"); ! 138: hp->rcode = FORMERR; ! 139: break; ! 140: } ! 141: if (!check_type(quest.qtype->type)) { ! 142: if (debug) ! 143: fprintf(ddt,"proc_query FORMERR Query type wrong\n"); ! 144: hp->rcode = FORMERR; ! 145: break; ! 146: } ! 147: #endif ! 148: /* ! 149: * Process query. ! 150: */ ! 151: if (type == T_AXFR) { ! 152: /* refuse request if not a TCP connection */ ! 153: if (qsp == QSTREAM_NULL) { ! 154: hp->rcode = REFUSED; ! 155: break; ! 156: } ! 157: /* don't compress names */ ! 158: dnptrs[0] = NULL; ! 159: } ! 160: buflen -= msglen; ! 161: count = 0; ! 162: foundname = 0; ! 163: founddata = 0; ! 164: dname = dnbuf; ! 165: again: ! 166: #ifdef DEBUG ! 167: if (debug) ! 168: fprintf(ddt,"nlookup(%s)\n", dname); ! 169: #endif ! 170: htp = hashtab; /* lookup relative to root */ ! 171: np = nlookup(dname, &htp, &fname, 0); ! 172: /* ! 173: * if nlookup failed to find address then ! 174: * see if there are any '.''s in the name ! 175: * if not then add local domain name to the ! 176: * name and try again. ! 177: */ ! 178: if (np == NULL) { ! 179: fname = ""; ! 180: dnp = &dname[strlen(dname)]; ! 181: if ( index(dname, '.') == NULL) ! 182: for (zp = zones; zp < &zones[nzones]; zp++) { ! 183: if ( zp->z_type == Z_DOMAIN){ ! 184: #ifdef DEBUG ! 185: if (debug >= 5) ! 186: fprintf(ddt,"domain = %s\n", ! 187: zp->z_origin); ! 188: #endif ! 189: (void) strcat(dname,"."); ! 190: (void) strcat(dname,zp->z_origin); ! 191: #ifdef DEBUG ! 192: if (debug) ! 193: fprintf(ddt,"nlookup(%s)\n", dname); ! 194: #endif ! 195: np = nlookup(dname, &htp, &fname, 0); ! 196: if (np != NULL) ! 197: break; ! 198: fname = ""; ! 199: *dnp = '\0'; ! 200: } ! 201: } ! 202: } ! 203: if (fname != dname) { ! 204: #ifdef DEBUG ! 205: if (debug && cname) { ! 206: if (founddata) ! 207: fprintf(ddt,"CNAME with data\n"); ! 208: else ! 209: fprintf(ddt,"CNAME without data %s\n", dname); ! 210: } ! 211: #endif ! 212: goto findns; ! 213: } ! 214: #ifdef DEBUG ! 215: if (debug) ! 216: fprintf(ddt,"found '%s'\n", dname); ! 217: #endif ! 218: foundname++; ! 219: pdp = NULL; ! 220: dp = np->n_data; ! 221: /* look for the data */ ! 222: while (dp != NULL) { ! 223: if (!wanted(dp, class, type)) { ! 224: pdp = dp; ! 225: dp = dp->d_next; ! 226: continue; ! 227: } ! 228: if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) { ! 229: if (n == -1) { ! 230: hp->tc = 1; ! 231: break; ! 232: } ! 233: ! 234: /* delete old cache entry */ ! 235: #ifdef DEBUG ! 236: if (debug) ! 237: fprintf(ddt,"deleting cache entry\n"); ! 238: #endif ! 239: rminv(dp); ! 240: tmp = dp->d_next; ! 241: (void) free((char *)dp); ! 242: dp = tmp; ! 243: if (pdp == NULL) ! 244: np->n_data = dp; ! 245: else ! 246: pdp->d_next = dp; ! 247: continue; ! 248: ! 249: } ! 250: cp += n; ! 251: buflen -= n; ! 252: count++; ! 253: if (dp->d_zone) ! 254: hp->aa = 1; ! 255: if (dp->d_type == T_CNAME) { ! 256: if (type == T_ANY) ! 257: break; ! 258: cname++; ! 259: dname = dp->d_data; ! 260: goto again; ! 261: } ! 262: founddata++; ! 263: pdp = dp; ! 264: dp = dp->d_next; ! 265: } ! 266: #ifdef DEBUG ! 267: if (debug >= 5) { ! 268: fprintf(ddt,"foundname = %d count = %d ", foundname, count); ! 269: fprintf(ddt,"founddata = %d cname = %d\n",founddata, cname); ! 270: } ! 271: #endif ! 272: if (count) { ! 273: hp->ancount = htons((u_short)count); ! 274: if (type == T_AXFR && founddata) { ! 275: #ifdef DEBUG ! 276: if (debug >= 5) ! 277: fprintf(ddt,"doing axfr()\n"); ! 278: #endif ! 279: /* ! 280: * child does the work while ! 281: * the parent continues ! 282: */ ! 283: if (fork() == 0) { ! 284: register FILE *rfp; ! 285: int fdstat; ! 286: ! 287: rfp = fdopen(qsp->s_rfd, "w"); ! 288: setproctitle("zone XFR to", qsp->s_rfd); ! 289: fdstat = fcntl(qsp->s_rfd, F_GETFL, 0); ! 290: if (fdstat != -1) ! 291: (void) fcntl(qsp->s_rfd, F_SETFL, ! 292: fdstat & ~FNDELAY); ! 293: fwritemsg(rfp, msg, cp - msg); ! 294: doaxfr(np, rfp, 1); ! 295: fwritemsg(rfp, msg, cp - msg); ! 296: (void) fflush(rfp); ! 297: exit(0); ! 298: } ! 299: qsp->s_time = tt.tv_sec; ! 300: qsp->s_refcnt--; ! 301: return; ! 302: } ! 303: if (hp->aa) ! 304: break; ! 305: } ! 306: findns: ! 307: /* ! 308: * Look for name servers to refer to and ! 309: * fill in the authority section or record the address ! 310: * for forwarding the query (recursion desired). ! 311: */ ! 312: for (count = 0; ; np = np->n_parent) { ! 313: #ifdef DEBUG ! 314: if (debug >= 5) ! 315: fprintf(ddt,"fname = '%s'\n", fname); ! 316: #endif ! 317: if (*fname == '\0') { ! 318: for (np = hashtab->h_tab[0]; np != NULL; ! 319: np = np->n_next) ! 320: if ( np->n_dname[0] == '\0') ! 321: goto foundns; ! 322: #ifdef DEBUG ! 323: if (debug) ! 324: fprintf(ddt,"No root nameserver?\n"); ! 325: #endif ! 326: syslog(LOG_ERR,"No root Nameserver\n"); ! 327: hp->rcode = SERVFAIL; ! 328: break; ! 329: } ! 330: foundns: ! 331: nspp = nsp; /* record ns records if forwarding */ ! 332: pdp = NULL; ! 333: dp = np->n_data; ! 334: curtime =(u_long) tt.tv_sec; ! 335: while (dp != NULL) { ! 336: if (dp->d_zone && match(dp, class, T_SOA)) { ! 337: if (!foundname) ! 338: hp->rcode = NXDOMAIN; ! 339: hp->aa = 1; ! 340: goto finish; ! 341: } ! 342: if (!match(dp, class, T_NS)) { ! 343: pdp = dp; ! 344: dp = dp->d_next; ! 345: continue; ! 346: } ! 347: if ((dp->d_zone == 0) && ! 348: (dp->d_ttl < curtime)) { ! 349: /* delete old cache entry */ ! 350: #ifdef DEBUG ! 351: if (debug) ! 352: fprintf(ddt,"deleting cache entry\n"); ! 353: #endif ! 354: rminv(dp); ! 355: tmp = dp->d_next; ! 356: (void) free((char *)dp); ! 357: dp = tmp; ! 358: if (pdp == NULL) ! 359: np->n_data = dp; ! 360: else ! 361: pdp->d_next = dp; ! 362: continue; ! 363: } ! 364: if (hp->rd && !founddata) { ! 365: if (nspp < &nsp[MAXNS-1]) ! 366: *nspp++ = dp; ! 367: pdp = dp; ! 368: dp = dp->d_next; ! 369: continue; ! 370: } ! 371: if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) { ! 372: if (n == -1) { ! 373: hp->tc = 1; ! 374: break; ! 375: } ! 376: /* delete old cache entry */ ! 377: #ifdef DEBUG ! 378: if (debug) ! 379: fprintf(ddt,"deleting cache entry\n"); ! 380: #endif ! 381: rminv(dp); ! 382: tmp = dp->d_next; ! 383: (void) free((char *)dp); ! 384: dp = tmp; ! 385: if (pdp == NULL) ! 386: np->n_data = dp; ! 387: else ! 388: pdp->d_next = dp; ! 389: continue; ! 390: } ! 391: cp += n; ! 392: buflen -= n; ! 393: count++; ! 394: pdp = dp; ! 395: dp = dp->d_next; ! 396: } ! 397: if (count && founddata) { ! 398: hp->nscount = htons((u_short)count); ! 399: break; ! 400: } ! 401: if (nspp != nsp) { ! 402: *nspp = NULL; ! 403: if (cname) { ! 404: id = hp->id; ! 405: for (qp = qhead; qp!=QINFO_NULL; ! 406: qp = qp->q_link) { ! 407: if (qp->q_id == id && ! 408: qp->q_cmsglen == msglen && ! 409: bcmp((char *)qp->q_cmsg+2, ! 410: msg+2, msglen-2) == 0) ! 411: return; ! 412: } ! 413: /* build new qinfo struct */ ! 414: qp = qnew(); ! 415: qp->q_naddr = 0; ! 416: if (nslookup(nsp, qp) == 0) { ! 417: #ifdef DEBUG ! 418: if (debug >= 5) ! 419: fprintf(ddt,"none found in nsp\n"); ! 420: #endif ! 421: qfree(qp); ! 422: hp->rcode = SERVFAIL; ! 423: break; ! 424: } ! 425: qp->q_cname++; ! 426: qp->q_stream = qsp; ! 427: qp->q_curaddr = 0; ! 428: qp->q_id = id; ! 429: qp->q_from = *from; ! 430: if ((qp->q_cmsg = malloc((unsigned)msglen)) ! 431: == NULL) { ! 432: #if DEBUG ! 433: if (debug) ! 434: fprintf(ddt,"ns_req: malloc fail\n"); ! 435: #endif ! 436: syslog(LOG_ERR, "ns_req: Out Of Memory"); ! 437: hp->rcode = SERVFAIL; ! 438: break; ! 439: } ! 440: bcopy(msg, qp->q_cmsg, qp->q_cmsglen = msglen); ! 441: if ((newmsg = malloc(BUFSIZ)) == NULL) { ! 442: #if DEBUG ! 443: if (debug) ! 444: fprintf(ddt,"ns_req: malloc error\n"); ! 445: #endif ! 446: syslog(LOG_ERR, "ns_req: Out Of Memory"); ! 447: hp->rcode = SERVFAIL; ! 448: goto finish; ! 449: } ! 450: buflen = BUFSIZ; ! 451: dnptrs[0] = newmsg; ! 452: dnptrs[1] = NULL; ! 453: newmsglen = res_mkquery(QUERY, dname, class, ! 454: type, (char *)NULL, 0, NULL, ! 455: newmsg, buflen); ! 456: qp->q_msg = newmsg; ! 457: qp->q_msglen = newmsglen; ! 458: hp = (HEADER *) newmsg; ! 459: hp->id = qp->q_nsid = htons((u_short)++nsid); ! 460: hp->ancount = 0; ! 461: hp->nscount = 0; ! 462: hp->arcount = 0; ! 463: schedretry(qp, (time_t)RETRYTIME); ! 464: ! 465: #ifdef DEBUG ! 466: if (debug) ! 467: fprintf(ddt,"forw -> %s (%d)\n", ! 468: inet_ntoa(qp->q_addr[0].sin_addr), ! 469: ntohs(qp->q_addr[0].sin_port)); ! 470: if ( debug >= 10) ! 471: fp_query(newmsg, ddt); ! 472: #endif ! 473: if (sendto(ds, newmsg, newmsglen, 0, ! 474: &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0){ ! 475: #ifdef DEBUG ! 476: if (debug) ! 477: fprintf(ddt,"sendto error \n"); ! 478: #endif ! 479: } ! 480: return; ! 481: } ! 482: if ((n = ns_forw(nsp, msg, msglen, from, qsp)) == 0) ! 483: return; ! 484: if (n == -2) { ! 485: hp->rcode = SERVFAIL; ! 486: break; ! 487: } ! 488: } ! 489: if (*fname == '\0') ! 490: break; ! 491: if ((fname = index(fname, '.')) == NULL) ! 492: fname = ""; ! 493: else ! 494: fname++; ! 495: } ! 496: break; ! 497: ! 498: case IQUERY: { ! 499: register struct invbuf *ip; ! 500: register int i; ! 501: int dlen, alen; ! 502: char anbuf[PACKETSZ], *data; ! 503: ! 504: if (ntohs(hp->ancount) != 1 || ! 505: hp->qdcount || hp->nscount || hp->arcount) { ! 506: #ifdef DEBUG ! 507: if (debug) ! 508: fprintf(ddt,"FORMERR IQuery header counts wrong\n"); ! 509: #endif ! 510: hp->qdcount = 0; ! 511: hp->ancount = 0; ! 512: hp->nscount = 0; ! 513: hp->arcount = 0; ! 514: hp->rcode = FORMERR; ! 515: break; ! 516: } ! 517: /* ! 518: * Skip domain name, get class, and type. ! 519: */ ! 520: if ((n = dn_skip(cp)) < 0) { ! 521: #ifdef DEBUG ! 522: if (debug) ! 523: fprintf(ddt,"FORMERR IQuery packet name problem\n"); ! 524: #endif ! 525: hp->rcode = FORMERR; ! 526: break; ! 527: } ! 528: cp += n; ! 529: type = getshort(cp); ! 530: cp += sizeof(u_short); ! 531: class = getshort(cp); ! 532: cp += sizeof(u_short) + sizeof(u_long); ! 533: dlen = getshort(cp); ! 534: cp += sizeof(u_short) + dlen; ! 535: if (cp != msg + msglen) { ! 536: #ifdef DEBUG ! 537: if (debug) ! 538: fprintf(ddt,"FORMERR IQuery message length off\n"); ! 539: #endif ! 540: hp->rcode = FORMERR; ! 541: break; ! 542: } ! 543: /* not all inverse queries are handled. */ ! 544: switch (type) { ! 545: case T_A: ! 546: case T_UID: ! 547: case T_GID: ! 548: break; ! 549: ! 550: default: ! 551: hp->rcode = REFUSED; ! 552: goto finish; ! 553: } ! 554: fname = msg + sizeof(HEADER); ! 555: bcopy(fname, anbuf, alen = cp - fname); ! 556: data = anbuf + alen - dlen; ! 557: cp = fname; ! 558: buflen -= sizeof(HEADER); ! 559: count = 0; ! 560: for (ip = invtab[dhash(data, dlen)]; ip != NULL; ! 561: ip = ip->i_next) { ! 562: for (i = 0; i < INVBLKSZ; i++) { ! 563: if ((np = ip->i_dname[i]) == NULL) ! 564: break; ! 565: #ifdef DEBUG ! 566: if (debug >= 5) ! 567: fprintf(ddt,"dname = %d\n", np->n_dname); ! 568: #endif ! 569: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { ! 570: if (!match(dp, class, type)) ! 571: continue; ! 572: if (dp->d_size != dlen || ! 573: bcmp(dp->d_data, data, dlen)) ! 574: continue; ! 575: getname(np, dnbuf, sizeof(dnbuf)); ! 576: buflen -= QFIXEDSZ; ! 577: if ((n = ! 578: dn_comp(dnbuf, cp, buflen, (char **)NULL, ! 579: (char **)NULL)) < 0) ! 580: { ! 581: hp->tc = 1; ! 582: goto finish; ! 583: } ! 584: cp += n; ! 585: putshort((u_short)dp->d_type, cp); ! 586: cp += sizeof(u_short); ! 587: putshort((u_short)dp->d_class, cp); ! 588: cp += sizeof(u_short); ! 589: buflen -= n; ! 590: count++; ! 591: } ! 592: } ! 593: } ! 594: hp->qdcount = htons((u_short)count); ! 595: if (alen > buflen) { ! 596: hp->tc = 1; ! 597: break; ! 598: } ! 599: bcopy(anbuf, cp, alen); ! 600: cp += alen; ! 601: break; ! 602: } ! 603: ! 604: #ifdef notdef ! 605: case UPDATEA: ! 606: if ((n = ! 607: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) ! 608: { ! 609: #ifdef DEBUG ! 610: if (debug) ! 611: fprintf(ddt,"FORMERR UpdateA expand name failed\n"); ! 612: #endif ! 613: hp->rcode = FORMERR; ! 614: break; ! 615: } ! 616: cp += n; ! 617: type = getshort(cp); ! 618: cp += sizeof(u_short); ! 619: class = getshort(cp); ! 620: cp += sizeof(u_short); ! 621: ttl = getlong(cp); ! 622: cp += sizeof(u_long); ! 623: n = getshort(cp); ! 624: cp += sizeof(u_short); ! 625: if (cp + n != msg + msglen) { ! 626: #ifdef DEBUG ! 627: if (debug) ! 628: fprintf(ddt,"FORMERR UpdateA expand name failed\n"); ! 629: #endif ! 630: hp->rcode = FORMERR; ! 631: break; ! 632: } ! 633: dp = savedata(class, type, ttl, cp, n); ! 634: dp->d_zone = findzone(dnbuf, class); ! 635: if ((n = updatedb(dnbuf, NULL, dp, DB_NODATA)) != NOERROR) { ! 636: #ifdef DEBUG ! 637: if (debug) ! 638: fprintf(ddt,"update failed\n"); ! 639: #endif ! 640: hp->rcode = n; ! 641: } ! 642: hp->rcode = NOERROR; ! 643: break; ! 644: ! 645: case UPDATED: ! 646: if ((n = ! 647: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) ! 648: { ! 649: #ifdef DEBUG ! 650: if (debug) ! 651: fprintf(ddt,"FORMERR UpdateD expand name failed\n"); ! 652: #endif ! 653: hp->rcode = FORMERR; ! 654: break; ! 655: } ! 656: cp += n; ! 657: rrec.r_type = getshort(cp); ! 658: cp += sizeof(u_short); ! 659: rrec.r_class = getshort(cp); ! 660: cp += sizeof(u_short) + sizeof(u_long); ! 661: rrec.r_size = getshort(cp); ! 662: rrec.r_data = cp += sizeof(u_short); ! 663: if (cp + rrec.r_size != msg + msglen) { ! 664: #ifdef DEBUG ! 665: if (debug) ! 666: fprintf(ddt,"FORMERR UpdateD message length off\n"); ! 667: #endif ! 668: hp->rcode = FORMERR; ! 669: break; ! 670: } ! 671: if (updatedb(dnbuf, &rrec, NULL, DB_DELETE) < 0) { ! 672: #ifdef DEBUG ! 673: if (debug) ! 674: fprintf(ddt,"update failed\n"); ! 675: #endif ! 676: } ! 677: hp->rcode = NOERROR; ! 678: break; ! 679: ! 680: case UPDATEM: ! 681: if ((n = dn_expand(msg, msg + msglen, cp, addbuf, ! 682: sizeof(addbuf))) < 0) { ! 683: #ifdef DEBUG ! 684: if (debug) ! 685: fprintf(ddt,"FORMERR UpdateM expand name 1 failed\n"); ! 686: #endif ! 687: hp->rcode = FORMERR; ! 688: break; ! 689: } ! 690: cp += n; ! 691: rrec.r_type = getshort(cp); ! 692: cp += sizeof(u_short); ! 693: rrec.r_class = getshort(cp); ! 694: cp += sizeof(u_short) + sizeof(u_long); ! 695: rrec.r_size = getshort(cp); ! 696: rrec.r_data = cp += sizeof(u_short); ! 697: cp += rrec.r_size; ! 698: if ((n = ! 699: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) ! 700: { ! 701: #ifdef DEBUG ! 702: if (debug) ! 703: fprintf(ddt,"FORMERR UpdateM expand name 2 failed\n"); ! 704: #endif ! 705: hp->rcode = FORMERR; ! 706: break; ! 707: } ! 708: if (cistrcmp(dnbuf, addbuf) != 0) { ! 709: #ifdef DEBUG ! 710: if (debug) ! 711: fprintf(ddt,"FORMERR UpdateM string compair failed\n"); ! 712: #endif ! 713: hp->rcode = FORMERR; ! 714: break; ! 715: } ! 716: cp += n; ! 717: type = getshort(cp); ! 718: cp += sizeof(u_short); ! 719: class = getshort(cp); ! 720: cp += sizeof(u_short); ! 721: ttl = getlong(cp); ! 722: cp += sizeof(u_long); ! 723: n = getshort(cp); ! 724: cp += sizeof(u_short); ! 725: if (cp + n != msg + msglen) { ! 726: #ifdef DEBUG ! 727: if (debug) ! 728: fprintf(ddt,"FORMERR UpdateM message length off\n"); ! 729: #endif ! 730: hp->rcode = FORMERR; ! 731: break; ! 732: } ! 733: dp = savedata(class, type, ttl, cp, n); ! 734: dp->d_zone = findzone(dnbuf, class); ! 735: if ((n = ! 736: updatedb(dnbuf, &rrec, dp, DB_MEXIST|DB_DELETE)) != NOERROR) ! 737: { ! 738: #ifdef DEBUG ! 739: if (debug) ! 740: fprintf(ddt,"update failed\n"); ! 741: #endif ! 742: hp->rcode = n; ! 743: } ! 744: hp->rcode = NOERROR; ! 745: break; ! 746: #endif ! 747: ! 748: case ZONEREF: ! 749: #ifdef DEBUG ! 750: if (debug) ! 751: fprintf(ddt,"Refresh Zone\n"); ! 752: #endif ! 753: ! 754: default: ! 755: hp->rcode = NOTIMP; ! 756: hp->qdcount = 0; ! 757: hp->ancount = 0; ! 758: hp->nscount = 0; ! 759: hp->arcount = 0; ! 760: } ! 761: finish: ! 762: hp->qr = 1; /* set Response flag */ ! 763: hp->ra = 1; /* Recursion is Available */ ! 764: if (addcount) ! 765: cp += doaddinfo(hp, cp, buflen - (cp - msg)); ! 766: #ifdef DEBUG ! 767: if (debug >= 10) ! 768: fp_query(msg, ddt); ! 769: #endif ! 770: if (qsp == QSTREAM_NULL) { ! 771: if (sendto(ds, msg, cp-msg, 0, from, sizeof(*from)) < 0) { ! 772: #ifdef DEBUG ! 773: if (debug) ! 774: fprintf(ddt,"error returning msg\n"); ! 775: #endif ! 776: } ! 777: } else { ! 778: (void) writemsg(qsp->s_rfd, msg, cp - msg); ! 779: qsp->s_time = tt.tv_sec; ! 780: qsp->s_refcnt--; ! 781: } ! 782: } ! 783: ! 784: fwritemsg(rfp, msg, msglen) ! 785: FILE *rfp; ! 786: char *msg; ! 787: int msglen; ! 788: { ! 789: u_short len = htons((u_short)msglen); ! 790: ! 791: if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 || ! 792: fwrite(msg, msglen, 1, rfp) != 1) { ! 793: #ifdef DEBUG ! 794: if (debug) ! 795: fprintf(ddt,"fwrite failed %d\n", errno); ! 796: #endif ! 797: /* ! 798: syslog(LOG_ERR, "fwritemsg: write failed: %m"); ! 799: */ ! 800: } ! 801: return; ! 802: } ! 803: ! 804: writemsg(rfd, msg, msglen) ! 805: int rfd; ! 806: char *msg; ! 807: int msglen; ! 808: { ! 809: struct iovec iov[2]; ! 810: u_short len = htons((u_short)msglen); ! 811: ! 812: iov[0].iov_base = (caddr_t)&len; ! 813: iov[0].iov_len = sizeof(len); ! 814: iov[1].iov_base = msg; ! 815: iov[1].iov_len = msglen; ! 816: if (writev(rfd, iov, 2) != sizeof(len) + msglen) { ! 817: #ifdef DEBUG ! 818: if (debug) ! 819: fprintf(ddt,"write failed %d\n", errno); ! 820: #endif ! 821: /* ! 822: syslog(LOG_ERR, "writemsg: write failed: %m"); ! 823: */ ! 824: return (-1); ! 825: } ! 826: return (0); ! 827: } ! 828: ! 829: /* ! 830: * Copy databuf into a resource record for replies. ! 831: * Return size of RR if OK, -1 if buffer is full and ! 832: * -2 if its an outdated cache entry. ! 833: */ ! 834: make_rr(name, dp, buf, buflen, doadd) ! 835: char *name; ! 836: register struct databuf *dp; ! 837: char *buf; ! 838: int buflen, doadd; ! 839: { ! 840: register char *cp; ! 841: register struct addinfo *ap; ! 842: char *cp1, *sp; ! 843: register long n; ! 844: u_long ttl; ! 845: char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); ! 846: ! 847: #ifdef DEBUG ! 848: if (debug >= 5) ! 849: fprintf(ddt,"make_rr(%s, %x, %x, %d, %d) %d\n", name, dp, buf, ! 850: buflen, doadd, dp->d_size); ! 851: #endif ! 852: ! 853: /* check for outdated RR before updating dnptrs by dn_comp() */ ! 854: if (dp->d_zone == 0) { ! 855: ttl = dp->d_ttl - (u_long) tt.tv_sec; ! 856: if (dp->d_ttl < (u_long)tt.tv_sec) ! 857: return (-2); ! 858: } else { ! 859: ttl = zones[dp->d_zone].z_minimum; ! 860: if (dp->d_ttl > ttl) ! 861: ttl = dp->d_ttl; ! 862: } ! 863: ! 864: buflen -= RRFIXEDSZ; ! 865: if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0) ! 866: return (-1); ! 867: cp = buf + n; ! 868: buflen -= n; ! 869: putshort((u_short)dp->d_type, cp); ! 870: cp += sizeof(u_short); ! 871: putshort((u_short)dp->d_class, cp); ! 872: cp += sizeof(u_short); ! 873: putlong(ttl, cp); ! 874: cp += sizeof(u_long); ! 875: sp = cp; ! 876: cp += sizeof(u_short); ! 877: switch (dp->d_type) { ! 878: case T_CNAME: ! 879: case T_MG: ! 880: case T_MR: ! 881: case T_PTR: ! 882: if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs, ! 883: (char **)edp)) < 0) ! 884: return (-1); ! 885: putshort((u_short)n, sp); ! 886: cp += n; ! 887: break; ! 888: ! 889: case T_MB: ! 890: case T_NS: ! 891: /* Store domain name in answer */ ! 892: if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs, ! 893: (char **)edp)) < 0) ! 894: return (-1); ! 895: putshort((u_short)n, sp); ! 896: cp += n; ! 897: if (!doadd) ! 898: break; ! 899: for (ap = addinfo, n = addcount; --n >= 0; ap++) ! 900: if (cistrcmp(ap->a_dname, dp->d_data) == 0) ! 901: goto found; ! 902: /* add domain name to additional section */ ! 903: if (addcount >= NADDRECS) ! 904: break; ! 905: addcount++; ! 906: ap->a_dname = dp->d_data; ! 907: ap->a_class = dp->d_class; ! 908: found: ! 909: break; ! 910: ! 911: case T_SOA: ! 912: case T_MINFO: ! 913: cp1 = dp->d_data; ! 914: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, ! 915: (char **)edp)) < 0) ! 916: return (-1); ! 917: cp += n; ! 918: buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long); ! 919: cp1 += strlen(cp1) + 1; ! 920: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, ! 921: (char **)edp)) < 0) ! 922: return (-1); ! 923: cp += n; ! 924: if (dp->d_type == T_SOA) { ! 925: cp1 += strlen(cp1) + 1; ! 926: bcopy(cp1, cp, ! 927: (int)(n = dp->d_size - (cp1 - dp->d_data))); ! 928: cp += n; ! 929: } ! 930: putshort((u_short)(cp - sp) - sizeof(u_short), sp); ! 931: break; ! 932: ! 933: case T_MX: ! 934: /* cp1 == our data/ cp == data of RR */ ! 935: cp1 = dp->d_data; ! 936: ! 937: /* copy preference */ ! 938: bcopy(cp1,cp,sizeof(u_short)); ! 939: cp += sizeof(u_short); ! 940: cp1 += sizeof(u_short); ! 941: buflen -= sizeof(u_short); ! 942: ! 943: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, ! 944: (char **)edp)) < 0) ! 945: return(-1); ! 946: cp += n; ! 947: ! 948: /* save data length */ ! 949: putshort((u_short)(cp-sp)-sizeof(u_short),sp); ! 950: break; ! 951: ! 952: default: ! 953: if (dp->d_size > buflen) ! 954: return (-1); ! 955: bcopy(dp->d_data, cp, dp->d_size); ! 956: putshort((u_short)dp->d_size, sp); ! 957: cp += dp->d_size; ! 958: } ! 959: return (cp - buf); ! 960: } ! 961: ! 962: /* ! 963: * Lookup addresses for names in addinfo and put into the message's ! 964: * additional section. ! 965: */ ! 966: doaddinfo(hp, msg, msglen) ! 967: HEADER *hp; ! 968: char *msg; ! 969: int msglen; ! 970: { ! 971: register char *cp; ! 972: register struct namebuf *np; ! 973: register struct databuf *dp; ! 974: register struct databuf *tmp; ! 975: struct hashbuf *htp; ! 976: struct databuf *pdp; ! 977: struct addinfo *ap; ! 978: char *fname; ! 979: int n, count; ! 980: ! 981: #ifdef DEBUG ! 982: if (debug >= 3) ! 983: fprintf(ddt,"doaddinfo() addcount = %d\n", addcount); ! 984: #endif ! 985: ! 986: count = 0; ! 987: cp = msg; ! 988: for (ap = addinfo; --addcount >= 0; ap++) { ! 989: #ifdef DEBUG ! 990: if (debug >= 5) ! 991: fprintf(ddt,"do additional '%s'\n", ap->a_dname); ! 992: #endif ! 993: htp = hashtab; /* lookup relative to root */ ! 994: np = nlookup(ap->a_dname, &htp, &fname, 0); ! 995: if (np == NULL || fname != ap->a_dname) ! 996: continue; ! 997: #ifdef DEBUG ! 998: if (debug >= 5) ! 999: fprintf(ddt,"found it\n"); ! 1000: #endif ! 1001: pdp = NULL; ! 1002: dp = np->n_data; ! 1003: /* look for the data */ ! 1004: while (dp != NULL) { ! 1005: if (!match(dp, (int)ap->a_class, T_A)) { ! 1006: pdp = dp; ! 1007: dp = dp->d_next; ! 1008: continue; ! 1009: } ! 1010: if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0) ! 1011: { ! 1012: if (n == -1) ! 1013: break; ! 1014: /* delete old cache entry */ ! 1015: #ifdef DEBUG ! 1016: if (debug) ! 1017: fprintf(ddt,"deleting cache entry\n"); ! 1018: #endif ! 1019: rminv(dp); ! 1020: tmp = dp->d_next; ! 1021: (void) free((char *)dp); ! 1022: dp = tmp; ! 1023: if (pdp == NULL) ! 1024: np->n_data = dp; ! 1025: else ! 1026: pdp->d_next = dp; ! 1027: continue; ! 1028: } ! 1029: #ifdef DEBUG ! 1030: if (debug >= 5) ! 1031: fprintf(ddt,"n = %d\n", n); ! 1032: #endif ! 1033: cp += n; ! 1034: msglen -= n; ! 1035: count++; ! 1036: pdp = dp; ! 1037: dp = dp->d_next; ! 1038: } ! 1039: } ! 1040: hp->arcount = htons((u_short)count); ! 1041: return (cp - msg); ! 1042: } ! 1043: ! 1044: /* ! 1045: * Do we want this data record based on the class and type? ! 1046: */ ! 1047: wanted(dp, class, type) ! 1048: struct databuf *dp; ! 1049: int class, type; ! 1050: { ! 1051: ! 1052: #ifdef DEBUG ! 1053: if (debug > 3) ! 1054: fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type, ! 1055: dp->d_class, dp->d_type); ! 1056: #endif ! 1057: ! 1058: if (dp->d_class != class && class != C_ANY) ! 1059: return (0); ! 1060: if (type == dp->d_type) ! 1061: return (1); ! 1062: switch (dp->d_type) { ! 1063: case T_ANY: ! 1064: case T_CNAME: ! 1065: return (1); ! 1066: } ! 1067: switch (type) { ! 1068: case T_ANY: ! 1069: return (1); ! 1070: ! 1071: case T_MAILB: ! 1072: switch (dp->d_type) { ! 1073: case T_MR: ! 1074: case T_MB: ! 1075: case T_MG: ! 1076: case T_MINFO: ! 1077: return (1); ! 1078: } ! 1079: break; ! 1080: ! 1081: case T_AXFR: ! 1082: if (dp->d_type == T_SOA) ! 1083: return (1); ! 1084: } ! 1085: return (0); ! 1086: } ! 1087: ! 1088: /* ! 1089: * Get the domain name of 'np' and put in 'buf'. ! 1090: */ ! 1091: getname(np, buf, buflen) ! 1092: struct namebuf *np; ! 1093: char *buf; ! 1094: int buflen; ! 1095: { ! 1096: register char *cp; ! 1097: ! 1098: cp = buf; ! 1099: while (np != NULL) { ! 1100: if (cp != buf) ! 1101: *cp++ = '.'; ! 1102: (void) strcpy(cp, np->n_dname); ! 1103: cp += strlen(cp); ! 1104: np = np->n_parent; ! 1105: } ! 1106: *cp = '\0'; ! 1107: } ! 1108: ! 1109: /* ! 1110: * Do a zone transfer. SOA record already sent. ! 1111: */ ! 1112: doaxfr(np, rfp, isroot) ! 1113: register struct namebuf *np; ! 1114: FILE *rfp; ! 1115: int isroot; ! 1116: { ! 1117: register struct databuf *dp; ! 1118: register int n; ! 1119: struct namebuf **npp, **nppend; ! 1120: char msg[PACKETSZ]; ! 1121: HEADER *hp = (HEADER *) msg; ! 1122: char *cp; ! 1123: char dname[MAXDNAME]; ! 1124: int fndns; ! 1125: ! 1126: #ifdef DEBUG ! 1127: if (debug && isroot) ! 1128: fprintf(ddt,"doaxfr()\n"); ! 1129: #endif ! 1130: fndns = 0; ! 1131: hp->id = 0; ! 1132: hp->opcode = QUERY; ! 1133: hp->qr = hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0; ! 1134: hp->rcode = NOERROR; ! 1135: hp->qdcount = 0; ! 1136: hp->ancount = htons(1); ! 1137: hp->nscount = 0; ! 1138: hp->arcount = 0; ! 1139: cp = msg + sizeof(HEADER); ! 1140: getname(np, dname, sizeof(dname)); ! 1141: ! 1142: /* first do data records */ ! 1143: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { ! 1144: /* skip the root SOA record (marks end of data) */ ! 1145: if (isroot) { ! 1146: if (dp->d_type == T_SOA) ! 1147: continue; ! 1148: } else if (dp->d_type == T_NS) ! 1149: fndns = 1; ! 1150: if (dp->d_zone == 0) ! 1151: continue; ! 1152: if ((n = make_rr(dname, dp, cp, ! 1153: sizeof(msg)-sizeof(HEADER), 0)) < 0) ! 1154: continue; ! 1155: fwritemsg(rfp, msg, n + sizeof(HEADER)); ! 1156: } ! 1157: ! 1158: /* next do subdomains */ ! 1159: if (fndns || np->n_hash == NULL) ! 1160: return; ! 1161: npp = np->n_hash->h_tab; ! 1162: nppend = npp + np->n_hash->h_size; ! 1163: while (npp < nppend) { ! 1164: for (np = *npp++; np != NULL; np = np->n_next) { ! 1165: doaxfr(np, rfp, 0); ! 1166: } ! 1167: } ! 1168: #ifdef DEBUG ! 1169: if (debug && isroot) ! 1170: fprintf(ddt,"exit doaxfr()\n"); ! 1171: #endif ! 1172: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.