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

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)ns_resp.c  4.3 (Berkeley) 5/30/86";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Copyright (c) 1986 Regents of the University of California
                      7:  *     All Rights Reserved
                      8:  */
                      9: 
                     10: #include <stdio.h>
                     11: #include <sys/types.h>
                     12: #include <sys/time.h>
                     13: #include <sys/socket.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: extern int errno;
                     21: extern char *dnptrs[];
                     22: extern char *malloc();
                     23: struct databuf *nsp[MAXNS], **nspp;
                     24: 
                     25: /*
                     26:  * Handle a response from a forwarded query.
                     27:  */
                     28: ns_resp(msg, msglen)
                     29:        char *msg;
                     30:        int msglen;
                     31: {
                     32:        register struct qinfo *qp;
                     33:        register HEADER *hp;
                     34:        register char *cp, *tp;
                     35:        int i, c, n, ancount, nscount, arcount;
                     36:        int type;
                     37:        int qtype, qclass;
                     38:        int cname = 0; /* flag for processing cname response */
                     39:        int count, founddata;
                     40:        int buflen;
                     41:        int newmsglen;
                     42:        char name[MAXDNAME], *dname;
                     43:        char *fname;
                     44:        char *newmsg;
                     45: 
                     46:        struct hashbuf *htp;
                     47:        struct databuf *dp, *tmp, *pdp;
                     48:        struct namebuf *np;
                     49: 
                     50: #ifdef DEBUG
                     51:        if (debug >= 3)
                     52:                fprintf(ddt,"ns_resp(%x, %d)\n", msg, msglen);
                     53: #endif
                     54:        hp = (HEADER *) msg;
                     55:        if( (qp = qfindid(hp->id)) == NULL )
                     56:                return;
                     57: 
                     58:        if (hp->rcode != NOERROR || hp->opcode != QUERY)
                     59:                goto retmsg;
                     60:        /*
                     61:         * Skip query section
                     62:         */
                     63:        cp = msg + sizeof(HEADER);
                     64:        if (hp->qdcount) {
                     65:                if ((n = dn_skip(cp)) < 0) {
                     66: #ifdef DEBUG
                     67:                        if (debug)
                     68:                            fprintf(ddt,"FORMERR ns_resp() dn_skip failed\n");
                     69: #endif
                     70:                        hp->rcode = FORMERR;
                     71:                        goto retmsg;
                     72:                }
                     73:                cp += n;
                     74:                qtype = getshort(cp);
                     75:                cp += sizeof(u_short);
                     76:                qclass = getshort(cp);
                     77:                cp += sizeof(u_short);
                     78:        }
                     79:        /*
                     80:         * Save answers, name server, and additional records for future use.
                     81:         */
                     82:        ancount = ntohs(hp->ancount);
                     83:        nscount = ntohs(hp->nscount);
                     84:        arcount = ntohs(hp->arcount);
                     85:        if (ancount == 1 || nscount) {
                     86:                /*
                     87:                 *  Check if it's a CNAME responce
                     88:                 */
                     89:                tp = cp;
                     90:                tp += dn_skip(tp); /* name */
                     91:                type = getshort(tp);
                     92:                tp += sizeof(u_short); /* type */
                     93:                if (type == T_CNAME) {
                     94:                        tp += sizeof(u_short); /* class */
                     95:                        tp += sizeof(u_long);  /* ttl */
                     96:                        tp += sizeof(u_short); /* dlen */
                     97:                        cname++;
                     98: #ifdef DEBUG
                     99:                        if (debug) {
                    100:                                fprintf(ddt,"CNAME - needs more processing\n");
                    101:                        }
                    102: #endif
                    103:                        if (!qp->q_cmsglen) {
                    104:                                qp->q_cmsg = qp->q_msg;
                    105:                                qp->q_cmsglen = qp->q_msglen;
                    106:                        }
                    107:                }
                    108:        }
                    109:        /*
                    110:         * Add the info recived in the responce to the Data Base
                    111:         */
                    112:        c = ancount + nscount + arcount;
                    113:        nspp = nsp;
                    114:        for (i = 0; i < c; i++) {
                    115:                if (cp >= msg + msglen) {
                    116: #ifdef DEBUG
                    117:                        if (debug)
                    118:                            fprintf(ddt, "FORMERR ns_resp() message bad count?\n");
                    119: #endif
                    120:                        hp->rcode = FORMERR;
                    121:                        goto retmsg;
                    122:                }
                    123:                if ((n = doupdate(msg, msglen, cp, 0,
                    124:                    !ancount && i < nscount)) < 0) {
                    125: #ifdef DEBUG
                    126:                        if (debug)
                    127:                            fprintf(ddt,"FORMERR ns_resp() doupdate failed\n");
                    128: #endif
                    129:                        hp->rcode = FORMERR;
                    130:                        goto retmsg;
                    131:                }
                    132:                cp += n;
                    133:        }
                    134:        if (cp > msg + msglen) {
                    135: #ifdef DEBUG
                    136:                if (debug)
                    137:                    fprintf(ddt,"FORMERR ns_resp()  packet size err %d, %d\n",
                    138:                       cp-msg, msglen);
                    139: #endif
                    140:                hp->rcode = FORMERR;
                    141:                goto retmsg;
                    142:        }
                    143:        if ((qtype == C_ANY) && ancount)
                    144:                goto retmsg;
                    145:        if ((!cname && !qp->q_cmsglen) && (ancount || nscount == 0))
                    146:                goto retmsg;
                    147: 
                    148:        /*
                    149:         * All messages in here need further processing.  i.e. they
                    150:         * are either CNAMEs or we got referred again.
                    151:         */
                    152:        count = 0;
                    153:        founddata = 0;
                    154:        dname = name;
                    155:        if ((newmsg = malloc(BUFSIZ)) == NULL) {
                    156: #if DEBUG
                    157:                if (debug)
                    158:                        fprintf(ddt,"ns_resp: malloc error\n");
                    159: #endif
                    160:                syslog(LOG_ERR, "ns_resp: Out Of Memory");
                    161:                hp->rcode = SERVFAIL;
                    162:                goto retmsg;
                    163:        }
                    164:        buflen = BUFSIZ;
                    165:        if ((!cname && qp->q_cmsglen) && ancount) {
                    166: #if DEBUG
                    167:                if (debug) {
                    168:                        fprintf(ddt,"Cname second pass\n");
                    169:                }
                    170: #endif
                    171:                newmsglen = qp->q_cmsglen;
                    172:                bcopy(qp->q_cmsg, newmsg, newmsglen);
                    173:        } else {
                    174:                newmsglen = msglen;
                    175:                bcopy(msg, newmsg, newmsglen);
                    176:        }
                    177:        buflen = buflen - newmsglen;
                    178:        hp = (HEADER *) newmsg;
                    179:        dnptrs[0] = newmsg;
                    180:        dnptrs[1] = NULL;
                    181:        cp = newmsg + sizeof(HEADER);
                    182:        if (cname)
                    183:                cp += dn_skip(cp) + QFIXEDSZ;
                    184:        if ((n = dn_expand(newmsg, newmsg + newmsglen,
                    185:                cp, dname, sizeof(name))) < 0) {
                    186: #ifdef DEBUG
                    187:                if (debug)
                    188:                        fprintf(ddt,"dn_expand failed\n" );
                    189: #endif
                    190:                hp->rcode = SERVFAIL;
                    191:                free(newmsg);
                    192:                goto retmsg;
                    193:        }
                    194:        cp = newmsg + sizeof(HEADER);
                    195:        if (cname)
                    196:                cp += dn_skip(cp);
                    197:        else
                    198:                cp += n;
                    199:        cp += QFIXEDSZ;
                    200: 
                    201: again:
                    202:        htp = hashtab;          /* lookup relative to root */
                    203: #ifdef DEBUG
                    204:        if (debug)
                    205:                fprintf(ddt,"ns_resp() nlookup(%s)\n",dname);
                    206: #endif
                    207:        np = nlookup(dname, &htp, &fname, 0);
                    208:        if (np == (struct namebuf *)NULL)
                    209:                fname = "";
                    210:        if (fname != dname)
                    211:                goto findns;
                    212: #ifdef DEBUG
                    213:        if (debug)
                    214:                fprintf(ddt,"found '%s'\n", dname);
                    215: #endif
                    216:        pdp = NULL;
                    217:        dp = np->n_data;
                    218:        /* look for the data */
                    219:        while (dp != NULL) {
                    220:                if (!wanted(dp, qclass, qtype)) {
                    221:                        pdp = dp;
                    222:                        dp = dp->d_next;
                    223:                        continue;
                    224:                }
                    225:                if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) {
                    226:                        if (n == -1) {
                    227:                                hp->tc = 1;
                    228:                                break;
                    229:                        }
                    230:                        /* delete old cache entry */
                    231: #ifdef DEBUG
                    232:                        if (debug >= 5)
                    233:                                fprintf(ddt,"deleting cache entry\n");
                    234: #endif
                    235:                        rminv(dp);
                    236:                        tmp = dp->d_next;
                    237:                        free((char *)dp);
                    238:                        dp = tmp;
                    239:                        if (pdp == NULL)
                    240:                                np->n_data = dp;
                    241:                        else
                    242:                                pdp->d_next = dp;
                    243:                        continue;
                    244:                }
                    245:                cp += n;
                    246:                buflen -= n;
                    247:                count++;
                    248:                if (dp->d_zone)
                    249:                        hp->aa = 1;
                    250:                if (dp->d_type == T_CNAME) {
                    251:                        if (type == T_ANY)
                    252:                                break;
                    253:                        dname = dp->d_data;
                    254:                        goto again;
                    255:                }
                    256:                founddata++;
                    257:                pdp = dp;
                    258:                dp = dp->d_next;
                    259:        }
                    260: #ifdef DEBUG
                    261:        if (debug >= 5)
                    262:                fprintf(ddt,"count = %d, founddata = %d\n", count, founddata);
                    263: #endif
                    264:        if (count)
                    265:                hp->ancount = htons((u_short)count);
                    266: 
                    267: findns:
                    268: 
                    269:        /*
                    270:         * Look for name servers to refer to and fill in the authority
                    271:         * section or record the address for forwarding the query
                    272:         * (recursion desired).
                    273:         */
                    274:        for (count = 0;; np = np->n_parent) {
                    275: #ifdef DEBUG
                    276:                if (debug >= 5)
                    277:                        fprintf(ddt, "fname = '%s'\n", fname);
                    278: #endif
                    279:                if (*fname == '\0') {
                    280:                        for (np = hashtab->h_tab[0]; np != NULL;
                    281:                             np = np->n_next)
                    282:                                if (np->n_dname[0] == '\0')
                    283:                                        goto foundns;
                    284: #ifdef DEBUG
                    285:                        if (debug)
                    286:                                fprintf(ddt, "No root nameserver?\n");
                    287: #endif
                    288:                        syslog(LOG_ERR, "No root Nameserver\n");
                    289:                        hp->rcode = SERVFAIL;
                    290:                        break;
                    291:                }
                    292: foundns:
                    293:                nspp = nsp;
                    294:                pdp = NULL;
                    295:                dp = np->n_data;
                    296:                while (dp != NULL) {
                    297:                        if (!match(dp, qclass, T_NS)) {
                    298:                                pdp = dp;
                    299:                                dp = dp->d_next;
                    300:                                continue;
                    301:                        }
                    302:                        if (!founddata) {
                    303:                                if (nspp < &nsp[MAXNS-1])
                    304:                                        *nspp++ = dp;
                    305:                                pdp = dp;
                    306:                                dp = dp->d_next;
                    307:                                continue;
                    308:                        }
                    309:                        if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) {
                    310:                                if (n == -1) {
                    311:                                        hp->tc = 1;
                    312:                                        break;
                    313:                                }
                    314:                                /* delete old cache entry */
                    315: #ifdef DEBUG
                    316:                                if (debug)
                    317:                                        fprintf(ddt,"deleting cache entry\n");
                    318: #endif
                    319:                                rminv(dp);
                    320:                                tmp = dp->d_next;               
                    321:                                free((char *)dp);
                    322:                                dp = tmp;
                    323:                                if (pdp == NULL)
                    324:                                        np->n_data = dp;
                    325:                                else
                    326:                                        pdp->d_next = dp;
                    327:                                continue;
                    328:                        }
                    329:                        cp += n;
                    330:                        buflen -= n;
                    331:                        count++;
                    332:                        pdp = dp;
                    333:                        dp = dp->d_next;
                    334:                }
                    335:                if ((*fname == '\0') || (count > 0))
                    336:                        break;
                    337:                if (nspp != nsp)
                    338:                        break;
                    339:                if ((fname = index(fname, '.')) == NULL)
                    340:                        fname = "";
                    341:                else
                    342:                        fname++;
                    343:        }
                    344: 
                    345:        if (count && founddata) {
                    346:                hp->nscount = htons((u_short)count);
                    347:                cp += doaddinfo(hp, cp, buflen);
                    348:                buflen = cp - newmsg;
                    349:                msg = newmsg;
                    350:                msglen = buflen;
                    351:                hp = (HEADER *) msg;
                    352:                goto retmsg;
                    353:        }
                    354: 
                    355:        *nspp = NULL;
                    356:        if (cname) {
                    357:                newmsglen = res_mkquery(QUERY, dname, C_ANY, T_A, (char *)NULL,
                    358:                                        0, NULL, newmsg, BUFSIZ);
                    359:                qp->q_msglen = newmsglen;
                    360:                hp->id = qp->q_nsid;
                    361:        } else {
                    362:                hp->ancount = 0;
                    363:                hp->nscount = 0;
                    364:                hp->arcount = 0;
                    365:                hp->qr = 0;
                    366:        }
                    367:        qp->q_naddr = 0;
                    368:        qp->q_curaddr = 0;
                    369:        n = nslookup(nsp, qp);
                    370: 
                    371: #ifdef DEBUG
                    372:                if (debug > 7) {
                    373:                        int kjd;
                    374: 
                    375:                        fprintf(ddt,"n = %d\n",n);
                    376:                        for (kjd = 0; kjd < qp->q_naddr; kjd++ )
                    377:                                fprintf(ddt,"list %d-> %s (%d)\n",  kjd,
                    378:                                        inet_ntoa(qp->q_addr[kjd].sin_addr),
                    379:                                        ntohs(qp->q_addr[kjd].sin_port));
                    380:                }
                    381: #endif DEBUG
                    382:        qp->q_msg = newmsg;
                    383:        if (qp->q_cname++ == MAXCNAMES) {
                    384:                hp->id = qp->q_id;
                    385:                hp->rd = 1;
                    386:                hp->ra = 1;             
                    387:                if (qp->q_stream != QSTREAM_NULL) {
                    388:                        (void) writemsg(qp->q_stream->s_rfd, newmsg, newmsglen);
                    389:                        qp->q_stream->s_time = tt.tv_sec;
                    390:                        qp->q_stream->s_refcnt--;
                    391:                } else {
                    392:                        if (sendto(ds, newmsg, newmsglen, 0, &qp->q_from,
                    393:                                sizeof(qp->q_from)) < 0) {
                    394: #ifdef DEBUG
                    395:                                if (debug)
                    396:                                        fprintf(ddt,"sendto failed\n");
                    397: #endif
                    398:                        }
                    399:                }
                    400:                qremove(qp);
                    401:                return;
                    402:        }
                    403: #ifdef DEBUG
                    404:        if (debug)
                    405:                fprintf(ddt,"q_cname = %d\n",qp->q_cname);
                    406: #endif
                    407:        unsched(qp);
                    408:        schedretry(qp, (time_t)RETRYTIME);
                    409: 
                    410: #ifdef DEBUG
                    411:        if (debug >= 3)
                    412:                fp_query(qp->q_msg, ddt);
                    413:        if (debug)
                    414:                fprintf(ddt,"try -> %s (%d)\n",
                    415:                        inet_ntoa(qp->q_addr[0].sin_addr),
                    416:                        ntohs(qp->q_addr[0].sin_port));
                    417: #endif
                    418:        if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
                    419:                &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0) {
                    420: #ifdef DEBUG
                    421:                if (debug)
                    422:                        fprintf(ddt, "error returning msg errno=%d\n",errno);
                    423: #endif
                    424:        }
                    425:        return;
                    426: 
                    427: retmsg:
                    428:        /*
                    429:         * Pass answer back to original requestor.
                    430:         */
                    431:        hp->id = qp->q_id;
                    432:        hp->rd = 1;             /* restore Recursion Desired bit */
                    433:        hp->ra = 1;             /* Recursion is Available */
                    434: #ifdef DEBUG
                    435:        if (debug)
                    436:                fprintf(ddt,"respond -> %s (%d)\n",
                    437:                        inet_ntoa(qp->q_from.sin_addr),
                    438:                        ntohs(qp->q_from.sin_port));
                    439:        if (debug >= 10)
                    440:                fp_query(msg, ddt);
                    441: #endif
                    442:        if (qp->q_stream == QSTREAM_NULL) {
                    443:                if (sendto(ds, msg, msglen, 0,
                    444:                    &qp->q_from, sizeof(qp->q_from)) < 0) {
                    445: #ifdef DEBUG
                    446:                        if (debug)
                    447:                                fprintf(ddt,"sendto failed\n");
                    448: #endif
                    449:                }
                    450: 
                    451:        } else {
                    452:                (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
                    453:                qp->q_stream->s_time = tt.tv_sec;
                    454:                qp->q_stream->s_refcnt--;
                    455:        }
                    456:        if (msg == newmsg)
                    457:                (void) free(newmsg);
                    458:        /*
                    459:         * Remove from table
                    460:         */
                    461:        qremove(qp);
                    462: }
                    463: 
                    464: /*
                    465:  * Decode the resource record 'rrp' and update the database.
                    466:  * If savens is true, record pointer for forwarding queries a second time.
                    467:  */
                    468: doupdate(msg, msglen, rrp, zone, savens)
                    469:        char *msg ;
                    470:        char *rrp;
                    471:        int  msglen, zone, savens;
                    472: {
                    473:        register char *cp;
                    474:        register int n;
                    475:        int class, type, dlen, n1;
                    476:        u_long ttl;
                    477:        struct databuf *dp;
                    478:        char dname[MAXDNAME];
                    479:        char data[BUFSIZ], *cp1;
                    480: 
                    481: #ifdef DEBUG
                    482:        if (debug >= 3)
                    483:                fprintf(ddt,"doupdate(%d, %d)\n", zone, savens);
                    484: #endif
                    485: 
                    486:        cp = rrp;
                    487:        if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0)
                    488:                return (-1);
                    489:        cp += n;
                    490:        type = getshort(cp);
                    491:        cp += sizeof(u_short);
                    492:        class = getshort(cp);
                    493:        cp += sizeof(u_short);
                    494:        ttl = getlong(cp);
                    495:        cp += sizeof(u_long);
                    496:        dlen = getshort(cp);
                    497:        cp += sizeof(u_short);
                    498:        if (zone == 0) {
                    499:                if (ttl == 0)
                    500:                        ttl = 5 * 60;
                    501:                ttl += (u_long) tt.tv_sec;
                    502:        }
                    503:        /*
                    504:         * Convert the resource record data into the internal
                    505:         * database format.
                    506:         */
                    507:        switch (type) {
                    508:        case T_A:
                    509:        case T_HINFO:
                    510:        case T_UINFO:
                    511:        case T_UID:
                    512:        case T_GID:
                    513:                cp1 = cp;
                    514:                n = dlen;
                    515:                cp += n;
                    516:                break;
                    517: 
                    518:        case T_CNAME:
                    519:        case T_MB:
                    520:        case T_MG:
                    521:        case T_MR:
                    522:        case T_NS:
                    523:        case T_PTR:
                    524:                if ((n = dn_expand(msg, msg + msglen, cp, data,
                    525:                   sizeof(data))) < 0)
                    526:                        return (-1);
                    527:                cp += n;
                    528:                cp1 = data;
                    529:                n = strlen(data) + 1;
                    530:                break;
                    531: 
                    532:        case T_MINFO:
                    533:        case T_SOA:
                    534:                if ((n = dn_expand(msg, msg + msglen, cp, data,
                    535:                    sizeof(data))) < 0)
                    536:                        return (-1);
                    537:                cp += n;
                    538:                cp1 = data + (n = strlen(data) + 1);
                    539:                n1 = sizeof(data) - n;
                    540:                if (type == T_SOA)
                    541:                        n1 -= 5 * sizeof(u_long);
                    542:                if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0)
                    543:                        return (-1);
                    544:                cp += n;
                    545:                cp1 += strlen(cp1) + 1;
                    546:                if (type == T_SOA) {
                    547:                        bcopy(cp, cp1, n = 5 * sizeof(u_long));
                    548:                        cp += n;
                    549:                        cp1 += n;
                    550:                }
                    551:                n = cp1 - data;
                    552:                cp1 = data;
                    553:                break;
                    554: 
                    555:        case T_MX:
                    556:                /* grab preference */
                    557:                bcopy(cp,data,sizeof(u_short));
                    558:                cp1 = data + sizeof(u_short);
                    559:                cp += sizeof(u_short);
                    560: 
                    561:                /* get name */
                    562:                if ((n = dn_expand(msg, msg + msglen, cp, cp1,
                    563:                    sizeof(data)-sizeof(u_short))) < 0)
                    564:                        return(-1);
                    565:                cp += n;
                    566: 
                    567:                /* compute end of data */
                    568:                cp1 += strlen(cp1) + 1;
                    569:                /* compute size of data */
                    570:                n = cp1 - data;
                    571:                cp1 = data;
                    572:                break;
                    573: 
                    574:        default:
                    575: #ifdef DEBUG
                    576:                if (debug >= 3)
                    577:                        fprintf(ddt,"unknown type %d\n", type);
                    578: #endif
                    579:                return ((cp - rrp) + dlen);
                    580:        }
                    581:        dp = savedata(class, type, ttl, cp1, n);
                    582:        dp->d_zone = zone;
                    583:        if ((n = db_update(dname, dp, dp, DB_NODATA)) < 0) {
                    584: #ifdef DEBUG
                    585:                if (debug && (n != DATAEXISTS))
                    586:                        fprintf(ddt,"update failed (%d)\n", n);
                    587:                else if (debug >= 3)
                    588:                        fprintf(ddt,"update failed (DATAEXISTS)\n");
                    589: #endif
                    590:                (void) free((char *)dp);
                    591:        } else if (savens && type == T_NS && nspp < &nsp[MAXNS-1])
                    592:                *nspp++ = dp;
                    593:        return (cp - rrp);
                    594: }

unix.superglobalmegacorp.com

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