Annotation of 43BSD/etc/named/ns_req.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.