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