Annotation of embedaddon/dhcp/minires/res_findzonecut.c, revision 1.1.1.1

1.1       misho       1: #if !defined(lint) && !defined(SABER)
1.1.1.1 ! misho       2: static const char rcsid[] = "$Id: res_findzonecut.c,v 1.16.786.3.6.2 2012/03/09 21:45:09 sar Exp $";
1.1       misho       3: #endif /* not lint */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
                      7:  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
                      8:  * Copyright (c) 1999-2003 by Internet Software Consortium
                      9:  *
                     10:  * Permission to use, copy, modify, and distribute this software for any
                     11:  * purpose with or without fee is hereby granted, provided that the above
                     12:  * copyright notice and this permission notice appear in all copies.
                     13:  *
                     14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     21:  *
                     22:  *   Internet Systems Consortium, Inc.
                     23:  *   950 Charter Street
                     24:  *   Redwood City, CA 94063
                     25:  *   <info@isc.org>
                     26:  *   https://www.isc.org/
                     27:  */
                     28: 
                     29: /* Import. */
                     30: 
                     31: #include <sys/param.h>
                     32: #include <sys/socket.h>
                     33: #include <sys/time.h>
                     34: 
                     35: #include <netinet/in.h>
                     36: #include <arpa/inet.h>
                     37: 
                     38: #include <errno.h>
                     39: #include <limits.h>
                     40: #include <netdb.h>
                     41: #include <stdarg.h>
                     42: #include <stdio.h>
                     43: #include <stdlib.h>
                     44: #include <string.h>
                     45: 
                     46: #include <isc-dhcp/list.h>
                     47: 
                     48: #include "minires/minires.h"
                     49: #include "arpa/nameser.h"
                     50: 
                     51: /* Data structures. */
                     52: 
                     53: typedef struct rr_a {
                     54:        ISC_LINK(struct rr_a)   link;
                     55:        struct in_addr          addr;
                     56: } rr_a;
                     57: typedef ISC_LIST(rr_a) rrset_a;
                     58: 
                     59: typedef struct rr_ns {
                     60:        ISC_LINK(struct rr_ns) link;
                     61:        char *name;
                     62:        rrset_a addrs;
                     63: } rr_ns;
                     64: typedef ISC_LIST(rr_ns) rrset_ns;
                     65: 
                     66: /* Forward. */
                     67: 
                     68: static int     satisfy(res_state,
                     69:                        const char *, rrset_ns *, struct in_addr *, int);
                     70: static int     add_addrs(res_state, rr_ns *, struct in_addr *, int);
                     71: static isc_result_t get_soa(res_state, const char *, ns_class,
                     72:                        char *, size_t, char *, size_t,
                     73:                        rrset_ns *);
                     74: static isc_result_t get_ns(res_state, const char *, ns_class, rrset_ns *);
                     75: static isc_result_t get_glue(res_state, ns_class, rrset_ns *);
                     76: static isc_result_t save_ns(res_state, ns_msg *, ns_sect,
                     77:                            const char *, ns_class, rrset_ns *);
                     78: static isc_result_t save_a(res_state, ns_msg *, ns_sect,
                     79:                           const char *, ns_class, rrset_a *);
                     80: static void    free_nsrrset(rrset_ns *);
                     81: static void    free_nsrr(rrset_ns *, rr_ns *);
                     82: static rr_ns * find_ns(rrset_ns *, const char *);
                     83: static isc_result_t do_query(res_state, const char *, ns_class, ns_type,
                     84:                             double *, ns_msg *, int *);
                     85: 
                     86: /* Public. */
                     87: 
                     88: /*
                     89:  * int
                     90:  * res_findzonecut(res, dname, class, zname, zsize, addrs, naddrs)
                     91:  *     find enclosing zone for a <dname,class>, and some server addresses
                     92:  * parameters:
                     93:  *     res - resolver context to work within (is modified)
                     94:  *     dname - domain name whose enclosing zone is desired
                     95:  *     class - class of dname (and its enclosing zone)
                     96:  *     zname - found zone name
                     97:  *     zsize - allocated size of zname
                     98:  *     addrs - found server addresses
                     99:  *     naddrs - max number of addrs
                    100:  * return values:
                    101:  *     < 0 - an error occurred (check errno)
                    102:  *     = 0 - zname is now valid, but addrs[] wasn't changed
                    103:  *     > 0 - zname is now valid, and return value is number of addrs[] found
                    104:  * notes:
                    105:  *     this function calls res_nsend() which means it depends on correctly
                    106:  *     functioning recursive nameservers (usually defined in /etc/resolv.conf
                    107:  *     or its local equivilent).
                    108:  *
                    109:  *     we start by asking for an SOA<dname,class>.  if we get one as an
                    110:  *     answer, that just means <dname,class> is a zone top, which is fine.
                    111:  *     more than likely we'll be told to go pound sand, in the form of a
                    112:  *     negative answer.
                    113:  *
                    114:  *     note that we are not prepared to deal with referrals since that would
                    115:  *     only come from authority servers and our correctly functioning local
                    116:  *     recursive server would have followed the referral and got us something
                    117:  *     more definite.
                    118:  *
                    119:  *     if the authority section contains an SOA, this SOA should also be the
                    120:  *     closest enclosing zone, since any intermediary zone cuts would've been
                    121:  *     returned as referrals and dealt with by our correctly functioning local
                    122:  *     recursive name server.  but an SOA in the authority section should NOT
                    123:  *     match our dname (since that would have been returned in the answer
                    124:  *     section).  an authority section SOA has to be "above" our dname.
                    125:  *
                    126:  *     we cannot fail to find an SOA in this way.  ultimately we'll return
                    127:  *     a zname indicating the root zone if that's the closest enclosing zone.
                    128:  *     however, since authority section SOA's were once optional, it's
                    129:  *     possible that we'll have to go hunting for the enclosing SOA by
                    130:  *     ripping labels off the front of our dname -- this is known as "doing
                    131:  *     it the hard way."
                    132:  *
                    133:  *     ultimately we want some server addresses, which are ideally the ones
                    134:  *     pertaining to the SOA.MNAME, but only if there is a matching NS RR.
                    135:  *     so the second phase (after we find an SOA) is to go looking for the
                    136:  *     NS RRset for that SOA's zone.
                    137:  *
                    138:  *     no answer section processed by this code is allowed to contain CNAME
                    139:  *     or DNAME RR's.  for the SOA query this means we strip a label and
                    140:  *     keep going.  for the NS and A queries this means we just give up.
                    141:  */
                    142: 
                    143: isc_result_t
                    144: res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
                    145:                char *zname, size_t zsize, struct in_addr *addrs, int naddrs,
                    146:                int *count, void *zcookie)
                    147: {
                    148:        char mname[NS_MAXDNAME];
                    149:        u_long save_pfcode;
                    150:        rrset_ns nsrrs;
                    151:        int n = 0;
                    152:        isc_result_t rcode;
                    153: 
                    154:        DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
                    155:                 dname, p_class(class), (long)zsize, naddrs));
                    156:        save_pfcode = statp->pfcode;
                    157:        statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
                    158:                         RES_PRF_QUES | RES_PRF_ANS |
                    159:                         RES_PRF_AUTH | RES_PRF_ADD;
                    160:        ISC_LIST_INIT(nsrrs);
                    161: 
                    162:        DPRINTF (("look for a predefined zone statement"));
                    163:        rcode = find_cached_zone (dname, class, zname, zsize,
                    164:                                  addrs, naddrs, &n, zcookie);
                    165:        if (rcode == ISC_R_SUCCESS)
                    166:                goto done;
                    167: 
                    168:        DPRINTF(("get the soa, and see if it has enough glue"));
                    169:        if ((rcode = get_soa(statp, dname, class, zname, zsize,
                    170:                             mname, sizeof mname, &nsrrs)) != ISC_R_SUCCESS ||
                    171:            ((opts & RES_EXHAUSTIVE) == 0 &&
                    172:             (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
                    173:                goto done;
                    174: 
                    175:        DPRINTF(("get the ns rrset and see if it has enough glue"));
                    176:        if ((rcode = get_ns(statp, zname, class, &nsrrs)) != ISC_R_SUCCESS ||
                    177:            ((opts & RES_EXHAUSTIVE) == 0 &&
                    178:             (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
                    179:                goto done;
                    180: 
                    181:        DPRINTF(("get the missing glue and see if it's finally enough"));
                    182:        if ((rcode = get_glue(statp, class, &nsrrs)) == ISC_R_SUCCESS)
                    183:                n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
                    184: 
                    185:        /* If we found the zone, cache it. */
                    186:        if (n > 0)
                    187:                cache_found_zone (class, zname, addrs, n);
                    188:  done:
                    189:        DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
                    190:        free_nsrrset(&nsrrs);
                    191:        statp->pfcode = save_pfcode;
                    192:        if (count)
                    193:                *count = n;
                    194:        return rcode;
                    195: }
                    196: 
                    197: /* Private. */
                    198: 
                    199: static int
                    200: satisfy(res_state statp,
                    201:        const char *mname, rrset_ns *nsrrsp, struct in_addr *addrs, int naddrs)
                    202: {
                    203:        rr_ns *nsrr;
                    204:        int n, x;
                    205: 
                    206:        n = 0;
                    207:        nsrr = find_ns(nsrrsp, mname);
                    208:        if (nsrr != NULL) {
                    209:                x = add_addrs(statp, nsrr, addrs, naddrs);
                    210:                addrs += x;
                    211:                naddrs -= x;
                    212:                n += x;
                    213:        }
                    214:        for (nsrr = ISC_LIST_HEAD(*nsrrsp);
                    215:             nsrr != NULL && naddrs > 0;
                    216:             nsrr = ISC_LIST_NEXT(nsrr, link))
                    217:                if (ns_samename(nsrr->name, mname) != 1) {
                    218:                        x = add_addrs(statp, nsrr, addrs, naddrs);
                    219:                        addrs += x;
                    220:                        naddrs -= x;
                    221:                        n += x;
                    222:                }
                    223:        DPRINTF(("satisfy(%s): %d", mname, n));
                    224:        return (n);
                    225: }
                    226: 
                    227: static int
                    228: add_addrs(res_state statp, rr_ns *nsrr, struct in_addr *addrs, int naddrs) {
                    229:        rr_a *arr;
                    230:        int n = 0;
                    231: 
                    232:        for (arr = ISC_LIST_HEAD(nsrr->addrs);
                    233:             arr != NULL; arr = ISC_LIST_NEXT(arr, link)) {
                    234:                if (naddrs <= 0)
                    235:                        return (0);
                    236:                *addrs++ = arr->addr;
                    237:                naddrs--;
                    238:                n++;
                    239:        }
                    240:        DPRINTF(("add_addrs: %d", n));
                    241:        return (n);
                    242: }
                    243: 
                    244: static isc_result_t
                    245: get_soa(res_state statp, const char *dname, ns_class class,
                    246:        char *zname, size_t zsize, char *mname, size_t msize,
                    247:        rrset_ns *nsrrsp)
                    248: {
                    249:        char tname[NS_MAXDNAME];
                    250:        double resp[NS_PACKETSZ / sizeof (double)];
                    251:        int n, i, ancount, nscount;
                    252:        ns_sect sect;
                    253:        ns_msg msg;
                    254:        isc_result_t rcode;
                    255: 
                    256:        /*
                    257:         * Find closest enclosing SOA, even if it's for the root zone.
                    258:         */
                    259: 
                    260:        /* First canonicalize dname (exactly one unescaped trailing "."). */
                    261:        rcode = ns_makecanon(dname, tname, sizeof tname);
                    262:        if (rcode != ISC_R_SUCCESS)
                    263:                return rcode;
                    264:        dname = tname;
                    265: 
                    266:        /* Now grovel the subdomains, hunting for an SOA answer or auth. */
                    267:        for (;;) {
                    268:                /* Leading or inter-label '.' are skipped here. */
                    269:                while (*dname == '.')
                    270:                        dname++;
                    271: 
                    272:                /* Is there an SOA? */
                    273:                rcode = do_query(statp, dname, class, ns_t_soa,
                    274:                                 resp, &msg, &n);
                    275:                if (rcode != ISC_R_SUCCESS) {
                    276:                        DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
                    277:                                 dname, p_class(class), n));
                    278:                        return rcode;
                    279:                }
                    280:                if (n > 0) {
                    281:                        DPRINTF(("get_soa: CNAME or DNAME found"));
                    282:                        sect = ns_s_max, n = 0;
                    283:                } else {
                    284:                        ancount = ns_msg_count(msg, ns_s_an);
                    285:                        nscount = ns_msg_count(msg, ns_s_ns);
                    286:                        if (ancount > 0 && rcode == ISC_R_SUCCESS)
                    287:                                sect = ns_s_an, n = ancount;
                    288:                        else if (nscount > 0)
                    289:                                sect = ns_s_ns, n = nscount;
                    290:                        else
                    291:                                sect = ns_s_max, n = 0;
                    292:                }
                    293:                for (i = 0; i < n; i++) {
                    294:                        const char *t;
                    295:                        const u_char *rdata;
                    296:                        ns_rr rr;
                    297: 
                    298:                        rcode = ns_parserr(&msg, sect, i, &rr) < 0;
                    299:                        if (rcode != ISC_R_SUCCESS) {
                    300:                                DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
                    301:                                         p_section(sect, ns_o_query), i));
                    302:                                return rcode;
                    303:                        }
                    304:                        if (ns_rr_type(rr) == ns_t_cname ||
                    305:                            ns_rr_type(rr) == ns_t_dname)
                    306:                                break;
                    307:                        if (ns_rr_type(rr) != ns_t_soa ||
                    308:                            ns_rr_class(rr) != class)
                    309:                                continue;
                    310:                        t = ns_rr_name(rr);
                    311:                        switch (sect) {
                    312:                        case ns_s_an:
                    313:                                if (ns_samedomain(dname, t) == 0) {
                    314:                                        DPRINTF(("get_soa: %s'%s', '%s') == 0",
                    315:                                                 "ns_samedomain(", dname, t));
                    316:                                        return ISC_R_NOTZONE;
                    317:                                }
                    318:                                break;
                    319:                        case ns_s_ns:
                    320:                                if (ns_samename(dname, t) == 1 ||
                    321:                                    ns_samedomain(dname, t) == 0) {
                    322:                                        DPRINTF(("get_soa: %smain('%s', '%s')",
                    323:                                                 "ns_samename() || !ns_samedo",
                    324:                                                 dname, t));
                    325:                                        return ISC_R_NOTZONE;
                    326:                                }
                    327:                                break;
                    328:                        default:
                    329:                                abort();
                    330:                        }
                    331:                        if (strlen(t) + 1 > zsize) {
                    332:                                DPRINTF(("get_soa: zname(%d) too small (%d)",
                    333:                                         zsize, strlen(t) + 1));
                    334:                                return ISC_R_NOSPACE;
                    335:                        }
                    336:                        strcpy(zname, t);
                    337:                        rdata = ns_rr_rdata(rr);
1.1.1.1 ! misho     338:                        /* ns_rr_rdlen(rr); */
1.1       misho     339:                        if (ns_name_uncompress((u_char *)resp,
                    340:                                               ns_msg_end(msg), rdata,
                    341:                                               mname, msize) < 0) {
                    342:                                DPRINTF(("get_soa: %s failed",
                    343:                                         "ns_name_uncompress"));
                    344:                                return ISC_R_NOMEMORY;
                    345:                        }
                    346:                        rcode = save_ns(statp, &msg,
                    347:                                        ns_s_ns, zname, class, nsrrsp);
                    348:                        if (rcode != ISC_R_SUCCESS) {
                    349:                                DPRINTF(("get_soa: save_ns failed"));
                    350:                                return rcode;
                    351:                        }
                    352:                        return ISC_R_SUCCESS;
                    353:                }
                    354: 
                    355:                /* If we're out of labels, then not even "." has an SOA! */
                    356:                if (*dname == '\0')
                    357:                        break;
                    358: 
                    359:                /* Find label-terminating "."; top of loop will skip it. */
                    360:                while (*dname != '.') {
                    361:                        if (*dname == '\\')
                    362:                                if (*++dname == '\0') {
                    363:                                        return ISC_R_NOSPACE;
                    364:                                }
                    365:                        dname++;
                    366:                }
                    367:        }
                    368:        DPRINTF(("get_soa: out of labels"));
                    369:        return ISC_R_DESTADDRREQ;
                    370: }
                    371: 
                    372: static isc_result_t
                    373: get_ns(res_state statp, const char *zname, ns_class class, rrset_ns *nsrrsp) {
                    374:        double resp[NS_PACKETSZ / sizeof (double)];
                    375:        ns_msg msg;
                    376:        int n;
                    377:        isc_result_t rcode;
                    378: 
                    379:        /* Go and get the NS RRs for this zone. */
                    380:        rcode = do_query(statp, zname, class, ns_t_ns, resp, &msg, &n);
                    381:        if (rcode != ISC_R_SUCCESS) {
                    382:                DPRINTF(("get_ns: do_query('zname', %s) failed (%d)",
                    383:                         zname, p_class(class), rcode));
                    384:                return rcode;
                    385:        }
                    386: 
                    387:        /* Remember the NS RRs and associated A RRs that came back. */
                    388:        rcode = save_ns(statp, &msg, ns_s_an, zname, class, nsrrsp);
                    389:        if (rcode != ISC_R_SUCCESS) {
                    390:                DPRINTF(("get_ns save_ns('%s', %s) failed",
                    391:                         zname, p_class(class)));
                    392:                return rcode;
                    393:        }
                    394: 
                    395:        return ISC_R_SUCCESS;
                    396: }
                    397: 
                    398: static isc_result_t
                    399: get_glue(res_state statp, ns_class class, rrset_ns *nsrrsp) {
                    400:        rr_ns *nsrr, *nsrr_n;
                    401: 
                    402:        /* Go and get the A RRs for each empty NS RR on our list. */
                    403:        for (nsrr = ISC_LIST_HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
                    404:                double resp[NS_PACKETSZ / sizeof (double)];
                    405:                ns_msg msg;
                    406:                int n;
                    407:                isc_result_t rcode;
                    408: 
                    409:                nsrr_n = ISC_LIST_NEXT(nsrr, link);
                    410: 
                    411:                if (ISC_LIST_EMPTY(nsrr->addrs)) {
                    412:                        rcode = do_query(statp, nsrr->name, class, ns_t_a,
                    413:                                         resp, &msg, &n);
                    414:                        if (rcode != ISC_R_SUCCESS) {
                    415:                            DPRINTF(("get_glue: do_query('%s', %s') failed",
                    416:                                     nsrr->name, p_class(class)));
                    417:                            return rcode;
                    418:                        }
                    419:                        if (n > 0) {
                    420:                                DPRINTF((
                    421:                        "get_glue: do_query('%s', %s') CNAME or DNAME found",
                    422:                                         nsrr->name, p_class(class)));
                    423:                        }
                    424:                        rcode = save_a(statp, &msg, ns_s_an, nsrr->name, class,
                    425:                                       &nsrr->addrs);
                    426:                        if (rcode != ISC_R_SUCCESS) {
                    427:                                DPRINTF(("get_glue: save_r('%s', %s) failed",
                    428:                                         nsrr->name, p_class(class)));
                    429:                                return rcode;
                    430:                        }
                    431:                        /* If it's still empty, it's just chaff. */
                    432:                        if (ISC_LIST_EMPTY(nsrr->addrs)) {
                    433:                                DPRINTF(("get_glue: removing empty '%s' NS",
                    434:                                         nsrr->name));
                    435:                                free_nsrr(nsrrsp, nsrr);
                    436:                        }
                    437:                }
                    438:        }
                    439:        return ISC_R_SUCCESS;
                    440: }
                    441: 
                    442: static isc_result_t
                    443: save_ns(res_state statp, ns_msg *msg, ns_sect sect,
                    444:        const char *owner, ns_class class,
                    445:        rrset_ns *nsrrsp)
                    446: {
                    447:        int i;
                    448:        isc_result_t rcode;
                    449: 
                    450:        for (i = 0; i < ns_msg_count(*msg, sect); i++) {
                    451:                char tname[MAXDNAME];
                    452:                const u_char *rdata;
                    453:                rr_ns *nsrr;
                    454:                ns_rr rr;
                    455: 
                    456:                rcode = ns_parserr(msg, sect, i, &rr);
                    457:                if (rcode != ISC_R_SUCCESS) {
                    458:                        DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
                    459:                                 p_section(sect, ns_o_query), i));
                    460:                        return rcode;
                    461:                }
                    462:                if (ns_rr_type(rr) != ns_t_ns ||
                    463:                    ns_rr_class(rr) != class ||
                    464:                    ns_samename(ns_rr_name(rr), owner) != 1)
                    465:                        continue;
                    466:                nsrr = find_ns(nsrrsp, ns_rr_name(rr));
                    467:                if (nsrr == NULL) {
                    468:                        nsrr = malloc(sizeof *nsrr);
                    469:                        if (nsrr == NULL) {
                    470:                                DPRINTF(("save_ns: malloc failed"));
                    471:                                return ISC_R_NOMEMORY;
                    472:                        }
                    473:                        rdata = ns_rr_rdata(rr);
1.1.1.1 ! misho     474:                        /* ns_rr_rdlen(rr); */
1.1       misho     475:                        if (ns_name_uncompress(ns_msg_base(*msg),
                    476:                                               ns_msg_end(*msg), rdata,
                    477:                                               tname, sizeof tname) < 0) {
                    478:                                DPRINTF(("save_ns: ns_name_uncompress failed"));
                    479:                                free(nsrr);
                    480:                                return ISC_R_NOMEMORY;
                    481:                        }
                    482:                        nsrr->name = strdup(tname);
                    483:                        if (nsrr->name == NULL) {
                    484:                                DPRINTF(("save_ns: strdup failed"));
                    485:                                free(nsrr);
                    486:                                return ISC_R_NOMEMORY;
                    487:                        }
                    488:                        ISC_LIST_INIT(nsrr->addrs);
                    489:                        ISC_LIST_APPEND(*nsrrsp, nsrr, link);
                    490:                }
                    491:                rcode = save_a(statp, msg, ns_s_ar,
                    492:                               nsrr->name, class, &nsrr->addrs);
                    493:                if (rcode != ISC_R_SUCCESS) {
                    494:                        DPRINTF(("save_ns: save_r('%s', %s) failed",
                    495:                                 nsrr->name, p_class(class)));
                    496:                        return rcode;
                    497:                }
                    498:        }
                    499:        return ISC_R_SUCCESS;
                    500: }
                    501: 
                    502: static isc_result_t
                    503: save_a(res_state statp, ns_msg *msg, ns_sect sect,
                    504:        const char *owner, ns_class class,
                    505:        rrset_a *arrsp)
                    506: {
                    507:        int i;
                    508:        isc_result_t rcode;
                    509: 
                    510:        for (i = 0; i < ns_msg_count(*msg, sect); i++) {
                    511:                ns_rr rr;
                    512:                rr_a *arr;
                    513: 
                    514:                rcode = ns_parserr(msg, sect, i, &rr);
                    515:                if (rcode != ISC_R_SUCCESS) {
                    516:                        DPRINTF(("save_a: ns_parserr(%s, %d) failed",
                    517:                                 p_section(sect, ns_o_query), i));
                    518:                        return rcode;
                    519:                }
                    520:                if (ns_rr_type(rr) != ns_t_a ||
                    521:                    ns_rr_class(rr) != class ||
                    522:                    ns_samename(ns_rr_name(rr), owner) != 1 ||
                    523:                    ns_rr_rdlen(rr) != NS_INADDRSZ)
                    524:                        continue;
                    525:                arr = malloc(sizeof *arr);
                    526:                if (arr == NULL) {
                    527:                        DPRINTF(("save_a: malloc failed"));
                    528:                        return ISC_R_NOMEMORY;
                    529:                }
                    530:                memcpy(&arr->addr, ns_rr_rdata(rr), NS_INADDRSZ);
                    531:                ISC_LIST_APPEND(*arrsp, arr, link);
                    532:        }
                    533:        return ISC_R_SUCCESS;
                    534: }
                    535: 
                    536: static void
                    537: free_nsrrset(rrset_ns *nsrrsp) {
                    538:        rr_ns *nsrr;
                    539: 
                    540:        while ((nsrr = ISC_LIST_HEAD(*nsrrsp)) != NULL)
                    541:                free_nsrr(nsrrsp, nsrr);
                    542: }
                    543: 
                    544: static void
                    545: free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
                    546:        rr_a *arr;
                    547: 
                    548:        while ((arr = ISC_LIST_HEAD(nsrr->addrs)) != NULL) {
                    549:                ISC_LIST_UNLINK(nsrr->addrs, arr, link);
                    550:                free(arr);
                    551:        }
                    552:        free((char *)nsrr->name);
                    553:        ISC_LIST_UNLINK(*nsrrsp, nsrr, link);
                    554:        free(nsrr);
                    555: }
                    556: 
                    557: static rr_ns *
                    558: find_ns(rrset_ns *nsrrsp, const char *dname) {
                    559:        rr_ns *nsrr;
                    560: 
                    561:        for (nsrr = ISC_LIST_HEAD(*nsrrsp);
                    562:             nsrr != NULL; nsrr = ISC_LIST_NEXT(nsrr, link))
                    563:                if (ns_samename(nsrr->name, dname) == 1)
                    564:                        return (nsrr);
                    565:        return (NULL);
                    566: }
                    567: 
                    568: static isc_result_t
                    569: do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
                    570:         double *resp, ns_msg *msg, int *alias_count)
                    571: {
                    572:        double req[NS_PACKETSZ / sizeof (double)];
                    573:        int i;
                    574:        unsigned n;
                    575:        isc_result_t status;
                    576: 
                    577:        status = res_nmkquery(statp, ns_o_query, dname, class, qtype,
                    578:                              NULL, 0, NULL, req, NS_PACKETSZ, &n);
                    579:        if (status != ISC_R_SUCCESS) {
                    580:                DPRINTF(("do_query: res_nmkquery failed"));
                    581:                return status;
                    582:        }
                    583:        status = res_nsend(statp, req, n, resp, NS_PACKETSZ, &n);
                    584:        if (status != ISC_R_SUCCESS) {
                    585:                DPRINTF(("do_query: res_nsend failed"));
                    586:                return status;
                    587:        }
                    588:        if (n == 0) {
                    589:                DPRINTF(("do_query: res_nsend returned 0"));
                    590:                return ISC_R_NOTFOUND;
                    591:        }
                    592:        if (ns_initparse((u_char *)resp, n, msg) < 0) {
                    593:                DPRINTF(("do_query: ns_initparse failed"));
                    594:                return ISC_R_NOSPACE;
                    595:        }
                    596:        n = 0;
                    597:        for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
                    598:                ns_rr rr;
                    599: 
                    600:                status = ns_parserr(msg, ns_s_an, i, &rr);
                    601:                if (status != ISC_R_SUCCESS) {
                    602:                        DPRINTF(("do_query: ns_parserr failed"));
                    603:                        return status;
                    604:                }
                    605:                n += (ns_rr_class(rr) == class &&
                    606:                      (ns_rr_type(rr) == ns_t_cname ||
                    607:                       ns_rr_type(rr) == ns_t_dname));
                    608:        }
                    609:        if (alias_count)
                    610:                *alias_count = n;
                    611:        return ISC_R_SUCCESS;
                    612: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>