Annotation of 43BSDReno/usr.sbin/named/ns_resp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)ns_resp.c  4.63 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: #include <stdio.h>
                     25: #include <sys/param.h>
                     26: #include <sys/time.h>
                     27: #include <sys/socket.h>
                     28: #include <sys/file.h>
                     29: #include <netinet/in.h>
                     30: #include <syslog.h>
                     31: #include <arpa/nameser.h>
                     32: #include "ns.h"
                     33: #include "db.h"
                     34: 
                     35: extern int     debug;
                     36: extern FILE    *ddt;
                     37: extern int errno;
                     38: extern u_char *dnptrs[];
                     39: extern time_t retrytime();
                     40: extern struct  fwdinfo *fwdtab;
                     41: extern struct  sockaddr_in from_addr;  /* Source addr of last packet */
                     42: extern int needs_prime_cache;
                     43: extern int priming;
                     44: 
                     45: struct qinfo *sysquery();
                     46: 
                     47: ns_resp(msg, msglen)
                     48:        u_char *msg;
                     49:        int msglen;
                     50: {
                     51:        register struct qinfo *qp;
                     52:        register HEADER *hp;
                     53:        register struct qserv *qs;
                     54:        register struct databuf *ns, *ns2;
                     55:        register u_char *cp;
                     56:        struct  databuf *nsp[NSMAX], **nspp;
                     57:        int i, c, n, ancount, aucount, nscount, arcount;
                     58:        int type, class, dbflags;
                     59:        int cname = 0; /* flag for processing cname response */
                     60:        int count, founddata, foundname;
                     61:        int buflen;
                     62:        int newmsglen;
                     63:        char name[MAXDNAME], *dname;
                     64:        char *fname;
                     65:        u_char newmsg[BUFSIZ];
                     66:        u_char **dpp, *tp;
                     67:        time_t rtrip;
                     68: 
                     69:        struct hashbuf *htp;
                     70:        struct namebuf *np;
                     71:        struct netinfo *lp;
                     72:        extern struct netinfo *local();
                     73:        extern int nsid;
                     74:        extern int addcount;
                     75:        struct fwdinfo *fwd;
                     76: 
                     77: #ifdef STATS
                     78:        stats[S_RESPONSES].cnt++;
                     79: #endif
                     80:        hp = (HEADER *) msg;
                     81:        if ((qp = qfindid(hp->id)) == NULL ) {
                     82: #ifdef DEBUG
                     83:                if (debug > 1)
                     84:                        fprintf(ddt,"DUP? dropped (id %d)\n", ntohs(hp->id));
                     85: #endif
                     86: #ifdef STATS
                     87:                stats[S_DUPRESP].cnt++;
                     88: #endif
                     89:                return;
                     90:        }
                     91: 
                     92: #ifdef DEBUG
                     93:        if (debug >= 2)
                     94:                fprintf(ddt,"%s response nsid=%d id=%d\n",
                     95:                        qp->q_system ? "SYSTEM" : "USER",
                     96:                        ntohs(qp->q_nsid), ntohs(qp->q_id));
                     97: #endif
                     98: 
                     99:        /*
                    100:         *  Here we handle bad responses from servers.
                    101:         *  Several possibilities come to mind:
                    102:         *      The server is sick and returns SERVFAIL
                    103:         *      The server returns some garbage opcode (its sick)
                    104:         *      The server can't understand our query and return FORMERR
                    105:         *  In all these cases, we simply drop the packet and force
                    106:         *  a retry.  This will make him look bad due to unresponsiveness.
                    107:         *  Be sure not to include authoritative NXDOMAIN
                    108:         */
                    109:        if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN)
                    110:            || (hp->rcode == NXDOMAIN && !hp->aa)
                    111:            || hp->opcode != QUERY) {
                    112: #ifdef DEBUG
                    113:                if (debug >= 2)
                    114:                        fprintf(ddt,"resp: error (ret %d, op %d), dropped\n",
                    115:                                hp->rcode, hp->opcode);
                    116: #endif
                    117: #ifdef STATS
                    118:                stats[S_BADRESPONSES].cnt++;
                    119: #endif
                    120:                return;
                    121:        }
                    122: 
                    123: #ifdef ALLOW_UPDATES
                    124:        if ( (hp->rcode == NOERROR) &&
                    125:             (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
                    126:              hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
                    127:              hp->opcode == UPDATEMA) ) {
                    128:                /*
                    129:                 * Update the secondary's copy, now that the primary
                    130:                 * successfully completed the update.  Zone doesn't matter
                    131:                 * for dyn. update -- doupdate calls findzone to find it
                    132:                 */
                    133:                doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + sizeof(HEADER),
                    134:                         0, (struct databuf *)0, 0);
                    135: #ifdef DEBUG
                    136:                if (debug >= 3)
                    137:                        fprintf(ddt,"resp: leaving, UPDATE*\n");
                    138: #endif
                    139:                /* return code filled in by doupdate */
                    140:                goto return_msg;
                    141:        }
                    142: #endif ALLOW_UPDATES
                    143: 
                    144:        /*
                    145:         * Determine if the response came from a forwarder.  Packets from
                    146:         * anyplace not listed as a forwarder or as a server to whom we
                    147:         * might have forwarded the query will be dropped.
                    148:         */
                    149:        for (fwd = fwdtab; fwd != (struct fwdinfo *)NULL; fwd = fwd->next)
                    150:                if (bcmp((char *)&fwd->fwdaddr.sin_addr, &from_addr.sin_addr,
                    151:                    sizeof(struct in_addr)) == 0)
                    152:                        break;
                    153:        /*
                    154:         * If we were using nameservers, find the qinfo pointer and update
                    155:         * the rtt and fact that we have called on this server before.
                    156:         */
                    157:        if (fwd == (struct fwdinfo *)NULL) {
                    158:                struct timeval *stp;
                    159: 
                    160:                for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++)
                    161:                        if (bcmp((char *)&qs->ns_addr.sin_addr,
                    162:                            &from_addr.sin_addr, sizeof(struct in_addr)) == 0)
                    163:                                break;
                    164:                if (n >= qp->q_naddr) {
                    165: #ifdef DEBUG
                    166:                        if (debug)
                    167:                            fprintf(ddt, "Response from unexpected source %s\n",
                    168:                                inet_ntoa(from_addr.sin_addr));
                    169: #endif DEBUG
                    170: #ifdef STATS
                    171:                        stats[S_MARTIANS].cnt++;
                    172: #endif
                    173:                        /* 
                    174:                         * We don't know who this response came from so it
                    175:                         * gets dropped on the floor.
                    176:                         */
                    177:                        return;
                    178:                }
                    179:                stp = &qs->stime;
                    180: 
                    181:                /* Handle response from different (untried) interface */
                    182:                if (stp->tv_sec == 0) {
                    183:                        ns = qs->ns;
                    184:                        while (qs > qp->q_addr &&
                    185:                            (qs->stime.tv_sec == 0 || qs->ns != ns))
                    186:                                qs--;
                    187:                        *stp = qs->stime;
                    188: #ifdef DEBUG
                    189:                        if (debug)
                    190:                            fprintf(ddt,
                    191:                            "Response from unused address %s, assuming %s\n",
                    192:                                inet_ntoa(from_addr.sin_addr),
                    193:                                inet_ntoa(qs->ns_addr.sin_addr));
                    194: #endif DEBUG
                    195:                }
                    196: 
                    197:                /* compute query round trip time */
                    198:                rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 +
                    199:                    (tt.tv_usec - stp->tv_usec) / 1000);
                    200:                
                    201: #ifdef DEBUG
                    202:                if (debug > 2)
                    203:                        fprintf(ddt,"stime %d/%d  now %d/%d rtt %d\n",
                    204:                            stp->tv_sec, stp->tv_usec,
                    205:                            tt.tv_sec, tt.tv_usec, rtrip);
                    206: #endif
                    207:                /* prevent floating point overflow, limit to 1000 sec */
                    208:                if (rtrip > 1000000)
                    209:                                rtrip = 1000000;
                    210:                ns = qs->nsdata;
                    211:                /*
                    212:                 * Don't update nstime if this doesn't look
                    213:                 * like an address databuf now.                 XXX
                    214:                 */
                    215:                if (ns->d_type == T_A && ns->d_class == qs->ns->d_class) {
                    216:                        if (ns->d_nstime == 0)
                    217:                                ns->d_nstime = (u_long)rtrip;
                    218:                        else
                    219:                                ns->d_nstime = ns->d_nstime * ALPHA +
                    220:                                    (1-ALPHA) * (u_long)rtrip;
                    221:                        /* prevent floating point overflow, limit to 1000 sec */
                    222:                        if (ns->d_nstime > 1000000)
                    223:                                ns->d_nstime = 1000000;
                    224:                }
                    225: 
                    226:                /*
                    227:                 * Record the source so that we do not use this NS again.
                    228:                 */
                    229:                if(qp->q_nusedns < NSMAX) {
                    230:                        qp->q_usedns[qp->q_nusedns++] = qs->ns;
                    231: #ifdef DEBUG
                    232:                        if(debug > 1)
                    233:                            fprintf(ddt, "NS #%d addr %s used, rtt %d\n",
                    234:                                n, inet_ntoa(qs->ns_addr.sin_addr),
                    235:                                ns->d_nstime);
                    236: #endif DEBUG
                    237:                }
                    238: 
                    239:                /*
                    240:                 * Penalize those who had earlier chances but failed
                    241:                 * by multiplying round-trip times by BETA (>1).
                    242:                 * Improve nstime for unused addresses by applying GAMMA.
                    243:                 * The GAMMA factor makes unused entries slowly
                    244:                 * improve, so they eventually get tried again.
                    245:                 * GAMMA should be slightly less than 1.
                    246:                 * Watch out for records that may have timed out
                    247:                 * and are no longer the correct type.                  XXX
                    248:                 */
                    249:                
                    250:                for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) {
                    251:                        ns2 = qs->nsdata;
                    252:                        if (ns2 == ns)
                    253:                            continue;
                    254:                        if (ns2->d_type != T_A ||
                    255:                            ns2->d_class != qs->ns->d_class)    /* XXX */
                    256:                                continue;
                    257:                        if (qs->stime.tv_sec) {
                    258:                            if (ns2->d_nstime == 0)
                    259:                                ns2->d_nstime = rtrip * BETA;
                    260:                            else
                    261:                                ns2->d_nstime =
                    262:                                    ns2->d_nstime * BETA + (1-ALPHA) * rtrip;
                    263:                            if (ns2->d_nstime > 1000000)
                    264:                                ns2->d_nstime = 1000000;
                    265:                        } else
                    266:                            ns2->d_nstime = ns2->d_nstime * GAMMA;
                    267: #ifdef DEBUG
                    268:                        if(debug > 1)
                    269:                            fprintf(ddt, "NS #%d %s rtt now %d\n", n,
                    270:                                inet_ntoa(qs->ns_addr.sin_addr),
                    271:                                ns2->d_nstime);
                    272: #endif DEBUG
                    273:                }
                    274:        }
                    275: 
                    276:        /*
                    277:         * Skip query section
                    278:         */
                    279:        addcount = 0;
                    280:        cp = msg + sizeof(HEADER);
                    281:        dpp = dnptrs;
                    282:        *dpp++ = msg;
                    283:        if ((*cp & INDIR_MASK) == 0)
                    284:                *dpp++ = cp;
                    285:        *dpp = NULL;
                    286:        if (hp->qdcount) {
                    287:                n = dn_skipname(cp, msg + msglen);
                    288:                if (n <= 0)
                    289:                        goto formerr;
                    290:                cp += n;
                    291:                GETSHORT(type, cp);
                    292:                GETSHORT(class, cp);
                    293:                if (cp - msg > msglen)
                    294:                        goto formerr;
                    295:        }
                    296: 
                    297:        /*
                    298:         * Save answers, authority, and additional records for future use.
                    299:         */
                    300:        ancount = ntohs(hp->ancount);
                    301:        aucount = ntohs(hp->nscount);
                    302:        arcount = ntohs(hp->arcount);
                    303:        nscount = 0;
                    304:        tp = cp;
                    305: #ifdef DEBUG
                    306:        if (debug >= 3)
                    307:                fprintf(ddt,"resp: ancount %d, aucount %d, arcount %d\n",
                    308:                        ancount, aucount, arcount);
                    309: #endif
                    310: 
                    311:        /*
                    312:         *  If there's an answer, check if it's a CNAME response;
                    313:         *  if no answer but aucount > 0, see if there is an NS
                    314:         *  or just an SOA.  (NOTE: ancount might be 1 with a CNAME,
                    315:         *  and NS records may still be in the authority section;
                    316:         *  we don't bother counting them, as we only use nscount
                    317:         *  if ancount == 0.)
                    318:         */
                    319:        if (ancount == 1 || (ancount == 0 && aucount > 0)) {
                    320:                c = aucount;
                    321:                do {
                    322:                        if (tp - msg >= msglen)
                    323:                                goto formerr;
                    324:                        n = dn_skipname(tp, msg + msglen);
                    325:                        if (n <= 0)
                    326:                                goto formerr;
                    327:                        tp += n;                /* name */
                    328:                        GETSHORT(i, tp);        /* type */
                    329:                        tp += sizeof(u_short);  /* class */
                    330:                        tp += sizeof(u_long);   /* ttl */
                    331:                        GETSHORT(count, tp);    /* dlen */
                    332:                        if (tp - msg > msglen - count)
                    333:                                goto formerr;
                    334:                        tp += count;
                    335:                        if (ancount && i == T_CNAME) {
                    336:                                cname++;
                    337: #ifdef DEBUG
                    338:                                if (debug)
                    339:                                        fprintf(ddt,"CNAME - needs more processing\n");
                    340: #endif
                    341:                                if (!qp->q_cmsglen) {
                    342:                                        qp->q_cmsg = qp->q_msg;
                    343:                                        qp->q_cmsglen = qp->q_msglen;
                    344:                                        qp->q_msg = NULL;
                    345:                                        qp->q_msglen = 0;
                    346:                                }
                    347:                        }
                    348:                        /*
                    349:                         * See if authority record is a nameserver.
                    350:                         */
                    351:                        if (ancount == 0 && i == T_NS)
                    352:                                nscount++;
                    353:                } while (--c > 0);
                    354:                tp = cp;
                    355:        }
                    356: 
                    357:        /*
                    358:         * Add the info received in the response to the Data Base
                    359:         */
                    360:        c = ancount + aucount + arcount;
                    361: #ifdef notdef
                    362:        /*
                    363:         * If the request was for a CNAME that doesn't exist,
                    364:         * but the name is valid, fetch any other data for the name.
                    365:         * DON'T do this now, as it will requery if data are already
                    366:         * in the cache (maybe later with negative caching).
                    367:         */
                    368:        if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR &&
                    369:           !qp->q_system) {
                    370: #ifdef DEBUG
                    371:                if (debug >= 3)
                    372:                        fprintf(ddt,"resp: leaving, no CNAME\n");
                    373: #endif
                    374:                /* Cause us to put it in the cache later */
                    375:                prime(class, T_ANY, qp);
                    376: 
                    377:                /* Nothing to store, just give user the answer */
                    378:                goto return_msg;
                    379:        }
                    380: #endif /* notdef */
                    381: 
                    382:        nspp = nsp;
                    383:        if (qp->q_system)
                    384:                dbflags = DB_NOTAUTH | DB_NODATA;
                    385:        else
                    386:                dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;
                    387:        for (i = 0; i < c; i++) {
                    388:                struct databuf *ns3;
                    389: 
                    390:                if (cp >= msg + msglen)
                    391:                        goto formerr;
                    392:                ns3 = 0;
                    393:                if ((n = doupdate(msg, msglen, cp, 0, &ns3, dbflags)) < 0) {
                    394: #ifdef DEBUG
                    395:                        if (debug)
                    396:                            fprintf(ddt,"resp: leaving, doupdate failed\n");
                    397: #endif
                    398:                        /* return code filled in by doupdate */
                    399:                        goto return_msg;
                    400:                }
                    401:                /*
                    402:                 * Remember nameservers from the authority section
                    403:                 * for referrals.
                    404:                 * (This is usually overwritten by findns below(?). XXX
                    405:                 */
                    406:                if (ns3 && i >= ancount && i < ancount + aucount &&
                    407:                    nspp < &nsp[NSMAX-1])
                    408:                        *nspp++ = ns3;
                    409:                cp += n;
                    410:        }
                    411: 
                    412:        if (qp->q_system && ancount) {
                    413:                if (qp->q_system == PRIMING_CACHE)
                    414:                        check_root();
                    415: #ifdef DEBUG
                    416:                if (debug > 2)
                    417:                        fprintf(ddt,"resp: leaving, SYSQUERY ancount %d\n", ancount);
                    418: #endif
                    419:                qremove(qp);
                    420:                return;
                    421:        }
                    422: 
                    423:        if (cp > msg + msglen)
                    424:                goto formerr;
                    425: 
                    426:        /*
                    427:         *  If there are addresses and this is a local query,
                    428:         *  sort them appropriately for the local context.
                    429:         */
                    430:        if (ancount > 1 && (lp = local(&qp->q_from)) != NULL) 
                    431:                sort_response(tp, ancount, lp, msg + msglen);
                    432: 
                    433:        /*
                    434:         * An answer to a T_ANY query or a successful answer to a
                    435:         * regular query with no indirection, then just return answer.
                    436:         */
                    437:        if ((hp->qdcount && type == T_ANY && ancount) ||
                    438:            (!cname && !qp->q_cmsglen && ancount)) {
                    439: #ifdef DEBUG
                    440:                if (debug >= 3)
                    441:                        fprintf(ddt,"resp: got as much answer as there is\n");
                    442: #endif
                    443:                goto return_msg;
                    444:        }
                    445: 
                    446:        /*
                    447:         * Eventually we will want to cache this negative answer.
                    448:         */
                    449:        if (ancount == 0 && nscount == 0 &&
                    450:            (hp->aa || fwd || class == C_ANY)) {
                    451:                /* We have an authoritative NO */
                    452: #ifdef DEBUG
                    453:                if (debug >= 3)
                    454:                        fprintf(ddt,"resp: leaving auth NO\n");
                    455: #endif
                    456:                if (qp->q_cmsglen) {
                    457:                        msg = (u_char *)qp->q_cmsg;
                    458:                        msglen = qp->q_cmsglen;
                    459:                        hp = (HEADER *)msg;
                    460:                }
                    461:                goto return_msg;
                    462:        }
                    463: 
                    464:        /*
                    465:         * All messages in here need further processing.  i.e. they
                    466:         * are either CNAMEs or we got referred again.
                    467:         */
                    468:        count = 0;
                    469:        founddata = 0;
                    470:        foundname = 0;
                    471:        dname = name;
                    472:        if (!cname && qp->q_cmsglen && ancount) {
                    473: #ifdef DEBUG
                    474:                if (debug)
                    475:                        fprintf(ddt,"Cname second pass\n");
                    476: #endif
                    477:                newmsglen = qp->q_cmsglen;
                    478:                bcopy(qp->q_cmsg, newmsg, newmsglen);
                    479:        } else {
                    480:                newmsglen = msglen;
                    481:                bcopy(msg, newmsg, newmsglen);
                    482:        }
                    483:        hp = (HEADER *) newmsg;
                    484:        hp->ancount = 0;
                    485:        hp->nscount = 0;
                    486:        hp->arcount = 0;
                    487:        dnptrs[0] = newmsg;
                    488:        dnptrs[1] = NULL;
                    489:        cp = newmsg + sizeof(HEADER);
                    490:        if (cname)
                    491:                cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ;
                    492:        if ((n = dn_expand(newmsg, newmsg + newmsglen,
                    493:                cp, dname, sizeof(name))) < 0) {
                    494: #ifdef DEBUG
                    495:                if (debug)
                    496:                        fprintf(ddt,"dn_expand failed\n" );
                    497: #endif
                    498:                goto servfail;
                    499:        }
                    500:        if (!cname)
                    501:                cp += n + QFIXEDSZ;
                    502:        buflen = sizeof(newmsg) - (cp - newmsg);
                    503: 
                    504: try_again:
                    505: #ifdef DEBUG
                    506:        if (debug)
                    507:                fprintf(ddt,"resp: nlookup(%s) type=%d\n",dname, type);
                    508: #endif
                    509:        fname = "";
                    510:        htp = hashtab;          /* lookup relative to root */
                    511:        np = nlookup(dname, &htp, &fname, 0);
                    512: #ifdef DEBUG
                    513:        if (debug)
                    514:                fprintf(ddt,"resp: %s '%s' as '%s' (cname=%d)\n",
                    515:                        np == NULL ? "missed" : "found", dname, fname, cname);
                    516: #endif
                    517:        if (np == NULL || fname != dname)
                    518:                goto fetch_ns;
                    519: 
                    520:        foundname++;
                    521:        count = cp - newmsg;
                    522:        n = finddata(np, class, type, hp, &dname, &buflen, &count);
                    523:        if (n == 0)
                    524:                goto fetch_ns;          /* NO data available */
                    525:        cp += n;
                    526:        buflen -= n;
                    527:        hp->ancount += count;
                    528:        if (fname != dname && type != T_CNAME && type != T_ANY) {
                    529:                cname++;
                    530:                goto try_again;
                    531:        }
                    532:        founddata = 1;
                    533: 
                    534: #ifdef DEBUG
                    535:        if (debug >= 3) {
                    536:            fprintf(ddt,"resp: foundname = %d count = %d ", foundname, count);
                    537:            fprintf(ddt,"founddata = %d cname = %d\n", founddata, cname);
                    538:        }
                    539: #endif
                    540: 
                    541: fetch_ns:
                    542:        hp->ancount = htons(hp->ancount);
                    543:        /*
                    544:         * Look for name servers to refer to and fill in the authority
                    545:         * section or record the address for forwarding the query
                    546:         * (recursion desired).
                    547:         */
                    548:        switch (findns(&np, class, nsp, &count)) {
                    549:        case NXDOMAIN:          /* shouldn't happen */
                    550: #ifdef DEBUG
                    551:                if (debug >= 3)
                    552:                        fprintf(ddt,"req: leaving (%s, rcode %d)\n",
                    553:                                dname, hp->rcode);
                    554: #endif
                    555:                if (!foundname)
                    556:                        hp->rcode = NXDOMAIN;
                    557:                if (class != C_ANY) {
                    558:                        hp->aa = 1;
                    559:                        /*
                    560:                         * should return SOA if founddata == 0,
                    561:                         * but old named's are confused by an SOA
                    562:                         * in the auth. section if there's no error.
                    563:                         */
                    564:                        if (foundname == 0 && np) {
                    565:                            n = doaddauth(hp, cp, buflen, np, nsp[0]);
                    566:                            cp += n;
                    567:                            buflen -= n;
                    568:                        }
                    569:                }
                    570:                goto return_newmsg;
                    571: 
                    572:        case SERVFAIL:
                    573:                goto servfail;
                    574:        }
                    575: 
                    576:        if (founddata) {
                    577:                hp = (HEADER *)newmsg;
                    578:                n = add_data(np, nsp, cp, buflen);
                    579:                if (n < 0) {
                    580:                        hp->tc = 1;
                    581:                        n = (-n);
                    582:                }
                    583:                cp += n;
                    584:                buflen -= n;
                    585:                hp->nscount = htons((u_short)count);
                    586:                goto return_newmsg;
                    587:        }
                    588: 
                    589:        /*
                    590:         *  If we get here, we don't have the answer yet and are about
                    591:         *  to iterate to try and get it.  First, infinite loop avoidance.
                    592:         */
                    593:        if (qp->q_nqueries++ > MAXQUERIES) {
                    594: #ifdef DEBUG
                    595:                if (debug)
                    596:                    fprintf(ddt,"resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",
                    597:                        dname, class, type);
                    598: #endif
                    599:                syslog(LOG_NOTICE,
                    600:                            "MAXQUERIES exceeded, possible data loop in resolving (%s)",
                    601:                            dname);
                    602:                goto servfail;
                    603:        }
                    604: 
                    605:        /* Reset the query control structure */
                    606:        qp->q_naddr = 0;
                    607:        qp->q_curaddr = 0;
                    608:        qp->q_fwd = fwdtab;
                    609:        if (nslookup(nsp, qp) == 0) {
                    610: #ifdef DEBUG
                    611:                if (debug >= 3)
                    612:                        fprintf(ddt,"resp: no addrs found for NS's\n");
                    613: #endif
                    614:                goto servfail;
                    615:        }
                    616:        for (n = 0; n < qp->q_naddr; n++)
                    617:                qp->q_addr[n].stime.tv_sec = 0;
                    618:        if (!qp->q_fwd)
                    619:                qp->q_addr[0].stime = tt;
                    620:        if (cname) {
                    621:                if (qp->q_cname++ == MAXCNAMES) {
                    622: #ifdef DEBUG
                    623:                        if (debug >= 3)
                    624:                                fprintf(ddt,"resp: leaving, MAXCNAMES exceeded\n");
                    625: #endif
                    626:                        goto servfail;
                    627:                }
                    628: #ifdef DEBUG
                    629:                if (debug)
                    630:                        fprintf(ddt,"q_cname = %d\n",qp->q_cname);
                    631:                if (debug >= 3)
                    632:                       fprintf(ddt,"resp: building recursive query; nslookup\n");
                    633: #endif
                    634:                if (qp->q_msg)
                    635:                        (void) free(qp->q_msg);
                    636:                if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
                    637: #ifdef DEBUG
                    638:                        if (debug)
                    639:                                fprintf(ddt,"resp: malloc error\n");
                    640: #endif
                    641:                        goto servfail;
                    642:                }
                    643:                qp->q_msglen = res_mkquery(QUERY, dname, class,
                    644:                    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
                    645:                hp = (HEADER *) qp->q_msg;
                    646:                hp->rd = 0;
                    647:        } else
                    648:                hp = (HEADER *)qp->q_msg;
                    649:        hp->id = qp->q_nsid = htons((u_short)++nsid);
                    650:        if (qp->q_fwd)
                    651:                hp->rd = 1;
                    652:        unsched(qp);
                    653:        schedretry(qp, retrytime(qp));
                    654: #ifdef DEBUG
                    655:        if (debug)
                    656:                fprintf(ddt,"resp: forw -> %s %d (%d) nsid=%d id=%d %dms\n",
                    657:                        inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
                    658:                        ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),
                    659:                        ntohs(qp->q_nsid), ntohs(qp->q_id),
                    660:                        qp->q_addr[0].nsdata->d_nstime);
                    661:        if ( debug >= 10)
                    662:                fp_query(msg, ddt);
                    663: #endif
                    664:        if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
                    665:                (struct sockaddr *)Q_NEXTADDR(qp,0),
                    666:                sizeof(struct sockaddr_in)) < 0) {
                    667: #ifdef DEBUG
                    668:                if (debug >= 5)
                    669:                        fprintf(ddt, "sendto error = %d\n", errno);
                    670: #endif
                    671:        }
                    672:        hp->rd = 0;     /* leave set to 0 for dup detection */
                    673: #ifdef STATS
                    674:        stats[S_OUTPKTS].cnt++;
                    675: #endif
                    676: #ifdef DEBUG
                    677:        if (debug >= 3)
                    678:                fprintf(ddt,"resp: Query sent.\n");
                    679: #endif
                    680:        return;
                    681: 
                    682: formerr:
                    683: #ifdef DEBUG
                    684:        if (debug)
                    685:            fprintf(ddt,"FORMERR resp() from %s size err %d, msglen %d\n",
                    686:                inet_ntoa(from_addr.sin_addr),
                    687:                cp-msg, msglen);
                    688: #endif
                    689:        syslog(LOG_INFO, "Malformed response from %s\n",
                    690:                inet_ntoa(from_addr.sin_addr));
                    691: #ifdef STATS
                    692:        stats[S_RESPFORMERR].cnt++;
                    693: #endif
                    694:        return;
                    695: 
                    696: return_msg:
                    697: #ifdef STATS
                    698:        stats[S_RESPOK].cnt++;
                    699: #endif
                    700:        /* The "standard" return code */
                    701:        hp->qr = 1;
                    702:        hp->id = qp->q_id;
                    703:        hp->rd = 1;
                    704:        hp->ra = 1;
                    705:        (void) send_msg(msg, msglen, qp);
                    706:        qremove(qp);
                    707:        return;
                    708: 
                    709: return_newmsg:
                    710: #ifdef STATS
                    711:        stats[S_RESPOK].cnt++;
                    712: #endif
                    713:        if (addcount) {
                    714:                n = doaddinfo(hp, cp, buflen);
                    715:                cp += n;
                    716:                buflen -= n;
                    717:        }
                    718: 
                    719:        hp->id = qp->q_id;
                    720:        hp->rd = 1;
                    721:        hp->ra = 1;
                    722:        hp->qr = 1;
                    723:        (void) send_msg(newmsg, cp - newmsg, qp);
                    724:        qremove(qp);
                    725:        return;
                    726: 
                    727: servfail:
                    728: #ifdef STATS
                    729:        stats[S_RESPFAIL].cnt++;
                    730: #endif
                    731:        hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
                    732:        hp->rcode = SERVFAIL;
                    733:        hp->id = qp->q_id;
                    734:        hp->rd = 1;
                    735:        hp->ra = 1;
                    736:        hp->qr = 1;
                    737:        (void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp);
                    738:        qremove(qp);
                    739:        return;
                    740: }
                    741: 
                    742: /*
                    743:  * Decode the resource record 'rrp' and update the database.
                    744:  * If savens is true, record pointer for forwarding queries a second time.
                    745:  */
                    746: doupdate(msg, msglen, rrp, zone, savens, flags)
                    747:        char *msg;
                    748:        u_char *rrp;
                    749:        struct databuf **savens;
                    750:        int  msglen, zone, flags;
                    751: {
                    752:        register u_char *cp;
                    753:        register int n;
                    754:        int class, type, dlen, n1;
                    755:        u_long ttl;
                    756:        struct databuf *dp;
                    757:        char dname[MAXDNAME];
                    758:        u_char *cp1;
                    759:        u_char data[BUFSIZ];
                    760:        register HEADER *hp = (HEADER *) msg;
                    761: #ifdef ALLOW_UPDATES
                    762:        int zonenum;
                    763: #endif
                    764: 
                    765: #ifdef DEBUG
                    766:        if (debug > 2)
                    767:                fprintf(ddt,"doupdate(zone %d, savens %x, flags %x)\n",
                    768:                        zone, savens, flags);
                    769: #endif
                    770: 
                    771:        cp = rrp;
                    772:        if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0) {
                    773:                hp->rcode = FORMERR;
                    774:                return (-1);
                    775:        }
                    776:        cp += n;
                    777:        GETSHORT(type, cp);
                    778:        GETSHORT(class, cp);
                    779:        GETLONG(ttl, cp);
                    780:        GETSHORT(dlen, cp);
                    781: #ifdef DEBUG
                    782:        if (debug > 2)
                    783:                fprintf(ddt,"doupdate: dname %s type %d class %d ttl %d\n",
                    784:                        dname, type, class, ttl);
                    785: #endif
                    786:        /*
                    787:         * Convert the resource record data into the internal
                    788:         * database format.
                    789:         */
                    790:        switch (type) {
                    791:        case T_A:
                    792:        case T_WKS:
                    793:        case T_HINFO:
                    794:        case T_UINFO:
                    795:        case T_UID:
                    796:        case T_GID:
                    797:        case T_TXT:
                    798: #ifdef ALLOW_T_UNSPEC
                    799:        case T_UNSPEC:
                    800: #endif ALLOW_T_UNSPEC
                    801:                cp1 = cp;
                    802:                n = dlen;
                    803:                cp += n;
                    804:                break;
                    805: 
                    806:        case T_CNAME:
                    807:        case T_MB:
                    808:        case T_MG:
                    809:        case T_MR:
                    810:        case T_NS:
                    811:        case T_PTR:
                    812:                if ((n = dn_expand(msg, msg + msglen, cp, data,
                    813:                   sizeof(data))) < 0) {
                    814:                        hp->rcode = FORMERR;
                    815:                        return (-1);
                    816:                }
                    817:                cp += n;
                    818:                cp1 = data;
                    819:                n = strlen(data) + 1;
                    820:                break;
                    821: 
                    822:        case T_MINFO:
                    823:        case T_SOA:
                    824:                if ((n = dn_expand(msg, msg + msglen, cp, data,
                    825:                    sizeof(data))) < 0) {
                    826:                        hp->rcode = FORMERR;
                    827:                        return (-1);
                    828:                }
                    829:                cp += n;
                    830:                cp1 = data + (n = strlen(data) + 1);
                    831:                n1 = sizeof(data) - n;
                    832:                if (type == T_SOA)
                    833:                        n1 -= 5 * sizeof(u_long);
                    834:                if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) {
                    835:                        hp->rcode = FORMERR;
                    836:                        return (-1);
                    837:                }
                    838:                cp += n;
                    839:                cp1 += strlen(cp1) + 1;
                    840:                if (type == T_SOA) {
                    841:                        bcopy(cp, cp1, n = 5 * sizeof(u_long));
                    842:                        cp += n;
                    843:                        cp1 += n;
                    844:                }
                    845:                n = cp1 - data;
                    846:                cp1 = data;
                    847:                break;
                    848: 
                    849:        case T_MX:
                    850:                /* grab preference */
                    851:                bcopy(cp,data,sizeof(u_short));
                    852:                cp1 = data + sizeof(u_short);
                    853:                cp += sizeof(u_short);
                    854: 
                    855:                /* get name */
                    856:                if ((n = dn_expand(msg, msg + msglen, cp, cp1,
                    857:                    sizeof(data)-sizeof(u_short))) < 0)
                    858:                        return(-1);
                    859:                cp += n;
                    860: 
                    861:                /* compute end of data */
                    862:                cp1 += strlen(cp1) + 1;
                    863:                /* compute size of data */
                    864:                n = cp1 - data;
                    865:                cp1 = data;
                    866:                break;
                    867: 
                    868:        default:
                    869: #ifdef DEBUG
                    870:                if (debug >= 3)
                    871:                        fprintf(ddt,"unknown type %d\n", type);
                    872: #endif
                    873:                return ((cp - rrp) + dlen);
                    874:        }
                    875:        if (n > MAXDATA) {
                    876: #ifdef DEBUG
                    877:                if (debug)
                    878:                    fprintf(ddt,
                    879:                        "update type %d: %d bytes is too much data\n",
                    880:                        type, n);
                    881: #endif
                    882:                hp->rcode = NOCHANGE;   /* XXX - FORMERR ??? */
                    883:                return(-1);
                    884:        }
                    885: 
                    886: #ifdef ALLOW_UPDATES
                    887:        /*
                    888:         * If this is a dynamic update request, process it specially; else,
                    889:         * execute normal update code.
                    890:         */
                    891:        switch(hp->opcode) {
                    892: 
                    893:        /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
                    894:        case UPDATEM:
                    895:        case UPDATEMA:
                    896: 
                    897:        /*
                    898:         * The named code for UPDATED and UPDATEDA is the same except that for
                    899:         * UPDATEDA we we ignore any data that was passed: we just delete all
                    900:         * RRs whose name, type, and class matches
                    901:         */
                    902:        case UPDATED:
                    903:        case UPDATEDA:
                    904:                if (type == T_SOA) {    /* Not allowed */
                    905: #ifdef DEBUG
                    906:                        if (debug)
                    907:                           fprintf(ddt, "UDPATE: REFUSED - SOA delete\n");
                    908: #endif
                    909:                        hp->rcode = REFUSED;
                    910:                        return(-1);
                    911:                }
                    912:                /*
                    913:                 * Don't check message length if doing UPDATEM/UPDATEMA,
                    914:                 * since the whole message wont have been demarshalled until
                    915:                 * we reach the code for UPDATEA
                    916:                 */
                    917:                if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
                    918:                        if (cp != (u_char *)(msg + msglen)) {
                    919: #ifdef DEBUG
                    920:                            if (debug)
                    921:                                fprintf(ddt,"FORMERR UPDATE message length off\n");
                    922: #endif
                    923:                            hp->rcode = FORMERR;
                    924:                            return(-1);
                    925:                        }
                    926:                }
                    927:                if ((zonenum = findzone(dname, class)) == 0) { 
                    928:                        hp->rcode = NXDOMAIN;
                    929:                        return(-1);
                    930:                }
                    931:                if (zones[zonenum].z_state & Z_DYNADDONLY) {
                    932:                        hp->rcode = NXDOMAIN;
                    933:                        return(-1);
                    934:                }
                    935:                if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
                    936:                        /* Make a dp for use in db_update, as old dp */
                    937:                        dp = savedata(class, type, 0, cp1, n);
                    938:                        dp->d_zone = zonenum;
                    939:                        n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
                    940:                                      hashtab);
                    941:                        if (n != OK) {
                    942: #ifdef DEBUG
                    943:                                if (debug)
                    944:                                    fprintf(ddt,"UPDATE: db_update failed\n");
                    945: #endif DEBUG
                    946:                                free( (struct databuf *) dp);
                    947:                                hp->rcode = NOCHANGE;
                    948:                                return(-1);
                    949:                        }
                    950:                } else {        /* UPDATEDA or UPDATEMA */
                    951:                        int DeletedOne = 0;
                    952:                        /* Make a dp for use in db_update, as old dp */
                    953:                        dp = savedata(class, type, 0, NULL, 0);
                    954:                        dp->d_zone = zonenum;
                    955:                        do {    /* Loop and delete all matching RR(s) */
                    956:                                n = db_update(dname, dp, NULL, DB_DELETE,
                    957:                                              hashtab);
                    958:                                if (n != OK)
                    959:                                        break;
                    960:                                DeletedOne++;
                    961:                        } while (1);
                    962:                        free( (struct databuf *) dp);
                    963:                        /* Ok for UPDATEMA not to have deleted any RRs */
                    964:                        if (!DeletedOne && hp->opcode == UPDATEDA) {
                    965: #ifdef DEBUG
                    966:                                if (debug)
                    967:                                        fprintf(ddt,"UPDATE: db_update failed\n");
                    968: #endif DEBUG
                    969:                                hp->rcode = NOCHANGE;
                    970:                                return(-1);
                    971:                        }
                    972:                }
                    973:                if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
                    974:                        return (cp - rrp);;
                    975:                /*
                    976:                 * Else unmarshal the RR to be added and continue on to
                    977:                 * UPDATEA code for UPDATEM/UPDATEMA
                    978:                 */
                    979:                if ((n =
                    980:                   dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
                    981: #ifdef DEBUG
                    982:                        if (debug)
                    983:                            fprintf(ddt,"FORMERR UPDATE expand name failed\n");
                    984: #endif
                    985:                        hp->rcode = FORMERR;
                    986:                        return(-1);
                    987:                }
                    988:                cp += n;
                    989:                GETSHORT(type, cp);
                    990:                GETSHORT(class, cp);
                    991:                GETLONG(ttl, cp);
                    992:                GETSHORT(n, cp);
                    993:                cp1 = cp;
                    994: /**** XXX - need bounds checking here ****/
                    995:                cp += n;
                    996: 
                    997:        case UPDATEA:
                    998:                if (n > MAXDATA) {
                    999: #ifdef DEBUG
                   1000:                        if (debug)
                   1001:                            fprintf(ddt,"UPDATE: too much data\n");
                   1002: #endif
                   1003:                        hp->rcode = NOCHANGE;
                   1004:                        return(-1);
                   1005:                }
                   1006:                if (cp != (u_char *)(msg + msglen)) {
                   1007: #ifdef DEBUG
                   1008:                        if (debug)
                   1009:                            fprintf(ddt,"FORMERR UPDATE message length off\n");
                   1010: #endif
                   1011:                        hp->rcode = FORMERR;
                   1012:                        return(-1);
                   1013:                }
                   1014:                if ((zonenum = findzone(dname, class)) == 0) { 
                   1015:                        hp->rcode = NXDOMAIN;
                   1016:                        return(-1);
                   1017:                }
                   1018:                if (zones[zonenum].z_state & Z_DYNADDONLY) {
                   1019:                        struct hashbuf *htp = hashtab;
                   1020:                        char *fname;
                   1021:                        if (nlookup(dname, &htp, &fname, 0) &&
                   1022:                            !strcmp(dname, fname)) {
                   1023: #ifdef DEBUG
                   1024:                            if (debug)
                   1025:                                fprintf(ddt,"refusing add of existing name\n");
                   1026: #endif
                   1027:                            hp->rcode = REFUSED;
                   1028:                            return(-1);
                   1029:                        }
                   1030:                }
                   1031:                dp = savedata(class, type, ttl, cp1, n);
                   1032:                dp->d_zone = zonenum;
                   1033:                if ((n = db_update(dname, NULL, dp, DB_NODATA,
                   1034:                                   hashtab)) != OK) {
                   1035: #ifdef DEBUG
                   1036:                        if (debug)
                   1037:                                fprintf(ddt,"UPDATE: db_update failed\n");
                   1038: #endif
                   1039:                        hp->rcode = NOCHANGE;
                   1040:                        return (-1);
                   1041:                }
                   1042:                else
                   1043:                        return (cp - rrp);
                   1044:        }
                   1045: #endif ALLOW_UPDATES
                   1046: 
                   1047:        if (zone == 0)
                   1048:                ttl += tt.tv_sec;
                   1049:        dp = savedata(class, type, ttl, cp1, n);
                   1050:        dp->d_zone = zone;
                   1051:        if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) {
                   1052: #ifdef DEBUG
                   1053:                if (debug && (n != DATAEXISTS))
                   1054:                        fprintf(ddt,"update failed (%d)\n", n);
                   1055:                else if (debug >= 3)
                   1056:                        fprintf(ddt,"update failed (DATAEXISTS)\n");
                   1057: #endif
                   1058:                (void) free((char *)dp);
                   1059:        } else if (type == T_NS && savens != NULL)
                   1060:                *savens = dp;
                   1061:        return (cp - rrp);
                   1062: }
                   1063: 
                   1064: send_msg(msg, msglen, qp)
                   1065:        char *msg;
                   1066:        int msglen;
                   1067:        struct qinfo *qp;
                   1068: {
                   1069:        extern struct qinfo *qhead;
                   1070: #ifdef DEBUG
                   1071:        struct qinfo *tqp;
                   1072: #endif DEBUG
                   1073: 
                   1074:        if (qp->q_system)
                   1075:                return(1);
                   1076: #ifdef DEBUG
                   1077:        if (debug) {
                   1078:                fprintf(ddt,"send_msg -> %s (%s %d %d) id=%d\n",
                   1079:                        inet_ntoa(qp->q_from.sin_addr), 
                   1080:                        qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",
                   1081:                        qp->q_stream == QSTREAM_NULL ? qp->q_dfd
                   1082:                                                     : qp->q_stream->s_rfd,
                   1083:                        ntohs(qp->q_from.sin_port),
                   1084:                        ntohs(qp->q_id));
                   1085:        }
                   1086:        if (debug>4)
                   1087:                for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
                   1088:                    fprintf(ddt, "qp %x q_id: %d  q_nsid: %d q_msglen: %d ",
                   1089:                        tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen);
                   1090:                    fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr,
                   1091:                        tqp->q_curaddr);
                   1092:                    fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next,
                   1093:                         qp->q_link);
                   1094:                }
                   1095:        if (debug >= 10)
                   1096:                fp_query(msg, ddt);
                   1097: #endif DEBUG
                   1098:        if (qp->q_stream == QSTREAM_NULL) {
                   1099:                if (sendto(qp->q_dfd, msg, msglen, 0,
                   1100:                    (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) {
                   1101: #ifdef DEBUG
                   1102:                        if (debug)
                   1103:                                fprintf(ddt, "sendto error errno= %d\n",errno);
                   1104: #endif
                   1105:                        return(1);
                   1106:                }
                   1107: #ifdef STATS
                   1108:                stats[S_OUTPKTS].cnt++;
                   1109: #endif
                   1110:        } else {
                   1111:                (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
                   1112:                sq_done(qp->q_stream);
                   1113:        }
                   1114:        return(0);
                   1115: }
                   1116: 
                   1117: prime(class, type, oqp)
                   1118:        int class, type;
                   1119:        register struct qinfo *oqp;
                   1120: {
                   1121:        char    dname[BUFSIZ];
                   1122: 
                   1123:        if (oqp->q_msg == NULL)
                   1124:                return;
                   1125:        if (dn_expand(oqp->q_msg, oqp->q_msg + oqp->q_msglen,
                   1126:            oqp->q_msg + sizeof(HEADER), dname, sizeof(dname)) < 0)
                   1127:                return;
                   1128: #ifdef DEBUG
                   1129:        if (debug >= 2)
                   1130:               fprintf(ddt,"prime: %s\n", dname);
                   1131: #endif
                   1132:        (void) sysquery(dname, class, type);
                   1133: }
                   1134: 
                   1135: 
                   1136: prime_cache()
                   1137: {
                   1138:        register struct qinfo *qp;
                   1139: 
                   1140: #ifdef DEBUG
                   1141:        if (debug)
                   1142:                fprintf(ddt,"prime_cache: priming = %d\n", priming);
                   1143: #endif
                   1144: #ifdef STATS
                   1145:        stats[S_PRIMECACHE].cnt++;
                   1146: #endif
                   1147:        if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {
                   1148:                priming++;
                   1149:                if ((qp = sysquery("", C_IN, T_NS)) == NULL)
                   1150:                        priming = 0;
                   1151:                else
                   1152:                        qp->q_system = PRIMING_CACHE;
                   1153:        }
                   1154:        needs_prime_cache = 0;
                   1155:        return;
                   1156: }
                   1157: 
                   1158: struct qinfo *
                   1159: sysquery(dname, class, type)
                   1160:        char *dname;
                   1161:        int class, type;
                   1162: {
                   1163:        extern struct qinfo *qhead;
                   1164:        extern int nsid;
                   1165:        register struct qinfo *qp, *oqp;
                   1166:        register HEADER *hp;
                   1167:        struct namebuf *np;
                   1168:        struct databuf *nsp[NSMAX];
                   1169:        struct hashbuf *htp;
                   1170:        char *fname;
                   1171:        int count;
                   1172: 
                   1173: #ifdef DEBUG
                   1174:        if (debug > 2)
                   1175:               fprintf(ddt,"sysquery(%s, %d, %d)\n", dname, class, type);
                   1176: #endif
                   1177: #ifdef STATS
                   1178:        stats[S_SYSQUERIES].cnt++;
                   1179: #endif
                   1180:        htp = hashtab;
                   1181:        if (priming && dname[0] == '\0')
                   1182:                np = NULL;
                   1183:        else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
                   1184: #ifdef DEBUG
                   1185:                if (debug)
                   1186:                        fprintf(ddt,"sysquery: nlookup error on %s?\n", dname);
                   1187: #endif
                   1188:                return(0);
                   1189:        }
                   1190: 
                   1191:        switch (findns(&np, class, nsp, &count)) {
                   1192:        case NXDOMAIN:
                   1193:        case SERVFAIL:
                   1194: #ifdef DEBUG
                   1195:                if (debug)
                   1196:                        fprintf(ddt,"sysquery: findns error on %s?\n", dname);
                   1197: #endif
                   1198:                return(0);
                   1199:        }
                   1200: 
                   1201:        /* build new qinfo struct */
                   1202:        qp = qnew();
                   1203:        qp->q_cmsg = qp->q_msg = NULL;
                   1204:        qp->q_dfd = ds;
                   1205:        qp->q_fwd = fwdtab;
                   1206:        qp->q_system++;
                   1207: 
                   1208:        if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
                   1209:                qfree(qp);
                   1210:                return(0);
                   1211:        }
                   1212:        qp->q_msglen = res_mkquery(QUERY, dname, class,
                   1213:            type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
                   1214:        hp = (HEADER *) qp->q_msg;
                   1215:        hp->id = qp->q_nsid = htons((u_short)++nsid);
                   1216:        hp->rd = (qp->q_fwd ? 1 : 0);
                   1217: 
                   1218:        /* First check for an already pending query for this data */
                   1219:        for (oqp = qhead; oqp!=QINFO_NULL; oqp = oqp->q_link) {
                   1220:                if (oqp != qp && oqp->q_msglen == qp->q_msglen &&
                   1221:             bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0) {
                   1222: #ifdef DEBUG
                   1223:                        if (debug >= 3)
                   1224:                                fprintf(ddt, "sysquery: duplicate\n");
                   1225: #endif
                   1226:                        qfree(qp);
                   1227:                        return(0);
                   1228:                }
                   1229:        }
                   1230: 
                   1231:        if (nslookup(nsp, qp) == 0) {
                   1232: #ifdef DEBUG
                   1233:                if (debug)
                   1234:                        fprintf(ddt,"resp: no addrs found for NS's\n");
                   1235: #endif
                   1236:                qfree(qp);
                   1237:                return(0);
                   1238:        }
                   1239: 
                   1240:        schedretry(qp, retrytime(qp));
                   1241:        if (qp->q_fwd == 0)
                   1242:                qp->q_addr[0].stime = tt;
                   1243: 
                   1244: #ifdef DEBUG
                   1245:        if (debug)
                   1246:            fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %dms\n",
                   1247:                inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
                   1248:                qp->q_dfd, ntohs(Q_NEXTADDR(qp,0)->sin_port),
                   1249:                ntohs(qp->q_nsid), ntohs(qp->q_id),
                   1250:                qp->q_addr[0].nsdata->d_nstime);
                   1251:        if ( debug >= 10)
                   1252:            fp_query(qp->q_msg, ddt);
                   1253: #endif
                   1254:        if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,
                   1255:            (struct sockaddr *)Q_NEXTADDR(qp,0),
                   1256:            sizeof(struct sockaddr_in)) < 0){
                   1257: #ifdef DEBUG
                   1258:            if (debug)
                   1259:                fprintf(ddt, "sendto error errno= %d\n",errno);
                   1260: #endif
                   1261:        }
                   1262: #ifdef STATS
                   1263:        stats[S_OUTPKTS].cnt++;
                   1264: #endif
                   1265:        return(qp);
                   1266: }
                   1267: 
                   1268: /*
                   1269:  * Check the list of root servers after receiving a response
                   1270:  * to a query for the root servers.
                   1271:  */
                   1272: check_root()
                   1273: {
                   1274:        register struct databuf *dp, *pdp;
                   1275:        register struct namebuf *np;
                   1276:        int count = 0;
                   1277: 
                   1278:        priming = 0;
                   1279:        for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
                   1280:                if (np->n_dname[0] == '\0')
                   1281:                        break;
                   1282:        if (np == NULL) {
                   1283:                syslog(LOG_ERR, "check_root: Can't find root!\n");
                   1284:                return;
                   1285:        }
                   1286:        for (dp = np->n_data; dp != NULL; dp = dp->d_next)
                   1287:                if (dp->d_type == T_NS)
                   1288:                        count++;
                   1289: #ifdef DEBUG
                   1290:        if (debug)
                   1291:            fprintf(ddt,"%d root servers\n", count);
                   1292: #endif
                   1293:        if (count < MINROOTS) {
                   1294:                syslog(LOG_WARNING,
                   1295:                "check_root: %d root servers after query to root server < min",
                   1296:                    count);
                   1297:                return;
                   1298:        }
                   1299:        pdp = NULL;
                   1300:        dp = np->n_data;
                   1301:        while (dp != NULL) {
                   1302:                if (dp->d_type == T_NS && dp->d_zone == 0 &&
                   1303:                    dp->d_ttl < tt.tv_sec) {
                   1304: #ifdef DEBUG
                   1305:                        if (debug)
                   1306:                            fprintf(ddt,"deleting old root server '%s'\n",
                   1307:                                dp->d_data);
                   1308: #endif
                   1309:                        dp = rm_datum(dp, np, pdp);
                   1310:                        /* SHOULD DELETE FROM HINTS ALSO */
                   1311:                        continue;
                   1312:                }
                   1313:                pdp = dp;
                   1314:                dp = dp->d_next;
                   1315:        }
                   1316:        check_ns();
                   1317: }
                   1318: 
                   1319: /* 
                   1320:  * Check the root to make sure that for each NS record we have a A RR
                   1321:  */
                   1322: check_ns()
                   1323: {
                   1324:        register struct databuf *dp, *tdp;
                   1325:        register struct namebuf *np, *tnp;
                   1326:        struct hashbuf *htp;
                   1327:        char *dname;
                   1328:        int found_arr;
                   1329:        char *fname;
                   1330:        time_t curtime;
                   1331: 
                   1332: #ifdef DEBUG
                   1333:        if (debug >= 2)
                   1334:               fprintf(ddt,"check_ns()\n");
                   1335: #endif
                   1336: #ifdef STATS
                   1337:        stats[S_CHECKNS].cnt++;
                   1338: #endif
                   1339: 
                   1340:        curtime = (u_long) tt.tv_sec;
                   1341:        for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {
                   1342:                if (np->n_dname[0] != 0)
                   1343:                        continue;
                   1344:                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                   1345:                        if (dp->d_type != T_NS)
                   1346:                            continue;
                   1347: 
                   1348:                        /* look for A records */
                   1349:                        dname = dp->d_data;
                   1350:                        htp = hashtab;
                   1351:                        tnp = nlookup(dname, &htp, &fname, 0);
                   1352:                        if (tnp == NULL || fname != dname) {
                   1353: #ifdef DEBUG
                   1354:                            if (debug >= 3)
                   1355:                                fprintf(ddt,"check_ns: %s: not found %s %x\n",
                   1356:                                        dname, fname, tnp);
                   1357: #endif
                   1358:                            (void) sysquery(dname, dp->d_class, T_A);
                   1359:                            continue;
                   1360:                        }
                   1361:                        /* look for name server addresses */
                   1362:                        found_arr = 0;
                   1363:                        for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) {
                   1364:                            if (tdp->d_type != T_A ||
                   1365:                               tdp->d_class != dp->d_class)
                   1366:                                continue;
                   1367:                            if ((tdp->d_zone == 0) &&
                   1368:                                (tdp->d_ttl < curtime)) {
                   1369: #ifdef DEBUG
                   1370:                                if (debug >= 3)
                   1371:                                    fprintf(ddt,"check_ns: stale entry '%s'\n",
                   1372:                                        tnp->n_dname);
                   1373: #endif
                   1374:                                /* Cache invalidate the address RR's */
                   1375:                                delete_all(tnp, dp->d_class, T_A);
                   1376:                                found_arr = 0;
                   1377:                                break;
                   1378:                            }
                   1379:                            found_arr++;
                   1380:                        }
                   1381:                        if (!found_arr)
                   1382:                            (void) sysquery(dname, dp->d_class, T_A);
                   1383:                }
                   1384:        }
                   1385: }
                   1386: 
                   1387: #define        MAXCLASS 255            /* belongs elsewhere */
                   1388: int    norootlogged[MAXCLASS];
                   1389: 
                   1390: /*
                   1391:  *  Find NS's or an SOA for the given dname (np) and fill in the
                   1392:  *  nsp array.  Returns OK on success, and SERVFAIL on error.
                   1393:  *  We return NXDOMAIN to indicate we are authoritative.
                   1394:  */
                   1395: findns(npp, class, nsp, countp)
                   1396:        register struct namebuf **npp;
                   1397:        struct databuf **nsp;
                   1398:        int *countp;
                   1399: {
                   1400:        register struct namebuf *np = *npp;
                   1401:        register struct databuf *dp;
                   1402:        register struct databuf **nspp;
                   1403:        struct hashbuf *htp = hashtab;
                   1404:        
                   1405:        if (priming && (np == NULL || np->n_dname[0] == '\0'))
                   1406:                htp = fcachetab;
                   1407: try_again:
                   1408:        if (htp == fcachetab)
                   1409:                needs_prime_cache = 1;
                   1410:        while (np == NULL && htp != NULL) {
                   1411: #ifdef DEBUG
                   1412:                if (debug > 2)
                   1413:                        fprintf(ddt, "findns: using %s\n", htp == hashtab ?
                   1414:                                "cache" : "hints");
                   1415: #endif
                   1416:                for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
                   1417:                        if (np->n_dname[0] == '\0')
                   1418:                                break;
                   1419:                htp = (htp == hashtab ? fcachetab : NULL);      /* Fallback */
                   1420:        }
                   1421:        while(np != NULL) {
                   1422: #ifdef DEBUG
                   1423:                if (debug >= 5)
                   1424:                        fprintf(ddt, "findns: np 0x%x\n", np);
                   1425: #endif
                   1426:                /* Look first for SOA records. */
                   1427:                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                   1428:                        if (dp->d_zone != 0 && match(dp, class, T_SOA)) {
                   1429: #ifdef DEBUG
                   1430:                                if (debug >= 3)
                   1431:                                        fprintf(ddt,"findns: SOA found\n");
                   1432: #endif
                   1433:                                if (zones[dp->d_zone].z_auth) {
                   1434:                                        *npp = np;
                   1435:                                        nsp[0] = dp;
                   1436:                                        return(NXDOMAIN);
                   1437:                                } else
                   1438:                                        return (SERVFAIL);
                   1439:                        }
                   1440:                }
                   1441: 
                   1442:                /* If no SOA records, look for NS records. */
                   1443:                nspp = &nsp[0];
                   1444:                *nspp = NULL;
                   1445:                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                   1446:                        if (dp->d_type != T_NS ||
                   1447:                            (dp->d_class != class && class != C_ANY))
                   1448:                                continue;
                   1449:                        /*
                   1450:                         * Don't use records that may become invalid to
                   1451:                         * reference later when we do the rtt computation.
                   1452:                         * Never delete our safety-belt information!
                   1453:                         */
                   1454:                        if ((dp->d_zone == 0) &&
                   1455:                            (dp->d_ttl < (tt.tv_sec+900)) &&
                   1456:                            !(dp->d_flags & DB_F_HINT)) {
                   1457: #ifdef DEBUG
                   1458:                                if (debug)
                   1459:                                        fprintf(ddt,"findns: stale entry '%s'\n",
                   1460:                                                    np->n_dname);
                   1461: #endif
                   1462:                                /* Cache invalidate the NS RR's */
                   1463:                                if (dp->d_ttl < tt.tv_sec)
                   1464:                                        delete_all(np, class, T_NS);
                   1465:                                goto try_parent;
                   1466:                        }
                   1467:                        if (nspp < &nsp[NSMAX-1])
                   1468:                                *nspp++ = dp;
                   1469:                }
                   1470: 
                   1471:                *countp = nspp - nsp;
                   1472:                if (*countp > 0) {
                   1473: #ifdef DEBUG
                   1474:                        if (debug >= 3)
                   1475:                                fprintf(ddt,"findns: %d NS's added for '%s'\n",
                   1476:                                        *countp, np->n_dname);
                   1477: #endif
                   1478:                        *nspp = NULL;
                   1479:                        *npp = np;
                   1480:                        return(OK);     /* Success, got some NS's */
                   1481:                }
                   1482: try_parent:
                   1483:                np = np->n_parent;
                   1484:        }
                   1485:        if (htp)
                   1486:                goto try_again;
                   1487: #ifdef DEBUG
                   1488:        if (debug)
                   1489:                fprintf(ddt, "findns: No root nameservers for class %d?\n",
                   1490:                    class);
                   1491: #endif
                   1492:        if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
                   1493:                norootlogged[class] = 1;
                   1494:                syslog(LOG_ERR, "No root nameservers for class %d\n", class);
                   1495:        }
                   1496:        return(SERVFAIL);
                   1497: }
                   1498: 
                   1499: /*
                   1500:  *  Extract RR's from the given node that match class and type.
                   1501:  *  Return number of bytes added to response.
                   1502:  *  If no matching data is found, then 0 is returned.
                   1503:  */
                   1504: finddata(np, class, type, hp, dnamep, lenp, countp)
                   1505:        struct namebuf *np;
                   1506:        int class, type;
                   1507:        register HEADER *hp;
                   1508:        char **dnamep;
                   1509:        int *lenp, *countp;
                   1510: {
                   1511:        register struct databuf *dp;
                   1512:        register char *cp;
                   1513:        int buflen, n, count = 0, foundstale = 0;
                   1514: 
                   1515:        buflen = *lenp;
                   1516:        cp = ((char *)hp) + *countp;
                   1517:        for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                   1518:                if (!wanted(dp, class, type)) {
                   1519:                        if (type == T_CNAME && class == dp->d_class) {
                   1520:                                /* any data means no CNAME exists */
                   1521:                                *countp = 0;
                   1522:                                return(0);
                   1523:                        }
                   1524:                        continue;
                   1525:                }
                   1526:                if (stale(dp)) {
                   1527:                        /*
                   1528:                         * Don't use stale data.
                   1529:                         * Would like to call delete_all here
                   1530:                         * and continue, but the data chain would get
                   1531:                         * munged; can't restart, as make_rr has side
                   1532:                         * effects (leaving pointers in dnptr).
                   1533:                         * Just skip this entry for now
                   1534:                         * and call delete_all at the end.
                   1535:                         */
                   1536: #ifdef DEBUG
                   1537:                        if (debug >=3)
                   1538:                           fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname);
                   1539: #endif
                   1540:                        if (dp->d_zone == 0)
                   1541:                                foundstale++;
                   1542:                        continue;
                   1543:                }
                   1544:                if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) {
                   1545:                        hp->tc = 1;
                   1546:                        *countp = count;
                   1547:                        return(*lenp - buflen);
                   1548:                }
                   1549: 
                   1550:                cp += n;
                   1551:                buflen -= n;
                   1552:                count++;
                   1553: #ifdef notdef
                   1554:                /* this isn't right for glue records, aa is set in ns_req */
                   1555:                if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY)
                   1556:                        hp->aa = 1;                     /* XXX */
                   1557: #endif
                   1558:                if (dp->d_type == T_CNAME) {
                   1559:                        if (type != T_ANY) {    /* or T_NS? */
                   1560:                                *dnamep = dp->d_data;
                   1561:                                if (dp->d_zone && zones[dp->d_zone].z_auth &&
                   1562:                                    class != C_ANY)             /* XXX */
                   1563:                                        hp->aa = 1;             /* XXX */
                   1564:                        }
                   1565:                        break;
                   1566:                }
                   1567:        }
                   1568:        /*
                   1569:         * Cache invalidate the other RR's of same type
                   1570:         * if some have timed out
                   1571:         */
                   1572:        if (foundstale)
                   1573:                delete_all(np, class, type);
                   1574: #ifdef DEBUG
                   1575:        if (debug >=3)
                   1576:                fprintf(ddt,"finddata: added %d class %d type %d RRs\n",
                   1577:                        count, class, type);
                   1578: #endif
                   1579:        *countp = count;
                   1580:        return(*lenp - buflen);
                   1581: }
                   1582: 
                   1583: /*
                   1584:  * Do we want this data record based on the class and type?
                   1585:  */
                   1586: wanted(dp, class, type)
                   1587:        struct databuf *dp;
                   1588:        int class, type;
                   1589: {
                   1590: 
                   1591: #ifdef DEBUG
                   1592:        if (debug > 3)
                   1593:                fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type,
                   1594:                        dp->d_class, dp->d_type);
                   1595: #endif
                   1596: 
                   1597:        if (dp->d_class != class && class != C_ANY)
                   1598:                return (0);
                   1599:        if (type == dp->d_type)
                   1600:                return (1);
                   1601:        switch (dp->d_type) {
                   1602:        case T_ANY:
                   1603:        case T_CNAME:
                   1604:                return (1);
                   1605:        }
                   1606:        switch (type) {
                   1607:        case T_ANY:
                   1608:                return (1);
                   1609: 
                   1610:        case T_MAILB:
                   1611:                switch (dp->d_type) {
                   1612:                case T_MR:
                   1613:                case T_MB:
                   1614:                case T_MG:
                   1615:                case T_MINFO:
                   1616:                        return (1);
                   1617:                }
                   1618:                break;
                   1619: 
                   1620:        case T_AXFR:
                   1621:                if (dp->d_type == T_SOA)
                   1622:                        return (1);
                   1623:        }
                   1624:        return (0);
                   1625: }
                   1626: 
                   1627: /*
                   1628:  *  Add RR entries from dpp array to a query/response.
                   1629:  *  Return the number of bytes added or negative the amount
                   1630:  *  added if truncation was required.  Typically you are
                   1631:  *  adding NS records to a response.
                   1632:  */
                   1633: add_data(np, dpp, cp, buflen)
                   1634:        struct namebuf *np;
                   1635:        struct databuf **dpp;
                   1636:        register char *cp;
                   1637:        int buflen;
                   1638: {
                   1639:        register struct databuf *dp;
                   1640:        char dname[MAXDNAME];
                   1641:        register int n, count = 0;
                   1642: 
                   1643:        getname(np, dname, sizeof(dname));
                   1644:        for(dp = *dpp++; dp != NULL; dp = *dpp++) {
                   1645:                if (stale(dp))
                   1646:                        continue;       /* ignore old cache entry */
                   1647:                if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0)
                   1648:                        return(-count);         /* Truncation */
                   1649:                cp += n;
                   1650:                buflen -= n;
                   1651:                count += n;
                   1652:        }
                   1653:        return(count);
                   1654: }
                   1655: 
                   1656: /*
                   1657:  *  This is best thought of as a "cache invalidate" function.
                   1658:  *  It is called whenever a piece of data is determined to have
                   1659:  *  timed out.  It is better to have no information, than to
                   1660:  *  have partial information you pass off as complete.
                   1661:  */
                   1662: delete_all(np, class, type)
                   1663: register struct namebuf *np;
                   1664: int class, type;
                   1665: {
                   1666:        register struct databuf *dp, *pdp;
                   1667: 
                   1668: #ifdef DEBUG
                   1669:        if (debug > 2)
                   1670:                fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n",
                   1671:                            np->n_dname, np, class, type);
                   1672: #endif
                   1673:        pdp = NULL;
                   1674:        dp = np->n_data;
                   1675:        while (dp != NULL) {
                   1676:                if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)
                   1677:                    && match(dp, class, type)) {
                   1678:                        dp = rm_datum(dp, np, pdp);
                   1679:                        continue;
                   1680:                }
                   1681:                pdp = dp;
                   1682:                dp = dp->d_next;
                   1683:        }
                   1684: }

unix.superglobalmegacorp.com

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