Annotation of 43BSD/etc/named/ns_req.c, revision 1.1.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.