|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ns_resp.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/time.h> ! 13: #include <sys/socket.h> ! 14: #include <netinet/in.h> ! 15: #include <syslog.h> ! 16: #include <arpa/nameser.h> ! 17: #include "ns.h" ! 18: #include "db.h" ! 19: ! 20: extern int errno; ! 21: extern char *dnptrs[]; ! 22: extern char *malloc(); ! 23: struct databuf *nsp[MAXNS], **nspp; ! 24: ! 25: /* ! 26: * Handle a response from a forwarded query. ! 27: */ ! 28: ns_resp(msg, msglen) ! 29: char *msg; ! 30: int msglen; ! 31: { ! 32: register struct qinfo *qp; ! 33: register HEADER *hp; ! 34: register char *cp, *tp; ! 35: int i, c, n, ancount, nscount, arcount; ! 36: int type; ! 37: int qtype, qclass; ! 38: int cname = 0; /* flag for processing cname response */ ! 39: int count, founddata; ! 40: int buflen; ! 41: int newmsglen; ! 42: char name[MAXDNAME], *dname; ! 43: char *fname; ! 44: char *newmsg; ! 45: ! 46: struct hashbuf *htp; ! 47: struct databuf *dp, *tmp, *pdp; ! 48: struct namebuf *np; ! 49: ! 50: #ifdef DEBUG ! 51: if (debug >= 3) ! 52: fprintf(ddt,"ns_resp(%x, %d)\n", msg, msglen); ! 53: #endif ! 54: hp = (HEADER *) msg; ! 55: if( (qp = qfindid(hp->id)) == NULL ) ! 56: return; ! 57: ! 58: if (hp->rcode != NOERROR || hp->opcode != QUERY) ! 59: goto retmsg; ! 60: /* ! 61: * Skip query section ! 62: */ ! 63: cp = msg + sizeof(HEADER); ! 64: if (hp->qdcount) { ! 65: if ((n = dn_skip(cp)) < 0) { ! 66: #ifdef DEBUG ! 67: if (debug) ! 68: fprintf(ddt,"FORMERR ns_resp() dn_skip failed\n"); ! 69: #endif ! 70: hp->rcode = FORMERR; ! 71: goto retmsg; ! 72: } ! 73: cp += n; ! 74: qtype = getshort(cp); ! 75: cp += sizeof(u_short); ! 76: qclass = getshort(cp); ! 77: cp += sizeof(u_short); ! 78: } ! 79: /* ! 80: * Save answers, name server, and additional records for future use. ! 81: */ ! 82: ancount = ntohs(hp->ancount); ! 83: nscount = ntohs(hp->nscount); ! 84: arcount = ntohs(hp->arcount); ! 85: if (ancount == 1 || nscount) { ! 86: /* ! 87: * Check if it's a CNAME responce ! 88: */ ! 89: tp = cp; ! 90: tp += dn_skip(tp); /* name */ ! 91: type = getshort(tp); ! 92: tp += sizeof(u_short); /* type */ ! 93: if (type == T_CNAME) { ! 94: tp += sizeof(u_short); /* class */ ! 95: tp += sizeof(u_long); /* ttl */ ! 96: tp += sizeof(u_short); /* dlen */ ! 97: cname++; ! 98: #ifdef DEBUG ! 99: if (debug) { ! 100: fprintf(ddt,"CNAME - needs more processing\n"); ! 101: } ! 102: #endif ! 103: if (!qp->q_cmsglen) { ! 104: qp->q_cmsg = qp->q_msg; ! 105: qp->q_cmsglen = qp->q_msglen; ! 106: } ! 107: } ! 108: } ! 109: /* ! 110: * Add the info recived in the responce to the Data Base ! 111: */ ! 112: c = ancount + nscount + arcount; ! 113: nspp = nsp; ! 114: for (i = 0; i < c; i++) { ! 115: if (cp >= msg + msglen) { ! 116: #ifdef DEBUG ! 117: if (debug) ! 118: fprintf(ddt, "FORMERR ns_resp() message bad count?\n"); ! 119: #endif ! 120: hp->rcode = FORMERR; ! 121: goto retmsg; ! 122: } ! 123: if ((n = doupdate(msg, msglen, cp, 0, ! 124: !ancount && i < nscount)) < 0) { ! 125: #ifdef DEBUG ! 126: if (debug) ! 127: fprintf(ddt,"FORMERR ns_resp() doupdate failed\n"); ! 128: #endif ! 129: hp->rcode = FORMERR; ! 130: goto retmsg; ! 131: } ! 132: cp += n; ! 133: } ! 134: if (cp > msg + msglen) { ! 135: #ifdef DEBUG ! 136: if (debug) ! 137: fprintf(ddt,"FORMERR ns_resp() packet size err %d, %d\n", ! 138: cp-msg, msglen); ! 139: #endif ! 140: hp->rcode = FORMERR; ! 141: goto retmsg; ! 142: } ! 143: if ((qtype == C_ANY) && ancount) ! 144: goto retmsg; ! 145: if ((!cname && !qp->q_cmsglen) && (ancount || nscount == 0)) ! 146: goto retmsg; ! 147: ! 148: /* ! 149: * All messages in here need further processing. i.e. they ! 150: * are either CNAMEs or we got referred again. ! 151: */ ! 152: count = 0; ! 153: founddata = 0; ! 154: dname = name; ! 155: if ((newmsg = malloc(BUFSIZ)) == NULL) { ! 156: #if DEBUG ! 157: if (debug) ! 158: fprintf(ddt,"ns_resp: malloc error\n"); ! 159: #endif ! 160: syslog(LOG_ERR, "ns_resp: Out Of Memory"); ! 161: hp->rcode = SERVFAIL; ! 162: goto retmsg; ! 163: } ! 164: buflen = BUFSIZ; ! 165: if ((!cname && qp->q_cmsglen) && ancount) { ! 166: #if DEBUG ! 167: if (debug) { ! 168: fprintf(ddt,"Cname second pass\n"); ! 169: } ! 170: #endif ! 171: newmsglen = qp->q_cmsglen; ! 172: bcopy(qp->q_cmsg, newmsg, newmsglen); ! 173: } else { ! 174: newmsglen = msglen; ! 175: bcopy(msg, newmsg, newmsglen); ! 176: } ! 177: buflen = buflen - newmsglen; ! 178: hp = (HEADER *) newmsg; ! 179: dnptrs[0] = newmsg; ! 180: dnptrs[1] = NULL; ! 181: cp = newmsg + sizeof(HEADER); ! 182: if (cname) ! 183: cp += dn_skip(cp) + QFIXEDSZ; ! 184: if ((n = dn_expand(newmsg, newmsg + newmsglen, ! 185: cp, dname, sizeof(name))) < 0) { ! 186: #ifdef DEBUG ! 187: if (debug) ! 188: fprintf(ddt,"dn_expand failed\n" ); ! 189: #endif ! 190: hp->rcode = SERVFAIL; ! 191: free(newmsg); ! 192: goto retmsg; ! 193: } ! 194: cp = newmsg + sizeof(HEADER); ! 195: if (cname) ! 196: cp += dn_skip(cp); ! 197: else ! 198: cp += n; ! 199: cp += QFIXEDSZ; ! 200: ! 201: again: ! 202: htp = hashtab; /* lookup relative to root */ ! 203: #ifdef DEBUG ! 204: if (debug) ! 205: fprintf(ddt,"ns_resp() nlookup(%s)\n",dname); ! 206: #endif ! 207: np = nlookup(dname, &htp, &fname, 0); ! 208: if (np == (struct namebuf *)NULL) ! 209: fname = ""; ! 210: if (fname != dname) ! 211: goto findns; ! 212: #ifdef DEBUG ! 213: if (debug) ! 214: fprintf(ddt,"found '%s'\n", dname); ! 215: #endif ! 216: pdp = NULL; ! 217: dp = np->n_data; ! 218: /* look for the data */ ! 219: while (dp != NULL) { ! 220: if (!wanted(dp, qclass, qtype)) { ! 221: pdp = dp; ! 222: dp = dp->d_next; ! 223: continue; ! 224: } ! 225: if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) { ! 226: if (n == -1) { ! 227: hp->tc = 1; ! 228: break; ! 229: } ! 230: /* delete old cache entry */ ! 231: #ifdef DEBUG ! 232: if (debug >= 5) ! 233: fprintf(ddt,"deleting cache entry\n"); ! 234: #endif ! 235: rminv(dp); ! 236: tmp = dp->d_next; ! 237: free((char *)dp); ! 238: dp = tmp; ! 239: if (pdp == NULL) ! 240: np->n_data = dp; ! 241: else ! 242: pdp->d_next = dp; ! 243: continue; ! 244: } ! 245: cp += n; ! 246: buflen -= n; ! 247: count++; ! 248: if (dp->d_zone) ! 249: hp->aa = 1; ! 250: if (dp->d_type == T_CNAME) { ! 251: if (type == T_ANY) ! 252: break; ! 253: dname = dp->d_data; ! 254: goto again; ! 255: } ! 256: founddata++; ! 257: pdp = dp; ! 258: dp = dp->d_next; ! 259: } ! 260: #ifdef DEBUG ! 261: if (debug >= 5) ! 262: fprintf(ddt,"count = %d, founddata = %d\n", count, founddata); ! 263: #endif ! 264: if (count) ! 265: hp->ancount = htons((u_short)count); ! 266: ! 267: findns: ! 268: ! 269: /* ! 270: * Look for name servers to refer to and fill in the authority ! 271: * section or record the address for forwarding the query ! 272: * (recursion desired). ! 273: */ ! 274: for (count = 0;; np = np->n_parent) { ! 275: #ifdef DEBUG ! 276: if (debug >= 5) ! 277: fprintf(ddt, "fname = '%s'\n", fname); ! 278: #endif ! 279: if (*fname == '\0') { ! 280: for (np = hashtab->h_tab[0]; np != NULL; ! 281: np = np->n_next) ! 282: if (np->n_dname[0] == '\0') ! 283: goto foundns; ! 284: #ifdef DEBUG ! 285: if (debug) ! 286: fprintf(ddt, "No root nameserver?\n"); ! 287: #endif ! 288: syslog(LOG_ERR, "No root Nameserver\n"); ! 289: hp->rcode = SERVFAIL; ! 290: break; ! 291: } ! 292: foundns: ! 293: nspp = nsp; ! 294: pdp = NULL; ! 295: dp = np->n_data; ! 296: while (dp != NULL) { ! 297: if (!match(dp, qclass, T_NS)) { ! 298: pdp = dp; ! 299: dp = dp->d_next; ! 300: continue; ! 301: } ! 302: if (!founddata) { ! 303: if (nspp < &nsp[MAXNS-1]) ! 304: *nspp++ = dp; ! 305: pdp = dp; ! 306: dp = dp->d_next; ! 307: continue; ! 308: } ! 309: if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) { ! 310: if (n == -1) { ! 311: hp->tc = 1; ! 312: break; ! 313: } ! 314: /* delete old cache entry */ ! 315: #ifdef DEBUG ! 316: if (debug) ! 317: fprintf(ddt,"deleting cache entry\n"); ! 318: #endif ! 319: rminv(dp); ! 320: tmp = dp->d_next; ! 321: free((char *)dp); ! 322: dp = tmp; ! 323: if (pdp == NULL) ! 324: np->n_data = dp; ! 325: else ! 326: pdp->d_next = dp; ! 327: continue; ! 328: } ! 329: cp += n; ! 330: buflen -= n; ! 331: count++; ! 332: pdp = dp; ! 333: dp = dp->d_next; ! 334: } ! 335: if ((*fname == '\0') || (count > 0)) ! 336: break; ! 337: if (nspp != nsp) ! 338: break; ! 339: if ((fname = index(fname, '.')) == NULL) ! 340: fname = ""; ! 341: else ! 342: fname++; ! 343: } ! 344: ! 345: if (count && founddata) { ! 346: hp->nscount = htons((u_short)count); ! 347: cp += doaddinfo(hp, cp, buflen); ! 348: buflen = cp - newmsg; ! 349: msg = newmsg; ! 350: msglen = buflen; ! 351: hp = (HEADER *) msg; ! 352: goto retmsg; ! 353: } ! 354: ! 355: *nspp = NULL; ! 356: if (cname) { ! 357: newmsglen = res_mkquery(QUERY, dname, C_ANY, T_A, (char *)NULL, ! 358: 0, NULL, newmsg, BUFSIZ); ! 359: qp->q_msglen = newmsglen; ! 360: hp->id = qp->q_nsid; ! 361: } else { ! 362: hp->ancount = 0; ! 363: hp->nscount = 0; ! 364: hp->arcount = 0; ! 365: hp->qr = 0; ! 366: } ! 367: qp->q_naddr = 0; ! 368: qp->q_curaddr = 0; ! 369: n = nslookup(nsp, qp); ! 370: ! 371: #ifdef DEBUG ! 372: if (debug > 7) { ! 373: int kjd; ! 374: ! 375: fprintf(ddt,"n = %d\n",n); ! 376: for (kjd = 0; kjd < qp->q_naddr; kjd++ ) ! 377: fprintf(ddt,"list %d-> %s (%d)\n", kjd, ! 378: inet_ntoa(qp->q_addr[kjd].sin_addr), ! 379: ntohs(qp->q_addr[kjd].sin_port)); ! 380: } ! 381: #endif DEBUG ! 382: qp->q_msg = newmsg; ! 383: if (qp->q_cname++ == MAXCNAMES) { ! 384: hp->id = qp->q_id; ! 385: hp->rd = 1; ! 386: hp->ra = 1; ! 387: if (qp->q_stream != QSTREAM_NULL) { ! 388: (void) writemsg(qp->q_stream->s_rfd, newmsg, newmsglen); ! 389: qp->q_stream->s_time = tt.tv_sec; ! 390: qp->q_stream->s_refcnt--; ! 391: } else { ! 392: if (sendto(ds, newmsg, newmsglen, 0, &qp->q_from, ! 393: sizeof(qp->q_from)) < 0) { ! 394: #ifdef DEBUG ! 395: if (debug) ! 396: fprintf(ddt,"sendto failed\n"); ! 397: #endif ! 398: } ! 399: } ! 400: qremove(qp); ! 401: return; ! 402: } ! 403: #ifdef DEBUG ! 404: if (debug) ! 405: fprintf(ddt,"q_cname = %d\n",qp->q_cname); ! 406: #endif ! 407: unsched(qp); ! 408: schedretry(qp, (time_t)RETRYTIME); ! 409: ! 410: #ifdef DEBUG ! 411: if (debug >= 3) ! 412: fp_query(qp->q_msg, ddt); ! 413: if (debug) ! 414: fprintf(ddt,"try -> %s (%d)\n", ! 415: inet_ntoa(qp->q_addr[0].sin_addr), ! 416: ntohs(qp->q_addr[0].sin_port)); ! 417: #endif ! 418: if (sendto(ds, qp->q_msg, qp->q_msglen, 0, ! 419: &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0) { ! 420: #ifdef DEBUG ! 421: if (debug) ! 422: fprintf(ddt, "error returning msg errno=%d\n",errno); ! 423: #endif ! 424: } ! 425: return; ! 426: ! 427: retmsg: ! 428: /* ! 429: * Pass answer back to original requestor. ! 430: */ ! 431: hp->id = qp->q_id; ! 432: hp->rd = 1; /* restore Recursion Desired bit */ ! 433: hp->ra = 1; /* Recursion is Available */ ! 434: #ifdef DEBUG ! 435: if (debug) ! 436: fprintf(ddt,"respond -> %s (%d)\n", ! 437: inet_ntoa(qp->q_from.sin_addr), ! 438: ntohs(qp->q_from.sin_port)); ! 439: if (debug >= 10) ! 440: fp_query(msg, ddt); ! 441: #endif ! 442: if (qp->q_stream == QSTREAM_NULL) { ! 443: if (sendto(ds, msg, msglen, 0, ! 444: &qp->q_from, sizeof(qp->q_from)) < 0) { ! 445: #ifdef DEBUG ! 446: if (debug) ! 447: fprintf(ddt,"sendto failed\n"); ! 448: #endif ! 449: } ! 450: ! 451: } else { ! 452: (void) writemsg(qp->q_stream->s_rfd, msg, msglen); ! 453: qp->q_stream->s_time = tt.tv_sec; ! 454: qp->q_stream->s_refcnt--; ! 455: } ! 456: if (msg == newmsg) ! 457: (void) free(newmsg); ! 458: /* ! 459: * Remove from table ! 460: */ ! 461: qremove(qp); ! 462: } ! 463: ! 464: /* ! 465: * Decode the resource record 'rrp' and update the database. ! 466: * If savens is true, record pointer for forwarding queries a second time. ! 467: */ ! 468: doupdate(msg, msglen, rrp, zone, savens) ! 469: char *msg ; ! 470: char *rrp; ! 471: int msglen, zone, savens; ! 472: { ! 473: register char *cp; ! 474: register int n; ! 475: int class, type, dlen, n1; ! 476: u_long ttl; ! 477: struct databuf *dp; ! 478: char dname[MAXDNAME]; ! 479: char data[BUFSIZ], *cp1; ! 480: ! 481: #ifdef DEBUG ! 482: if (debug >= 3) ! 483: fprintf(ddt,"doupdate(%d, %d)\n", zone, savens); ! 484: #endif ! 485: ! 486: cp = rrp; ! 487: if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0) ! 488: return (-1); ! 489: cp += n; ! 490: type = getshort(cp); ! 491: cp += sizeof(u_short); ! 492: class = getshort(cp); ! 493: cp += sizeof(u_short); ! 494: ttl = getlong(cp); ! 495: cp += sizeof(u_long); ! 496: dlen = getshort(cp); ! 497: cp += sizeof(u_short); ! 498: if (zone == 0) { ! 499: if (ttl == 0) ! 500: ttl = 5 * 60; ! 501: ttl += (u_long) tt.tv_sec; ! 502: } ! 503: /* ! 504: * Convert the resource record data into the internal ! 505: * database format. ! 506: */ ! 507: switch (type) { ! 508: case T_A: ! 509: case T_HINFO: ! 510: case T_UINFO: ! 511: case T_UID: ! 512: case T_GID: ! 513: cp1 = cp; ! 514: n = dlen; ! 515: cp += n; ! 516: break; ! 517: ! 518: case T_CNAME: ! 519: case T_MB: ! 520: case T_MG: ! 521: case T_MR: ! 522: case T_NS: ! 523: case T_PTR: ! 524: if ((n = dn_expand(msg, msg + msglen, cp, data, ! 525: sizeof(data))) < 0) ! 526: return (-1); ! 527: cp += n; ! 528: cp1 = data; ! 529: n = strlen(data) + 1; ! 530: break; ! 531: ! 532: case T_MINFO: ! 533: case T_SOA: ! 534: if ((n = dn_expand(msg, msg + msglen, cp, data, ! 535: sizeof(data))) < 0) ! 536: return (-1); ! 537: cp += n; ! 538: cp1 = data + (n = strlen(data) + 1); ! 539: n1 = sizeof(data) - n; ! 540: if (type == T_SOA) ! 541: n1 -= 5 * sizeof(u_long); ! 542: if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) ! 543: return (-1); ! 544: cp += n; ! 545: cp1 += strlen(cp1) + 1; ! 546: if (type == T_SOA) { ! 547: bcopy(cp, cp1, n = 5 * sizeof(u_long)); ! 548: cp += n; ! 549: cp1 += n; ! 550: } ! 551: n = cp1 - data; ! 552: cp1 = data; ! 553: break; ! 554: ! 555: case T_MX: ! 556: /* grab preference */ ! 557: bcopy(cp,data,sizeof(u_short)); ! 558: cp1 = data + sizeof(u_short); ! 559: cp += sizeof(u_short); ! 560: ! 561: /* get name */ ! 562: if ((n = dn_expand(msg, msg + msglen, cp, cp1, ! 563: sizeof(data)-sizeof(u_short))) < 0) ! 564: return(-1); ! 565: cp += n; ! 566: ! 567: /* compute end of data */ ! 568: cp1 += strlen(cp1) + 1; ! 569: /* compute size of data */ ! 570: n = cp1 - data; ! 571: cp1 = data; ! 572: break; ! 573: ! 574: default: ! 575: #ifdef DEBUG ! 576: if (debug >= 3) ! 577: fprintf(ddt,"unknown type %d\n", type); ! 578: #endif ! 579: return ((cp - rrp) + dlen); ! 580: } ! 581: dp = savedata(class, type, ttl, cp1, n); ! 582: dp->d_zone = zone; ! 583: if ((n = db_update(dname, dp, dp, DB_NODATA)) < 0) { ! 584: #ifdef DEBUG ! 585: if (debug && (n != DATAEXISTS)) ! 586: fprintf(ddt,"update failed (%d)\n", n); ! 587: else if (debug >= 3) ! 588: fprintf(ddt,"update failed (DATAEXISTS)\n"); ! 589: #endif ! 590: (void) free((char *)dp); ! 591: } else if (savens && type == T_NS && nspp < &nsp[MAXNS-1]) ! 592: *nspp++ = dp; ! 593: return (cp - rrp); ! 594: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.