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: }

Defined functions

doaddinfo defined in line 966; used 2 times
doaxfr defined in line 1112; used 2 times
fwritemsg defined in line 784; used 3 times
getname defined in line 1091; used 3 times
make_rr defined in line 834; used 6 times
ns_req defined in line 38; used 2 times
wanted defined in line 1047; used 2 times

Defined variables

addcount defined in line 29; used 7 times
addinfo defined in line 28; used 2 times
dnptrs defined in line 31; used 15 times
sccsid defined in line 2; never used

Defined struct's

addinfo defined in line 23; used 6 times

Defined macros

NADDRECS defined in line 21; used 2 times
Last modified: 1986-05-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2888
Valid CSS Valid XHTML 1.0 Strict