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

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)ns_forw.c  4.3 (Berkeley) 6/4/86";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1986 Regents of the University of California
        !             7:  *     All Rights Reserved
        !             8:  */
        !             9: 
        !            10: #include <stdio.h>
        !            11: #include <sys/types.h>
        !            12: #include <sys/socket.h>
        !            13: #include <sys/time.h>
        !            14: #include <netinet/in.h>
        !            15: #include <syslog.h>
        !            16: #include <arpa/nameser.h>
        !            17: #include "ns.h"
        !            18: #include "db.h"
        !            19: 
        !            20: struct qinfo *qhead = QINFO_NULL;      /* head of allocated queries */
        !            21: struct qinfo *retryqp = QINFO_NULL;    /* list of queries to retry */
        !            22: 
        !            23: int    nsid;                           /* next forwarded query id */
        !            24: extern int errno;
        !            25: 
        !            26: /*
        !            27:  * Forward the query to get the answer since its not in the database.
        !            28:  */
        !            29: ns_forw(nsp, msg, msglen, fp, qsp)
        !            30:        struct databuf *nsp[];
        !            31:        char *msg;
        !            32:        int msglen;
        !            33:        struct sockaddr_in *fp;
        !            34:        struct qstream *qsp;
        !            35: {
        !            36:        register struct qinfo *qp;
        !            37:        HEADER *hp;
        !            38:        u_short id;
        !            39:        extern char *calloc();
        !            40:        extern char *malloc();
        !            41: 
        !            42: #ifdef DEBUG
        !            43:        if (debug > 3)
        !            44:                fprintf(ddt,"ns_forw()\n");
        !            45: #endif
        !            46: 
        !            47:        /* Don't forward if we're already working on it. */
        !            48:        hp = (HEADER *) msg;
        !            49:        id = hp->id;
        !            50:        hp->rd = 0;
        !            51:        /* Look at them all */
        !            52:        for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
        !            53:                if (qp->q_id == id && qp->q_msglen == msglen &&
        !            54:                    bcmp((char *)qp->q_msg+2, msg+2, msglen-2) == 0)
        !            55:                        return (0);
        !            56:        }
        !            57: 
        !            58:        qp = qnew();
        !            59:        qp->q_naddr = 0;
        !            60:        if (nslookup(nsp, qp) == 0) {
        !            61: #ifdef DEBUG
        !            62:                if (debug >= 5)
        !            63:                        fprintf(ddt,"none found in nsp\n");
        !            64: #endif
        !            65:                qfree(qp);
        !            66:                return (-1);
        !            67:        }
        !            68:        qp->q_stream = qsp;
        !            69:        qp->q_curaddr = 0;
        !            70:        qp->q_id = id;
        !            71:        hp->id = qp->q_nsid = htons((u_short)++nsid);
        !            72:        hp->ancount = 0;
        !            73:        hp->nscount = 0;
        !            74:        hp->arcount = 0;
        !            75:        qp->q_from = *fp;
        !            76:        if ((qp->q_msg = malloc((unsigned)msglen)) == NULL) {
        !            77:                syslog(LOG_ERR, "forw: %m");
        !            78:                exit(1);
        !            79:        }
        !            80:        bcopy(msg, qp->q_msg, qp->q_msglen = msglen);
        !            81: 
        !            82:        schedretry(qp, (time_t)RETRYTIME);
        !            83: #ifdef DEBUG
        !            84:        if (debug)
        !            85:                fprintf(ddt,"forw -> %s (%d)\n",
        !            86:                        inet_ntoa(qp->q_addr[0].sin_addr),
        !            87:                        ntohs(qp->q_addr[0].sin_port));
        !            88:        if ( debug >= 10)
        !            89:                fp_query(msg, ddt);
        !            90: #endif
        !            91:        if (sendto(ds, msg, msglen, 0, &qp->q_addr[0],
        !            92:            sizeof(qp->q_addr[0])) < 0) {
        !            93: #ifdef DEBUG
        !            94:                if (debug >= 5)
        !            95:                        fprintf(ddt,"error forwarding msg\n");
        !            96: #endif
        !            97:        }
        !            98:        return (0);
        !            99: }
        !           100: 
        !           101: /*
        !           102:  * Lookup the address for each nameserver in `nsp' and add it to
        !           103:  * the list saved in the qinfo structure.
        !           104:  */
        !           105: nslookup(nsp, qp)
        !           106:        struct databuf *nsp[];
        !           107:        struct qinfo *qp;
        !           108: {
        !           109:        register struct namebuf *np;
        !           110:        register struct databuf *dp, *pdp;
        !           111:        register int n, i;
        !           112:        struct databuf *tmp;
        !           113:        struct hashbuf *htp;
        !           114:        char *dname, *fname;
        !           115:        int naddr, class;
        !           116:        time_t curtime;
        !           117: 
        !           118:        extern short ns_port;
        !           119: 
        !           120: #ifdef DEBUG
        !           121:        if (debug >= 3)
        !           122:                fprintf(ddt,"nslookup(nsp=x%x,qp=x%x)\n",nsp,qp);
        !           123: #endif
        !           124: 
        !           125:        naddr = n = qp->q_naddr;
        !           126:        curtime = (u_long) tt.tv_sec;
        !           127:        while ((dp = *nsp++) != NULL) {
        !           128:                dname = dp->d_data;
        !           129:                class = dp->d_class;
        !           130:                htp = hashtab;          /* lookup relative to root */
        !           131:                np = nlookup(dname, &htp, &fname, 0);
        !           132:                if (np == NULL || fname != dname) {
        !           133: #ifdef DEBUG
        !           134:                        if (debug >= 5)
        !           135:                                fprintf(ddt,"%s: not found\n", dname);
        !           136: #endif
        !           137:                        continue;
        !           138:                }
        !           139:                /* look for name server addresses */
        !           140:                pdp = NULL;
        !           141:                dp = np->n_data;
        !           142:                while (dp != NULL) {
        !           143:                        if (!match(dp, class, T_A))
        !           144:                                goto skip;
        !           145:                        if ((dp->d_zone == 0) && (dp->d_ttl < curtime)) {
        !           146:                                /* delete old cache entry */
        !           147: #ifdef DEBUG
        !           148:                                if (debug >= 5)
        !           149:                                        fprintf(ddt,"deleting cache entry\n");
        !           150: #endif
        !           151:                                rminv(dp);
        !           152:                                tmp = dp->d_next;                       
        !           153:                                (void) free((char *)dp);
        !           154:                                dp = tmp;
        !           155:                                if (pdp == NULL)
        !           156:                                        np->n_data = dp;
        !           157:                                else
        !           158:                                        pdp->d_next = dp;
        !           159:                                continue;
        !           160:                        }
        !           161:                        /* don't put in duplicates */
        !           162:                        for (i = 0; i < n; i++)
        !           163:                                if (bcmp((char *)&qp->q_addr[i].sin_addr,
        !           164:                                    dp->d_data, sizeof(struct in_addr)) == 0)
        !           165:                                        goto skip;
        !           166:                        if (n >= MAXNS)
        !           167:                                break;
        !           168:                        qp->q_addr[n].sin_family = AF_INET;
        !           169:                        qp->q_addr[n].sin_addr = *(struct in_addr *)dp->d_data;
        !           170:                        qp->q_addr[n].sin_port = (u_short)ns_port;
        !           171:                        qp->q_nretry[n] = 0;
        !           172:                        n++;
        !           173:                skip:   pdp = dp;
        !           174:                        dp = dp->d_next;
        !           175:                }
        !           176:                if (n >= MAXNS) {
        !           177: #ifdef DEBUG
        !           178:                        if (debug >= 5)
        !           179:                                fprintf(ddt,"q_addr table full\n");
        !           180: #endif
        !           181:                        break;
        !           182:                }
        !           183:        }
        !           184:        qp->q_naddr = n;
        !           185:        return (n - naddr);
        !           186: }
        !           187: 
        !           188: /*
        !           189:  * Arrange that forwarded query (qp) is retried after t seconds.
        !           190:  */
        !           191: schedretry(qp, t)
        !           192:        struct qinfo *qp;
        !           193:        time_t t;
        !           194: {
        !           195:        register struct qinfo *qp1, *qp2;
        !           196: 
        !           197: #ifdef DEBUG
        !           198:        if (debug > 3) {
        !           199:                fprintf(ddt,"schedretry(%#x, %d)\n", qp, t);
        !           200:                if (qp->q_time)
        !           201:                   fprintf(ddt,"WARNING: schedretry(%x,%d) q_time already %d\n",                    qp->q_time);
        !           202:        }
        !           203: #endif
        !           204:        t += (u_long) tt.tv_sec;
        !           205:        qp->q_time = t;
        !           206: 
        !           207:        if ((qp1 = retryqp) == NULL) {
        !           208:                retryqp = qp;
        !           209:                qp->q_next = NULL;
        !           210:                return;
        !           211:        }
        !           212:        while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t)
        !           213:                qp1 = qp2;
        !           214:        qp1->q_next = qp;
        !           215:        qp->q_next = qp2;
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Unsched is called to remove a forwarded query entry.
        !           220:  */
        !           221: unsched(qp)
        !           222:        struct qinfo *qp;
        !           223: {
        !           224:        register struct qinfo *np;
        !           225: 
        !           226: #ifdef DEBUG
        !           227:        if (debug > 3) {
        !           228:                fprintf(ddt,"unsched(%#x, %d )\n", qp, qp->q_id);
        !           229:        }
        !           230: #endif
        !           231:        if( retryqp == qp )  {
        !           232:                retryqp = qp->q_next;
        !           233:        } else {
        !           234:                for( np=retryqp; np->q_next != QINFO_NULL; np = np->q_next ) {
        !           235:                        if( np->q_next != qp)
        !           236:                                continue;
        !           237:                        np->q_next = qp->q_next;        /* dequeue */
        !           238:                        break;
        !           239:                }
        !           240:        }
        !           241:        qp->q_next = QINFO_NULL;                /* sanity check */
        !           242:        qp->q_time = 0;
        !           243: }
        !           244: 
        !           245: /*
        !           246:  * Retry is called to retransmit query 'qp'.
        !           247:  */
        !           248: retry(qp)
        !           249:        register struct qinfo *qp;
        !           250: {
        !           251:        register int n;
        !           252:        register HEADER *hp;
        !           253: 
        !           254: #ifdef DEBUG
        !           255:        if (debug > 3)
        !           256:                fprintf(ddt,"retry(x%x) id=%d\n", qp, ntohs(qp->q_id));
        !           257: #endif
        !           258: 
        !           259:        /* try next address */
        !           260:        n = qp->q_curaddr;
        !           261:        ++qp->q_nretry[n];
        !           262:        do {
        !           263:                if (++n >= qp->q_naddr)
        !           264:                        n = 0;
        !           265:                if (qp->q_nretry[n] < MAXRETRY)
        !           266:                        goto found;
        !           267:        } while (n != qp->q_curaddr);
        !           268:        /*
        !           269:         * Give up. Can't reach destination.
        !           270:         */
        !           271: #ifdef DEBUG
        !           272:        if (debug >= 5)
        !           273:                fprintf(ddt,"give up\n");
        !           274: #endif
        !           275:        hp = (HEADER *)qp->q_msg;
        !           276:        hp->qr = 1;
        !           277:        hp->rcode = SERVFAIL;
        !           278:        hp->ra = 1;
        !           279: #ifdef DEBUG
        !           280:        if (debug >= 10)
        !           281:                fp_query(qp->q_msg, ddt);
        !           282: #endif
        !           283:        if (sendto(ds, qp->q_msg, qp->q_msglen, 0, &qp->q_from,
        !           284:            sizeof(qp->q_from))) {
        !           285: #ifdef DEBUG
        !           286:                if (debug)
        !           287:                        fprintf(ddt,"gave up retry(x%x) id=%d\n",
        !           288:                                qp, ntohs(qp->q_id));
        !           289: #endif
        !           290:        }
        !           291:        qremove(qp);
        !           292:        return;
        !           293: found:
        !           294:        qp->q_curaddr = n;
        !           295: #ifdef DEBUG
        !           296:        if (debug)
        !           297:                fprintf(ddt,"resend(id=%d n=%d) -> %s (%d)\n",ntohs(qp->q_id),
        !           298:                                n, inet_ntoa(qp->q_addr[n].sin_addr),
        !           299:                                ntohs(qp->q_addr[n].sin_port));
        !           300:        if ( debug >= 10)
        !           301:                fp_query(qp->q_msg, ddt);
        !           302: #endif
        !           303:        if (sendto(ds, qp->q_msg, qp->q_msglen, 0, &qp->q_addr[n],
        !           304:            sizeof(qp->q_addr[0])) < 0) {
        !           305: #ifdef DEBUG
        !           306:                if (debug > 3)
        !           307:                        fprintf(ddt,"error returning msg\n");
        !           308: #endif
        !           309:        }
        !           310:        unsched(qp);
        !           311:        schedretry(qp, (time_t)RETRYTIME);
        !           312: }
        !           313: 
        !           314: qremove(qp)
        !           315: register struct qinfo *qp;
        !           316: {
        !           317: #ifdef DEBUG
        !           318:        if(debug > 3)
        !           319:                fprintf(ddt,"qremove(x%x)\n", qp);
        !           320: #endif
        !           321:        unsched(qp);                    /* get off queue first */
        !           322:        free(qp->q_msg);
        !           323:        if (qp->q_cmsg);
        !           324:                free(qp->q_cmsg);
        !           325:        qfree(qp);
        !           326: }
        !           327: 
        !           328: struct qinfo *
        !           329: qfindid(id)
        !           330: register u_short id;
        !           331: {
        !           332:        register struct qinfo *qp;
        !           333: 
        !           334: #ifdef DEBUG
        !           335:        if(debug > 3)
        !           336:                fprintf(ddt,"qfindid(%d)\n", ntohs(id));
        !           337: #endif
        !           338:        for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
        !           339:                if (qp->q_nsid == id)
        !           340:                        return(qp);
        !           341:        }
        !           342: #ifdef DEBUG
        !           343:        if (debug >= 5)
        !           344:                fprintf(ddt,"qp not found\n");
        !           345: #endif
        !           346:        return(NULL);
        !           347: }
        !           348: 
        !           349: struct qinfo *
        !           350: qnew()
        !           351: {
        !           352:        register struct qinfo *qp;
        !           353: 
        !           354:        if ((qp = (struct qinfo *)calloc(1, sizeof(struct qinfo))) == NULL) {
        !           355: #ifdef DEBUG
        !           356:                if (debug >= 5)
        !           357:                        fprintf(ddt,"qnew: calloc error\n");
        !           358: #endif
        !           359:                syslog(LOG_ERR, "forw: %m");
        !           360:                exit(12);
        !           361:        }
        !           362: #ifdef DEBUG
        !           363:        if (debug >= 5)
        !           364:                fprintf(ddt,"qnew(x%x)\n", qp);
        !           365: #endif
        !           366:        qp->q_link = qhead;
        !           367:        qhead = qp;
        !           368:        return( qp );
        !           369: }
        !           370: 
        !           371: qfree(qp)
        !           372: struct qinfo *qp;
        !           373: {
        !           374:        register struct qinfo *np;
        !           375: 
        !           376: #ifdef DEBUG
        !           377:        if(debug > 3)
        !           378:                fprintf(ddt,"qfree( x%x )\n", qp);
        !           379:        if(debug && qp->q_next)
        !           380:                fprintf(ddt,"WARNING:  qfree of linked ptr x%x\n", qp);
        !           381: #endif
        !           382:        if( qhead == qp )  {
        !           383:                qhead = qp->q_link;
        !           384:        } else {
        !           385:                for( np=qhead; np->q_link != QINFO_NULL; np = np->q_link )  {
        !           386:                        if( np->q_link != qp )  continue;
        !           387:                        np->q_link = qp->q_link;        /* dequeue */
        !           388:                        break;
        !           389:                }
        !           390:        }
        !           391:        (void)free((char *)qp);
        !           392: }

unix.superglobalmegacorp.com

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