Annotation of 43BSDTahoe/etc/named/ns_resp.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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