[BACK]Return to master.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / dns

Annotation of src/external/mpl/bind/dist/lib/dns/master.c, Revision 1.1.1.1

1.1       christos    1: /*     $NetBSD$        */
                      2:
                      3: /*
                      4:  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
                      5:  *
                      6:  * This Source Code Form is subject to the terms of the Mozilla Public
                      7:  * License, v. 2.0. If a copy of the MPL was not distributed with this
                      8:  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
                      9:  *
                     10:  * See the COPYRIGHT file distributed with this work for additional
                     11:  * information regarding copyright ownership.
                     12:  */
                     13:
                     14: /*! \file */
                     15:
                     16: #include <config.h>
                     17:
                     18: #include <isc/event.h>
                     19: #include <isc/lex.h>
                     20: #include <isc/magic.h>
                     21: #include <isc/mem.h>
                     22: #include <isc/print.h>
                     23: #include <isc/serial.h>
                     24: #include <isc/stdio.h>
                     25: #include <isc/stdtime.h>
                     26: #include <isc/string.h>
                     27: #include <isc/task.h>
                     28: #include <isc/util.h>
                     29:
                     30: #include <dns/callbacks.h>
                     31: #include <dns/events.h>
                     32: #include <dns/fixedname.h>
                     33: #include <dns/master.h>
                     34: #include <dns/name.h>
                     35: #include <dns/rdata.h>
                     36: #include <dns/rdataclass.h>
                     37: #include <dns/rdatalist.h>
                     38: #include <dns/rdataset.h>
                     39: #include <dns/rdatastruct.h>
                     40: #include <dns/rdatatype.h>
                     41: #include <dns/result.h>
                     42: #include <dns/soa.h>
                     43: #include <dns/time.h>
                     44: #include <dns/ttl.h>
                     45:
                     46: /*!
                     47:  * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
                     48:  * by these sizes when we need to.
                     49:  *
                     50:  */
                     51: /*% RDLSZ reflects the number of different types with the same name expected. */
                     52: #define RDLSZ 32
                     53: /*%
                     54:  * RDSZ reflects the number of rdata expected at a give name that can fit into
                     55:  * 64k.
                     56:  */
                     57: #define RDSZ 512
                     58:
                     59: #define NBUFS 4
                     60: #define MAXWIRESZ 255
                     61:
                     62: /*%
                     63:  * Target buffer size and minimum target size.
                     64:  * MINTSIZ must be big enough to hold the largest rdata record.
                     65:  * \brief
                     66:  * TSIZ >= MINTSIZ
                     67:  */
                     68: #define TSIZ (128*1024)
                     69: /*%
                     70:  * max message size - header - root - type - class - ttl - rdlen
                     71:  */
                     72: #define MINTSIZ DNS_RDATA_MAXLENGTH
                     73: /*%
                     74:  * Size for tokens in the presentation format,
                     75:  * The largest tokens are the base64 blocks in KEY and CERT records,
                     76:  * Largest key allowed is about 1372 bytes but
                     77:  * there is no fixed upper bound on CERT records.
                     78:  * 2K is too small for some X.509s, 8K is overkill.
                     79:  */
                     80: #define TOKENSIZ (8*1024)
                     81:
                     82: /*%
                     83:  * Buffers sizes for $GENERATE.
                     84:  */
                     85: #define DNS_MASTER_LHS 2048
                     86: #define DNS_MASTER_RHS MINTSIZ
                     87:
                     88: #define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
                     89:
                     90: typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
                     91:
                     92: typedef struct dns_incctx dns_incctx_t;
                     93:
                     94: /*%
                     95:  * Master file load state.
                     96:  */
                     97:
                     98: struct dns_loadctx {
                     99:        unsigned int            magic;
                    100:        isc_mem_t               *mctx;
                    101:        dns_masterformat_t      format;
                    102:
                    103:        dns_rdatacallbacks_t    *callbacks;
                    104:        isc_task_t              *task;
                    105:        dns_loaddonefunc_t      done;
                    106:        void                    *done_arg;
                    107:
                    108:        /* Common methods */
                    109:        isc_result_t            (*openfile)(dns_loadctx_t *lctx,
                    110:                                            const char *filename);
                    111:        isc_result_t            (*load)(dns_loadctx_t *lctx);
                    112:
                    113:        /* Members used by all formats */
                    114:        isc_uint32_t            maxttl;
                    115:
                    116:        /* Members specific to the text format: */
                    117:        isc_lex_t               *lex;
                    118:        isc_boolean_t           keep_lex;
                    119:        unsigned int            options;
                    120:        isc_boolean_t           ttl_known;
                    121:        isc_boolean_t           default_ttl_known;
                    122:        isc_boolean_t           warn_1035;
                    123:        isc_boolean_t           warn_tcr;
                    124:        isc_boolean_t           warn_sigexpired;
                    125:        isc_boolean_t           seen_include;
                    126:        isc_uint32_t            ttl;
                    127:        isc_uint32_t            default_ttl;
                    128:        dns_rdataclass_t        zclass;
                    129:        dns_fixedname_t         fixed_top;
                    130:        dns_name_t              *top;                   /*%< top of zone */
                    131:
                    132:        /* Members specific to the raw format: */
                    133:        FILE                    *f;
                    134:        isc_boolean_t           first;
                    135:        dns_masterrawheader_t   header;
                    136:
                    137:        /* Which fixed buffers we are using? */
                    138:        unsigned int            loop_cnt;               /*% records per quantum,
                    139:                                                         * 0 => all. */
                    140:        isc_boolean_t           canceled;
                    141:        isc_mutex_t             lock;
                    142:        isc_result_t            result;
                    143:        /* locked by lock */
                    144:        isc_uint32_t            references;
                    145:        dns_incctx_t            *inc;
                    146:        isc_uint32_t            resign;
                    147:        isc_stdtime_t           now;
                    148:
                    149:        dns_masterincludecb_t   include_cb;
                    150:        void                    *include_arg;
                    151: };
                    152:
                    153: struct dns_incctx {
                    154:        dns_incctx_t            *parent;
                    155:        dns_name_t              *origin;
                    156:        dns_name_t              *current;
                    157:        dns_name_t              *glue;
                    158:        dns_fixedname_t         fixed[NBUFS];           /* working buffers */
                    159:        unsigned int            in_use[NBUFS];          /* covert to bitmap? */
                    160:        int                     glue_in_use;
                    161:        int                     current_in_use;
                    162:        int                     origin_in_use;
                    163:        isc_boolean_t           origin_changed;
                    164:        isc_boolean_t           drop;
                    165:        unsigned int            glue_line;
                    166:        unsigned int            current_line;
                    167: };
                    168:
                    169: #define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
                    170: #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
                    171:
                    172: #define DNS_AS_STR(t) ((t).value.as_textregion.base)
                    173:
                    174: static isc_result_t
                    175: openfile_text(dns_loadctx_t *lctx, const char *master_file);
                    176:
                    177: static isc_result_t
                    178: load_text(dns_loadctx_t *lctx);
                    179:
                    180: static isc_result_t
                    181: openfile_raw(dns_loadctx_t *lctx, const char *master_file);
                    182:
                    183: static isc_result_t
                    184: load_raw(dns_loadctx_t *lctx);
                    185:
                    186: static isc_result_t
                    187: openfile_map(dns_loadctx_t *lctx, const char *master_file);
                    188:
                    189: static isc_result_t
                    190: load_map(dns_loadctx_t *lctx);
                    191:
                    192: static isc_result_t
                    193: pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
                    194:
                    195: static isc_result_t
                    196: commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
                    197:        dns_name_t *, const char *, unsigned int);
                    198:
                    199: static isc_boolean_t
                    200: is_glue(rdatalist_head_t *, dns_name_t *);
                    201:
                    202: static dns_rdatalist_t *
                    203: grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
                    204:                rdatalist_head_t *, isc_mem_t *mctx);
                    205:
                    206: static dns_rdata_t *
                    207: grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
                    208:           isc_mem_t *);
                    209:
                    210: static void
                    211: load_quantum(isc_task_t *task, isc_event_t *event);
                    212:
                    213: static isc_result_t
                    214: task_send(dns_loadctx_t *lctx);
                    215:
                    216: static void
                    217: loadctx_destroy(dns_loadctx_t *lctx);
                    218:
                    219: #define GETTOKENERR(lexer, options, token, eol, err) \
                    220:        do { \
                    221:                result = gettoken(lexer, options, token, eol, callbacks); \
                    222:                switch (result) { \
                    223:                case ISC_R_SUCCESS: \
                    224:                        break; \
                    225:                case ISC_R_UNEXPECTED: \
                    226:                        goto insist_and_cleanup; \
                    227:                default: \
                    228:                        if (MANYERRS(lctx, result)) { \
                    229:                                SETRESULT(lctx, result); \
                    230:                                LOGIT(result); \
                    231:                                read_till_eol = ISC_TRUE; \
                    232:                                err \
                    233:                                goto next_line; \
                    234:                        } else \
                    235:                                goto log_and_cleanup; \
                    236:                } \
                    237:                if ((token)->type == isc_tokentype_special) { \
                    238:                        result = DNS_R_SYNTAX; \
                    239:                        if (MANYERRS(lctx, result)) { \
                    240:                                SETRESULT(lctx, result); \
                    241:                                LOGIT(result); \
                    242:                                read_till_eol = ISC_TRUE; \
                    243:                                goto next_line; \
                    244:                        } else \
                    245:                                goto log_and_cleanup; \
                    246:                } \
                    247:        } while (0)
                    248: #define GETTOKEN(lexer, options, token, eol) \
                    249:        GETTOKENERR(lexer, options, token, eol, {} )
                    250:
                    251: #define COMMITALL \
                    252:        do { \
                    253:                result = commit(callbacks, lctx, &current_list, \
                    254:                                ictx->current, source, ictx->current_line); \
                    255:                if (MANYERRS(lctx, result)) { \
                    256:                        SETRESULT(lctx, result); \
                    257:                } else if (result != ISC_R_SUCCESS) \
                    258:                        goto insist_and_cleanup; \
                    259:                result = commit(callbacks, lctx, &glue_list, \
                    260:                                ictx->glue, source, ictx->glue_line); \
                    261:                if (MANYERRS(lctx, result)) { \
                    262:                        SETRESULT(lctx, result); \
                    263:                } else if (result != ISC_R_SUCCESS) \
                    264:                        goto insist_and_cleanup; \
                    265:                rdcount = 0; \
                    266:                rdlcount = 0; \
                    267:                isc_buffer_init(&target, target_mem, target_size); \
                    268:                rdcount_save = rdcount; \
                    269:                rdlcount_save = rdlcount; \
                    270:        } while (0)
                    271:
                    272: #define WARNUNEXPECTEDEOF(lexer) \
                    273:        do { \
                    274:                if (isc_lex_isfile(lexer)) \
                    275:                        (*callbacks->warn)(callbacks, \
                    276:                                "%s: file does not end with newline", \
                    277:                                source); \
                    278:        } while (0)
                    279:
                    280: #define EXPECTEOL \
                    281:        do { \
                    282:                GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
                    283:                if (token.type != isc_tokentype_eol) { \
                    284:                        isc_lex_ungettoken(lctx->lex, &token); \
                    285:                        result = DNS_R_EXTRATOKEN; \
                    286:                        if (MANYERRS(lctx, result)) { \
                    287:                                SETRESULT(lctx, result); \
                    288:                                LOGIT(result); \
                    289:                                read_till_eol = ISC_TRUE; \
                    290:                                break; \
                    291:                        } else if (result != ISC_R_SUCCESS) \
                    292:                                goto log_and_cleanup; \
                    293:                } \
                    294:        } while (0)
                    295:
                    296: #define MANYERRS(lctx, result) \
                    297:                ((result != ISC_R_SUCCESS) && \
                    298:                 (result != ISC_R_IOERROR) && \
                    299:                 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
                    300:
                    301: #define SETRESULT(lctx, r) \
                    302:                do { \
                    303:                        if ((lctx)->result == ISC_R_SUCCESS) \
                    304:                                (lctx)->result = r; \
                    305:                } while (0)
                    306:
                    307: #define LOGITFILE(result, filename) \
                    308:        if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
                    309:            result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
                    310:            result == ISC_R_NOPERM) \
                    311:                (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
                    312:                                    "dns_master_load", source, line, \
                    313:                                    filename, dns_result_totext(result)); \
                    314:        else LOGIT(result)
                    315:
                    316: #define LOGIT(result) \
                    317:        if (result == ISC_R_NOMEMORY) \
                    318:                (*callbacks->error)(callbacks, "dns_master_load: %s", \
                    319:                                    dns_result_totext(result)); \
                    320:        else \
                    321:                (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
                    322:                                    "dns_master_load", \
                    323:                                    source, line, dns_result_totext(result))
                    324:
                    325:
                    326: static unsigned char in_addr_arpa_data[]  = "\007IN-ADDR\004ARPA";
                    327: static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
                    328: static dns_name_t const in_addr_arpa =
                    329:        DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets);
                    330:
                    331: static unsigned char ip6_int_data[]  = "\003IP6\003INT";
                    332: static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
                    333: static dns_name_t const ip6_int =
                    334:        DNS_NAME_INITABSOLUTE(ip6_int_data, ip6_int_offsets);
                    335:
                    336: static unsigned char ip6_arpa_data[]  = "\003IP6\004ARPA";
                    337: static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
                    338: static dns_name_t const ip6_arpa =
                    339:        DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets);
                    340:
                    341: static inline isc_result_t
                    342: gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
                    343:         isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
                    344: {
                    345:        isc_result_t result;
                    346:
                    347:        options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
                    348:                ISC_LEXOPT_ESCAPE;
                    349:        result = isc_lex_gettoken(lex, options, token);
                    350:        if (result != ISC_R_SUCCESS) {
                    351:                switch (result) {
                    352:                case ISC_R_NOMEMORY:
                    353:                        return (ISC_R_NOMEMORY);
                    354:                default:
                    355:                        (*callbacks->error)(callbacks,
                    356:                                            "dns_master_load: %s:%lu:"
                    357:                                            " isc_lex_gettoken() failed: %s",
                    358:                                            isc_lex_getsourcename(lex),
                    359:                                            isc_lex_getsourceline(lex),
                    360:                                            isc_result_totext(result));
                    361:                        return (result);
                    362:                }
                    363:                /*NOTREACHED*/
                    364:        }
                    365:        if (eol != ISC_TRUE)
                    366:                if (token->type == isc_tokentype_eol ||
                    367:                    token->type == isc_tokentype_eof) {
                    368:                        unsigned long int line;
                    369:                        const char *what;
                    370:                        const char *file;
                    371:                        file = isc_lex_getsourcename(lex);
                    372:                        line = isc_lex_getsourceline(lex);
                    373:                        if (token->type == isc_tokentype_eol) {
                    374:                                line--;
                    375:                                what = "line";
                    376:                        } else
                    377:                                what = "file";
                    378:                        (*callbacks->error)(callbacks,
                    379:                            "dns_master_load: %s:%lu: unexpected end of %s",
                    380:                                            file, line, what);
                    381:                        return (ISC_R_UNEXPECTEDEND);
                    382:                }
                    383:        return (ISC_R_SUCCESS);
                    384: }
                    385:
                    386:
                    387: void
                    388: dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
                    389:
                    390:        REQUIRE(target != NULL && *target == NULL);
                    391:        REQUIRE(DNS_LCTX_VALID(source));
                    392:
                    393:        LOCK(&source->lock);
                    394:        INSIST(source->references > 0);
                    395:        source->references++;
                    396:        INSIST(source->references != 0);        /* Overflow? */
                    397:        UNLOCK(&source->lock);
                    398:
                    399:        *target = source;
                    400: }
                    401:
                    402: void
                    403: dns_loadctx_detach(dns_loadctx_t **lctxp) {
                    404:        dns_loadctx_t *lctx;
                    405:        isc_boolean_t need_destroy = ISC_FALSE;
                    406:
                    407:        REQUIRE(lctxp != NULL);
                    408:        lctx = *lctxp;
                    409:        REQUIRE(DNS_LCTX_VALID(lctx));
                    410:
                    411:        LOCK(&lctx->lock);
                    412:        INSIST(lctx->references > 0);
                    413:        lctx->references--;
                    414:        if (lctx->references == 0)
                    415:                need_destroy = ISC_TRUE;
                    416:        UNLOCK(&lctx->lock);
                    417:
                    418:        if (need_destroy)
                    419:                loadctx_destroy(lctx);
                    420:        *lctxp = NULL;
                    421: }
                    422:
                    423: static void
                    424: incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
                    425:        dns_incctx_t *parent;
                    426:
                    427:  again:
                    428:        parent = ictx->parent;
                    429:        ictx->parent = NULL;
                    430:
                    431:        isc_mem_put(mctx, ictx, sizeof(*ictx));
                    432:
                    433:        if (parent != NULL) {
                    434:                ictx = parent;
                    435:                goto again;
                    436:        }
                    437: }
                    438:
                    439: static void
                    440: loadctx_destroy(dns_loadctx_t *lctx) {
                    441:        isc_mem_t *mctx;
                    442:        isc_result_t result;
                    443:
                    444:        REQUIRE(DNS_LCTX_VALID(lctx));
                    445:
                    446:        lctx->magic = 0;
                    447:        if (lctx->inc != NULL)
                    448:                incctx_destroy(lctx->mctx, lctx->inc);
                    449:
                    450:        if (lctx->f != NULL) {
                    451:                result = isc_stdio_close(lctx->f);
                    452:                if (result != ISC_R_SUCCESS) {
                    453:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                    454:                                         "isc_stdio_close() failed: %s",
                    455:                                         isc_result_totext(result));
                    456:                }
                    457:        }
                    458:
                    459:        /* isc_lex_destroy() will close all open streams */
                    460:        if (lctx->lex != NULL && !lctx->keep_lex)
                    461:                isc_lex_destroy(&lctx->lex);
                    462:
                    463:        if (lctx->task != NULL)
                    464:                isc_task_detach(&lctx->task);
                    465:        DESTROYLOCK(&lctx->lock);
                    466:        mctx = NULL;
                    467:        isc_mem_attach(lctx->mctx, &mctx);
                    468:        isc_mem_detach(&lctx->mctx);
                    469:        isc_mem_put(mctx, lctx, sizeof(*lctx));
                    470:        isc_mem_detach(&mctx);
                    471: }
                    472:
                    473: static isc_result_t
                    474: incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
                    475:        dns_incctx_t *ictx;
                    476:        isc_region_t r;
                    477:        int i;
                    478:
                    479:        ictx = isc_mem_get(mctx, sizeof(*ictx));
                    480:        if (ictx == NULL)
                    481:                return (ISC_R_NOMEMORY);
                    482:
                    483:        for (i = 0; i < NBUFS; i++) {
                    484:                dns_fixedname_init(&ictx->fixed[i]);
                    485:                ictx->in_use[i] = ISC_FALSE;
                    486:        }
                    487:
                    488:        ictx->origin_in_use = 0;
                    489:        ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
                    490:        ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
                    491:        dns_name_toregion(origin, &r);
                    492:        dns_name_fromregion(ictx->origin, &r);
                    493:
                    494:        ictx->glue = NULL;
                    495:        ictx->current = NULL;
                    496:        ictx->glue_in_use = -1;
                    497:        ictx->current_in_use = -1;
                    498:        ictx->parent = NULL;
                    499:        ictx->drop = ISC_FALSE;
                    500:        ictx->glue_line = 0;
                    501:        ictx->current_line = 0;
                    502:        ictx->origin_changed = ISC_TRUE;
                    503:
                    504:        *ictxp = ictx;
                    505:        return (ISC_R_SUCCESS);
                    506: }
                    507:
                    508: static isc_result_t
                    509: loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
                    510:               unsigned int options, isc_uint32_t resign, dns_name_t *top,
                    511:               dns_rdataclass_t zclass, dns_name_t *origin,
                    512:               dns_rdatacallbacks_t *callbacks, isc_task_t *task,
                    513:               dns_loaddonefunc_t done, void *done_arg,
                    514:               dns_masterincludecb_t include_cb, void *include_arg,
                    515:               isc_lex_t *lex, dns_loadctx_t **lctxp)
                    516: {
                    517:        dns_loadctx_t *lctx;
                    518:        isc_result_t result;
                    519:        isc_region_t r;
                    520:        isc_lexspecials_t specials;
                    521:
                    522:        REQUIRE(lctxp != NULL && *lctxp == NULL);
                    523:        REQUIRE(callbacks != NULL);
                    524:        REQUIRE(callbacks->add != NULL);
                    525:        REQUIRE(callbacks->error != NULL);
                    526:        REQUIRE(callbacks->warn != NULL);
                    527:        REQUIRE(mctx != NULL);
                    528:        REQUIRE(dns_name_isabsolute(top));
                    529:        REQUIRE(dns_name_isabsolute(origin));
                    530:        REQUIRE((task == NULL && done == NULL) ||
                    531:                (task != NULL && done != NULL));
                    532:
                    533:        lctx = isc_mem_get(mctx, sizeof(*lctx));
                    534:        if (lctx == NULL)
                    535:                return (ISC_R_NOMEMORY);
                    536:        result = isc_mutex_init(&lctx->lock);
                    537:        if (result != ISC_R_SUCCESS) {
                    538:                isc_mem_put(mctx, lctx, sizeof(*lctx));
                    539:                return (result);
                    540:        }
                    541:
                    542:        lctx->inc = NULL;
                    543:        result = incctx_create(mctx, origin, &lctx->inc);
                    544:        if (result != ISC_R_SUCCESS)
                    545:                goto cleanup_ctx;
                    546:
                    547:        lctx->maxttl = 0;
                    548:
                    549:        lctx->format = format;
                    550:        switch (format) {
                    551:        default:
                    552:                INSIST(0);
                    553:        case dns_masterformat_text:
                    554:                lctx->openfile = openfile_text;
                    555:                lctx->load = load_text;
                    556:                break;
                    557:        case dns_masterformat_raw:
                    558:                lctx->openfile = openfile_raw;
                    559:                lctx->load = load_raw;
                    560:                break;
                    561:        case dns_masterformat_map:
                    562:                lctx->openfile = openfile_map;
                    563:                lctx->load = load_map;
                    564:                break;
                    565:        }
                    566:
                    567:        if (lex != NULL) {
                    568:                lctx->lex = lex;
                    569:                lctx->keep_lex = ISC_TRUE;
                    570:        } else {
                    571:                lctx->lex = NULL;
                    572:                result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
                    573:                if (result != ISC_R_SUCCESS)
                    574:                        goto cleanup_inc;
                    575:                lctx->keep_lex = ISC_FALSE;
                    576:                memset(specials, 0, sizeof(specials));
                    577:                specials[0] = 1;
                    578:                specials['('] = 1;
                    579:                specials[')'] = 1;
                    580:                specials['"'] = 1;
                    581:                isc_lex_setspecials(lctx->lex, specials);
                    582:                isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
                    583:        }
                    584:
                    585:        lctx->ttl_known = ISC_TF((options & DNS_MASTER_NOTTL) != 0);
                    586:        lctx->ttl = 0;
                    587:        lctx->default_ttl_known = lctx->ttl_known;
                    588:        lctx->default_ttl = 0;
                    589:        lctx->warn_1035 = ISC_TRUE;     /* XXX Argument? */
                    590:        lctx->warn_tcr = ISC_TRUE;      /* XXX Argument? */
                    591:        lctx->warn_sigexpired = ISC_TRUE;       /* XXX Argument? */
                    592:        lctx->options = options;
                    593:        lctx->seen_include = ISC_FALSE;
                    594:        lctx->zclass = zclass;
                    595:        lctx->resign = resign;
                    596:        lctx->result = ISC_R_SUCCESS;
                    597:        lctx->include_cb = include_cb;
                    598:        lctx->include_arg = include_arg;
                    599:        isc_stdtime_get(&lctx->now);
                    600:
                    601:        lctx->top = dns_fixedname_initname(&lctx->fixed_top);
                    602:        dns_name_toregion(top, &r);
                    603:        dns_name_fromregion(lctx->top, &r);
                    604:
                    605:        lctx->f = NULL;
                    606:        lctx->first = ISC_TRUE;
                    607:        dns_master_initrawheader(&lctx->header);
                    608:
                    609:        lctx->loop_cnt = (done != NULL) ? 100 : 0;
                    610:        lctx->callbacks = callbacks;
                    611:        lctx->task = NULL;
                    612:        if (task != NULL)
                    613:                isc_task_attach(task, &lctx->task);
                    614:        lctx->done = done;
                    615:        lctx->done_arg = done_arg;
                    616:        lctx->canceled = ISC_FALSE;
                    617:        lctx->mctx = NULL;
                    618:        isc_mem_attach(mctx, &lctx->mctx);
                    619:        lctx->references = 1;                   /* Implicit attach. */
                    620:        lctx->magic = DNS_LCTX_MAGIC;
                    621:        *lctxp = lctx;
                    622:        return (ISC_R_SUCCESS);
                    623:
                    624:  cleanup_inc:
                    625:        incctx_destroy(mctx, lctx->inc);
                    626:  cleanup_ctx:
                    627:        isc_mem_put(mctx, lctx, sizeof(*lctx));
                    628:        return (result);
                    629: }
                    630:
                    631: static const char *hex = "0123456789abcdef0123456789ABCDEF";
                    632:
                    633: /*%
                    634:  * Convert value into a nibble sequence from least significant to most
                    635:  * significant nibble.  Zero fill upper most significant nibbles if
                    636:  * required to make the width.
                    637:  *
                    638:  * Returns the number of characters that should have been written without
                    639:  * counting the terminating NUL.
                    640:  */
                    641: static unsigned int
                    642: nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
                    643:        unsigned int count = 0;
                    644:
                    645:        /*
                    646:         * This reserve space for the NUL string terminator.
                    647:         */
                    648:        if (length > 0U) {
                    649:                *numbuf = '\0';
                    650:                length--;
                    651:        }
                    652:        do {
                    653:                char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
                    654:                value >>= 4;
                    655:                if (length > 0U) {
                    656:                        *numbuf++ = val;
                    657:                        *numbuf = '\0';
                    658:                        length--;
                    659:                }
                    660:                if (width > 0)
                    661:                        width--;
                    662:                count++;
                    663:                /*
                    664:                 * If width is non zero then we need to add a label seperator.
                    665:                 * If value is non zero then we need to add another label and
                    666:                 * that requires a label seperator.
                    667:                 */
                    668:                if (width > 0 || value != 0) {
                    669:                        if (length > 0U) {
                    670:                                *numbuf++ = '.';
                    671:                                *numbuf = '\0';
                    672:                                length--;
                    673:                        }
                    674:                        if (width > 0)
                    675:                                width--;
                    676:                        count++;
                    677:                }
                    678:        } while (value != 0 || width > 0);
                    679:        return (count);
                    680: }
                    681:
                    682: static isc_result_t
                    683: genname(char *name, int it, char *buffer, size_t length) {
                    684:        char fmt[sizeof("%04000000000d")];
                    685:        char numbuf[128];
                    686:        char *cp;
                    687:        char mode[2];
                    688:        int delta = 0;
                    689:        isc_textregion_t r;
                    690:        unsigned int n;
                    691:        unsigned int width;
                    692:        isc_boolean_t nibblemode;
                    693:
                    694:        r.base = buffer;
                    695:        r.length = (unsigned int)length;
                    696:
                    697:        while (*name != '\0') {
                    698:                if (*name == '$') {
                    699:                        name++;
                    700:                        if (*name == '$') {
                    701:                                if (r.length == 0)
                    702:                                        return (ISC_R_NOSPACE);
                    703:                                r.base[0] = *name++;
                    704:                                isc_textregion_consume(&r, 1);
                    705:                                continue;
                    706:                        }
                    707:                        nibblemode = ISC_FALSE;
                    708:                        strlcpy(fmt, "%d", sizeof(fmt));
                    709:                        /* Get format specifier. */
                    710:                        if (*name == '{' ) {
                    711:                                n = sscanf(name, "{%d,%u,%1[doxXnN]}",
                    712:                                           &delta, &width, mode);
                    713:                                switch (n) {
                    714:                                case 1:
                    715:                                        break;
                    716:                                case 2:
                    717:                                        n = snprintf(fmt, sizeof(fmt),
                    718:                                                     "%%0%ud", width);
                    719:                                        break;
                    720:                                case 3:
                    721:                                        if (mode[0] == 'n' || mode[0] == 'N')
                    722:                                                nibblemode = ISC_TRUE;
                    723:                                        n = snprintf(fmt, sizeof(fmt),
                    724:                                                     "%%0%u%c", width, mode[0]);
                    725:                                        break;
                    726:                                default:
                    727:                                        return (DNS_R_SYNTAX);
                    728:                                }
                    729:                                if (n >= sizeof(fmt))
                    730:                                        return (ISC_R_NOSPACE);
                    731:                                /* Skip past closing brace. */
                    732:                                while (*name != '\0' && *name++ != '}')
                    733:                                        continue;
                    734:                        }
                    735:                        if (nibblemode)
                    736:                                n = nibbles(numbuf, sizeof(numbuf), width,
                    737:                                            mode[0], it + delta);
                    738:                        else
                    739:                                n = snprintf(numbuf, sizeof(numbuf), fmt,
                    740:                                             it + delta);
                    741:                        if (n >= sizeof(numbuf))
                    742:                                return (ISC_R_NOSPACE);
                    743:                        cp = numbuf;
                    744:                        while (*cp != '\0') {
                    745:                                if (r.length == 0)
                    746:                                        return (ISC_R_NOSPACE);
                    747:                                r.base[0] = *cp++;
                    748:                                isc_textregion_consume(&r, 1);
                    749:                        }
                    750:                } else if (*name == '\\') {
                    751:                        if (r.length == 0)
                    752:                                return (ISC_R_NOSPACE);
                    753:                        r.base[0] = *name++;
                    754:                        isc_textregion_consume(&r, 1);
                    755:                        if (*name == '\0')
                    756:                                continue;
                    757:                        if (r.length == 0)
                    758:                                return (ISC_R_NOSPACE);
                    759:                        r.base[0] = *name++;
                    760:                        isc_textregion_consume(&r, 1);
                    761:                } else {
                    762:                        if (r.length == 0)
                    763:                                return (ISC_R_NOSPACE);
                    764:                        r.base[0] = *name++;
                    765:                        isc_textregion_consume(&r, 1);
                    766:                }
                    767:        }
                    768:        if (r.length == 0)
                    769:                return (ISC_R_NOSPACE);
                    770:        r.base[0] = '\0';
                    771:        return (ISC_R_SUCCESS);
                    772: }
                    773:
                    774: static isc_result_t
                    775: generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
                    776:         const char *source, unsigned int line)
                    777: {
                    778:        char *target_mem = NULL;
                    779:        char *lhsbuf = NULL;
                    780:        char *rhsbuf = NULL;
                    781:        dns_fixedname_t ownerfixed;
                    782:        dns_name_t *owner;
                    783:        dns_rdata_t rdata = DNS_RDATA_INIT;
                    784:        dns_rdatacallbacks_t *callbacks;
                    785:        dns_rdatalist_t rdatalist;
                    786:        dns_rdatatype_t type;
                    787:        rdatalist_head_t head;
                    788:        int target_size = MINTSIZ;      /* only one rdata at a time */
                    789:        isc_buffer_t buffer;
                    790:        isc_buffer_t target;
                    791:        isc_result_t result;
                    792:        isc_textregion_t r;
                    793:        int i, n, start, stop, step = 0;
                    794:        dns_incctx_t *ictx;
                    795:        char dummy[2];
                    796:
                    797:        ictx = lctx->inc;
                    798:        callbacks = lctx->callbacks;
                    799:        owner = dns_fixedname_initname(&ownerfixed);
                    800:        ISC_LIST_INIT(head);
                    801:
                    802:        target_mem = isc_mem_get(lctx->mctx, target_size);
                    803:        rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
                    804:        lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
                    805:        if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
                    806:                result = ISC_R_NOMEMORY;
                    807:                goto error_cleanup;
                    808:        }
                    809:        isc_buffer_init(&target, target_mem, target_size);
                    810:
                    811:        n = sscanf(range, "%d-%d%1[/]%d", &start, &stop, dummy, &step);
                    812:        if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
                    813:             (n == 4 && step < 1) || (stop < start))
                    814:        {
                    815:               (*callbacks->error)(callbacks,
                    816:                                  "%s: %s:%lu: invalid range '%s'",
                    817:                                  "$GENERATE", source, line, range);
                    818:                result = DNS_R_SYNTAX;
                    819:                goto insist_cleanup;
                    820:        }
                    821:        if (n == 2)
                    822:                step = 1;
                    823:
                    824:        /*
                    825:         * Get type.
                    826:         */
                    827:        r.base = gtype;
                    828:        r.length = strlen(gtype);
                    829:        result = dns_rdatatype_fromtext(&type, &r);
                    830:        if (result != ISC_R_SUCCESS) {
                    831:                (*callbacks->error)(callbacks,
                    832:                                   "%s: %s:%lu: unknown RR type '%s'",
                    833:                                   "$GENERATE", source, line, gtype);
                    834:                goto insist_cleanup;
                    835:        }
                    836:
                    837:        /*
                    838:         * RFC2930: TKEY and TSIG are not allowed to be loaded
                    839:         * from master files.
                    840:         */
                    841:        if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                    842:            (lctx->options & DNS_MASTER_SLAVE) == 0 &&
                    843:            dns_rdatatype_ismeta(type))
                    844:        {
                    845:                (*callbacks->error)(callbacks,
                    846:                                   "%s: %s:%lu: meta RR type '%s'",
                    847:                                   "$GENERATE",
                    848:                                   source, line, gtype);
                    849:                result = DNS_R_METATYPE;
                    850:                goto insist_cleanup;
                    851:        }
                    852:
                    853:        for (i = start; i <= stop; i += step) {
                    854:                result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
                    855:                if (result != ISC_R_SUCCESS)
                    856:                        goto error_cleanup;
                    857:                result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
                    858:                if (result != ISC_R_SUCCESS)
                    859:                        goto error_cleanup;
                    860:
                    861:                isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
                    862:                isc_buffer_add(&buffer, strlen(lhsbuf));
                    863:                isc_buffer_setactive(&buffer, strlen(lhsbuf));
                    864:                result = dns_name_fromtext(owner, &buffer, ictx->origin,
                    865:                                           0, NULL);
                    866:                if (result != ISC_R_SUCCESS)
                    867:                        goto error_cleanup;
                    868:
                    869:                if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                    870:                    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
                    871:                    (lctx->options & DNS_MASTER_KEY) == 0 &&
                    872:                    !dns_name_issubdomain(owner, lctx->top))
                    873:                {
                    874:                        char namebuf[DNS_NAME_FORMATSIZE];
                    875:                        dns_name_format(owner, namebuf, sizeof(namebuf));
                    876:                        /*
                    877:                         * Ignore out-of-zone data.
                    878:                         */
                    879:                        (*callbacks->warn)(callbacks,
                    880:                                           "%s:%lu: "
                    881:                                           "ignoring out-of-zone data (%s)",
                    882:                                           source, line, namebuf);
                    883:                        continue;
                    884:                }
                    885:
                    886:                isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
                    887:                isc_buffer_add(&buffer, strlen(rhsbuf));
                    888:                isc_buffer_setactive(&buffer, strlen(rhsbuf));
                    889:
                    890:                result = isc_lex_openbuffer(lctx->lex, &buffer);
                    891:                if (result != ISC_R_SUCCESS)
                    892:                        goto error_cleanup;
                    893:
                    894:                isc_buffer_init(&target, target_mem, target_size);
                    895:                result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
                    896:                                            lctx->lex, ictx->origin, 0,
                    897:                                            lctx->mctx, &target, callbacks);
                    898:                RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
                    899:                if (result != ISC_R_SUCCESS)
                    900:                        goto error_cleanup;
                    901:
                    902:                dns_rdatalist_init(&rdatalist);
                    903:                rdatalist.type = type;
                    904:                rdatalist.rdclass = lctx->zclass;
                    905:                rdatalist.ttl = lctx->ttl;
                    906:                ISC_LIST_PREPEND(head, &rdatalist, link);
                    907:                ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
                    908:                result = commit(callbacks, lctx, &head, owner, source, line);
                    909:                ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
                    910:                if (result != ISC_R_SUCCESS)
                    911:                        goto error_cleanup;
                    912:                dns_rdata_reset(&rdata);
                    913:        }
                    914:        result = ISC_R_SUCCESS;
                    915:        goto cleanup;
                    916:
                    917:  error_cleanup:
                    918:        if (result == ISC_R_NOMEMORY)
                    919:                (*callbacks->error)(callbacks, "$GENERATE: %s",
                    920:                                    dns_result_totext(result));
                    921:        else
                    922:                (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
                    923:                                    source, line, dns_result_totext(result));
                    924:
                    925:  insist_cleanup:
                    926:        INSIST(result != ISC_R_SUCCESS);
                    927:
                    928:  cleanup:
                    929:        if (target_mem != NULL)
                    930:                isc_mem_put(lctx->mctx, target_mem, target_size);
                    931:        if (lhsbuf != NULL)
                    932:                isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
                    933:        if (rhsbuf != NULL)
                    934:                isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
                    935:        return (result);
                    936: }
                    937:
                    938: static void
                    939: limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source,
                    940:          unsigned int line, isc_uint32_t *ttlp)
                    941: {
                    942:        if (*ttlp > 0x7fffffffUL) {
                    943:                (callbacks->warn)(callbacks,
                    944:                                  "%s: %s:%lu: "
                    945:                                  "$TTL %lu > MAXTTL, "
                    946:                                  "setting $TTL to 0",
                    947:                                  "dns_master_load",
                    948:                                  source, line,
                    949:                                  *ttlp);
                    950:                *ttlp = 0;
                    951:        }
                    952: }
                    953:
                    954: static isc_result_t
                    955: check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
                    956:         unsigned long line)
                    957: {
                    958:        char *tmp = NULL;
                    959:        isc_result_t result = ISC_R_SUCCESS;
                    960:        void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
                    961:
                    962:        if ((lctx->options & DNS_MASTER_FATALNS) != 0)
                    963:                callback = lctx->callbacks->error;
                    964:        else
                    965:                callback = lctx->callbacks->warn;
                    966:
                    967:        if (token->type == isc_tokentype_string) {
                    968:                struct in_addr addr;
                    969:                struct in6_addr addr6;
                    970:
                    971:                tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
                    972:                if (tmp == NULL)
                    973:                        return (ISC_R_NOMEMORY);
                    974:                /*
                    975:                 * Catch both "1.2.3.4" and "1.2.3.4."
                    976:                 */
                    977:                if (tmp[strlen(tmp) - 1] == '.')
                    978:                        tmp[strlen(tmp) - 1] = '\0';
                    979:                if (inet_aton(tmp, &addr) == 1 ||
                    980:                    inet_pton(AF_INET6, tmp, &addr6) == 1)
                    981:                        result = DNS_R_NSISADDRESS;
                    982:        }
                    983:        if (result != ISC_R_SUCCESS)
                    984:                (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
                    985:                            "appears to be an address",
                    986:                            source, line, DNS_AS_STR(*token));
                    987:        if (tmp != NULL)
                    988:                isc_mem_free(lctx->mctx, tmp);
                    989:        return (result);
                    990: }
                    991:
                    992: static void
                    993: check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
                    994:               dns_rdatacallbacks_t *callbacks)
                    995: {
                    996:        dns_name_t *name;
                    997:
                    998:        name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
                    999:        if (dns_name_internalwildcard(name)) {
                   1000:                char namebuf[DNS_NAME_FORMATSIZE];
                   1001:
                   1002:                dns_name_format(name, namebuf, sizeof(namebuf));
                   1003:                (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
                   1004:                                   "'%s' contains an non-terminal wildcard",
                   1005:                                   source, line, namebuf);
                   1006:        }
                   1007: }
                   1008:
                   1009: static isc_result_t
                   1010: openfile_text(dns_loadctx_t *lctx, const char *master_file) {
                   1011:        return (isc_lex_openfile(lctx->lex, master_file));
                   1012: }
                   1013:
                   1014: static int
                   1015: find_free_name(dns_incctx_t *incctx) {
                   1016:        int i;
                   1017:
                   1018:        for (i = 0; i < (NBUFS - 1); i++) {
                   1019:                if (!incctx->in_use[i]) {
                   1020:                        break;
                   1021:                }
                   1022:        }
                   1023:        INSIST(!incctx->in_use[i]);
                   1024:        return (i);
                   1025: }
                   1026:
                   1027: static isc_result_t
                   1028: load_text(dns_loadctx_t *lctx) {
                   1029:        dns_rdataclass_t rdclass;
                   1030:        dns_rdatatype_t type, covers;
                   1031:        isc_uint32_t ttl_offset = 0;
                   1032:        dns_name_t *new_name;
                   1033:        isc_boolean_t current_has_delegation = ISC_FALSE;
                   1034:        isc_boolean_t done = ISC_FALSE;
                   1035:        isc_boolean_t finish_origin = ISC_FALSE;
                   1036:        isc_boolean_t finish_include = ISC_FALSE;
                   1037:        isc_boolean_t read_till_eol = ISC_FALSE;
                   1038:        isc_boolean_t initialws;
                   1039:        char *include_file = NULL;
                   1040:        isc_token_t token;
                   1041:        isc_result_t result = ISC_R_UNEXPECTED;
                   1042:        rdatalist_head_t glue_list;
                   1043:        rdatalist_head_t current_list;
                   1044:        dns_rdatalist_t *this;
                   1045:        dns_rdatalist_t *rdatalist = NULL;
                   1046:        dns_rdatalist_t *new_rdatalist;
                   1047:        int rdlcount = 0;
                   1048:        int rdlcount_save = 0;
                   1049:        int rdatalist_size = 0;
                   1050:        isc_buffer_t buffer;
                   1051:        isc_buffer_t target;
                   1052:        isc_buffer_t target_ft;
                   1053:        isc_buffer_t target_save;
                   1054:        dns_rdata_t *rdata = NULL;
                   1055:        dns_rdata_t *new_rdata;
                   1056:        int rdcount = 0;
                   1057:        int rdcount_save = 0;
                   1058:        int rdata_size = 0;
                   1059:        unsigned char *target_mem = NULL;
                   1060:        int target_size = TSIZ;
                   1061:        int new_in_use;
                   1062:        unsigned int loop_cnt = 0;
                   1063:        isc_mem_t *mctx;
                   1064:        dns_rdatacallbacks_t *callbacks;
                   1065:        dns_incctx_t *ictx;
                   1066:        char *range = NULL;
                   1067:        char *lhs = NULL;
                   1068:        char *gtype = NULL;
                   1069:        char *rhs = NULL;
                   1070:        const char *source = "";
                   1071:        unsigned long line = 0;
                   1072:        isc_boolean_t explicit_ttl;
                   1073:        char classname1[DNS_RDATACLASS_FORMATSIZE];
                   1074:        char classname2[DNS_RDATACLASS_FORMATSIZE];
                   1075:        unsigned int options = 0;
                   1076:
                   1077:        REQUIRE(DNS_LCTX_VALID(lctx));
                   1078:        callbacks = lctx->callbacks;
                   1079:        mctx = lctx->mctx;
                   1080:        ictx = lctx->inc;
                   1081:
                   1082:        ISC_LIST_INIT(glue_list);
                   1083:        ISC_LIST_INIT(current_list);
                   1084:
                   1085:
                   1086:        /*
                   1087:         * Allocate target_size of buffer space.  This is greater than twice
                   1088:         * the maximum individual RR data size.
                   1089:         */
                   1090:        target_mem = isc_mem_get(mctx, target_size);
                   1091:        if (target_mem == NULL) {
                   1092:                result = ISC_R_NOMEMORY;
                   1093:                goto log_and_cleanup;
                   1094:        }
                   1095:        isc_buffer_init(&target, target_mem, target_size);
                   1096:        target_save = target;
                   1097:
                   1098:        if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
                   1099:                options |= DNS_RDATA_CHECKNAMES;
                   1100:        if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
                   1101:                options |= DNS_RDATA_CHECKNAMESFAIL;
                   1102:        if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
                   1103:                options |= DNS_RDATA_CHECKMX;
                   1104:        if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
                   1105:                options |= DNS_RDATA_CHECKMXFAIL;
                   1106:        source = isc_lex_getsourcename(lctx->lex);
                   1107:        do {
                   1108:                initialws = ISC_FALSE;
                   1109:                line = isc_lex_getsourceline(lctx->lex);
                   1110:                GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
                   1111:                         &token, ISC_TRUE);
                   1112:                line = isc_lex_getsourceline(lctx->lex);
                   1113:
                   1114:                if (token.type == isc_tokentype_eof) {
                   1115:                        if (read_till_eol)
                   1116:                                WARNUNEXPECTEDEOF(lctx->lex);
                   1117:                        /* Pop the include stack? */
                   1118:                        if (ictx->parent != NULL) {
                   1119:                                COMMITALL;
                   1120:                                lctx->inc = ictx->parent;
                   1121:                                ictx->parent = NULL;
                   1122:                                incctx_destroy(lctx->mctx, ictx);
                   1123:                                RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
                   1124:                                line = isc_lex_getsourceline(lctx->lex);
                   1125:                                POST(line);
                   1126:                                source = isc_lex_getsourcename(lctx->lex);
                   1127:                                ictx = lctx->inc;
                   1128:                                continue;
                   1129:                        }
                   1130:                        done = ISC_TRUE;
                   1131:                        continue;
                   1132:                }
                   1133:
                   1134:                if (token.type == isc_tokentype_eol) {
                   1135:                        read_till_eol = ISC_FALSE;
                   1136:                        continue;               /* blank line */
                   1137:                }
                   1138:
                   1139:                if (read_till_eol)
                   1140:                        continue;
                   1141:
                   1142:                if (token.type == isc_tokentype_initialws) {
                   1143:                        /*
                   1144:                         * Still working on the same name.
                   1145:                         */
                   1146:                        initialws = ISC_TRUE;
                   1147:                } else if (token.type == isc_tokentype_string ||
                   1148:                           token.type == isc_tokentype_qstring) {
                   1149:
                   1150:                        /*
                   1151:                         * "$" Support.
                   1152:                         *
                   1153:                         * "$ORIGIN" and "$INCLUDE" can both take domain names.
                   1154:                         * The processing of "$ORIGIN" and "$INCLUDE" extends
                   1155:                         * across the normal domain name processing.
                   1156:                         */
                   1157:
                   1158:                        if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
                   1159:                                GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1160:                                finish_origin = ISC_TRUE;
                   1161:                        } else if (strcasecmp(DNS_AS_STR(token),
                   1162:                                              "$TTL") == 0) {
                   1163:                                GETTOKENERR(lctx->lex, 0, &token, ISC_FALSE,
                   1164:                                            lctx->ttl = 0;
                   1165:                                            lctx->default_ttl_known = ISC_TRUE;);
                   1166:                                result =
                   1167:                                   dns_ttl_fromtext(&token.value.as_textregion,
                   1168:                                                    &lctx->ttl);
                   1169:                                if (MANYERRS(lctx, result)) {
                   1170:                                        SETRESULT(lctx, result);
                   1171:                                        lctx->ttl = 0;
                   1172:                                } else if (result != ISC_R_SUCCESS)
                   1173:                                        goto insist_and_cleanup;
                   1174:                                limit_ttl(callbacks, source, line, &lctx->ttl);
                   1175:                                lctx->default_ttl = lctx->ttl;
                   1176:                                lctx->default_ttl_known = ISC_TRUE;
                   1177:                                EXPECTEOL;
                   1178:                                continue;
                   1179:                        } else if (strcasecmp(DNS_AS_STR(token),
                   1180:                                              "$INCLUDE") == 0) {
                   1181:                                COMMITALL;
                   1182:                                if ((lctx->options & DNS_MASTER_NOINCLUDE)
                   1183:                                    != 0)
                   1184:                                {
                   1185:                                        (callbacks->error)(callbacks,
                   1186:                                           "%s: %s:%lu: $INCLUDE not allowed",
                   1187:                                           "dns_master_load",
                   1188:                                           source, line);
                   1189:                                        result = DNS_R_REFUSED;
                   1190:                                        goto insist_and_cleanup;
                   1191:                                }
                   1192:                                if (ttl_offset != 0) {
                   1193:                                        (callbacks->error)(callbacks,
                   1194:                                           "%s: %s:%lu: $INCLUDE "
                   1195:                                           "may not be used with $DATE",
                   1196:                                           "dns_master_load",
                   1197:                                           source, line);
                   1198:                                        result = DNS_R_SYNTAX;
                   1199:                                        goto insist_and_cleanup;
                   1200:                                }
                   1201:                                GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
                   1202:                                         ISC_FALSE);
                   1203:                                if (include_file != NULL)
                   1204:                                        isc_mem_free(mctx, include_file);
                   1205:                                include_file = isc_mem_strdup(mctx,
                   1206:                                                           DNS_AS_STR(token));
                   1207:                                if (include_file == NULL) {
                   1208:                                        result = ISC_R_NOMEMORY;
                   1209:                                        goto log_and_cleanup;
                   1210:                                }
                   1211:                                GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
                   1212:
                   1213:                                if (token.type == isc_tokentype_eol ||
                   1214:                                    token.type == isc_tokentype_eof) {
                   1215:                                        if (token.type == isc_tokentype_eof)
                   1216:                                                WARNUNEXPECTEDEOF(lctx->lex);
                   1217:                                        /*
                   1218:                                         * No origin field.
                   1219:                                         */
                   1220:                                        result = pushfile(include_file,
                   1221:                                                          ictx->origin, lctx);
                   1222:                                        if (MANYERRS(lctx, result)) {
                   1223:                                                SETRESULT(lctx, result);
                   1224:                                                LOGITFILE(result, include_file);
                   1225:                                                continue;
                   1226:                                        } else if (result != ISC_R_SUCCESS) {
                   1227:                                                LOGITFILE(result, include_file);
                   1228:                                                goto insist_and_cleanup;
                   1229:                                        }
                   1230:                                        ictx = lctx->inc;
                   1231:                                        source =
                   1232:                                               isc_lex_getsourcename(lctx->lex);
                   1233:                                        line = isc_lex_getsourceline(lctx->lex);
                   1234:                                        POST(line);
                   1235:                                        continue;
                   1236:                                }
                   1237:                                /*
                   1238:                                 * There is an origin field.  Fall through
                   1239:                                 * to domain name processing code and do
                   1240:                                 * the actual inclusion later.
                   1241:                                 */
                   1242:                                finish_include = ISC_TRUE;
                   1243:                        } else if (strcasecmp(DNS_AS_STR(token),
                   1244:                                              "$DATE") == 0) {
                   1245:                                isc_int64_t dump_time64;
                   1246:                                isc_stdtime_t dump_time, current_time;
                   1247:                                GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1248:                                isc_stdtime_get(&current_time);
                   1249:                                result = dns_time64_fromtext(DNS_AS_STR(token),
                   1250:                                                             &dump_time64);
                   1251:                                if (MANYERRS(lctx, result)) {
                   1252:                                        SETRESULT(lctx, result);
                   1253:                                        LOGIT(result);
                   1254:                                        dump_time64 = 0;
                   1255:                                } else if (result != ISC_R_SUCCESS)
                   1256:                                        goto log_and_cleanup;
                   1257:                                dump_time = (isc_stdtime_t)dump_time64;
                   1258:                                if (dump_time != dump_time64) {
                   1259:                                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                   1260:                                         "%s: %s:%lu: $DATE outside epoch",
                   1261:                                         "dns_master_load", source, line);
                   1262:                                        result = ISC_R_UNEXPECTED;
                   1263:                                        goto insist_and_cleanup;
                   1264:                                }
                   1265:                                if (dump_time > current_time) {
                   1266:                                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                   1267:                                        "%s: %s:%lu: "
                   1268:                                        "$DATE in future, using current date",
                   1269:                                        "dns_master_load", source, line);
                   1270:                                        dump_time = current_time;
                   1271:                                }
                   1272:                                ttl_offset = current_time - dump_time;
                   1273:                                EXPECTEOL;
                   1274:                                continue;
                   1275:                        } else if (strcasecmp(DNS_AS_STR(token),
                   1276:                                              "$GENERATE") == 0) {
                   1277:                                /*
                   1278:                                 * Lazy cleanup.
                   1279:                                 */
                   1280:                                if (range != NULL)
                   1281:                                        isc_mem_free(mctx, range);
                   1282:                                if (lhs != NULL)
                   1283:                                        isc_mem_free(mctx, lhs);
                   1284:                                if (gtype != NULL)
                   1285:                                        isc_mem_free(mctx, gtype);
                   1286:                                if (rhs != NULL)
                   1287:                                        isc_mem_free(mctx, rhs);
                   1288:                                range = lhs = gtype = rhs = NULL;
                   1289:                                /* RANGE */
                   1290:                                GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1291:                                range = isc_mem_strdup(mctx,
                   1292:                                                     DNS_AS_STR(token));
                   1293:                                if (range == NULL) {
                   1294:                                        result = ISC_R_NOMEMORY;
                   1295:                                        goto log_and_cleanup;
                   1296:                                }
                   1297:                                /* LHS */
                   1298:                                GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1299:                                lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
                   1300:                                if (lhs == NULL) {
                   1301:                                        result = ISC_R_NOMEMORY;
                   1302:                                        goto log_and_cleanup;
                   1303:                                }
                   1304:                                rdclass = 0;
                   1305:                                explicit_ttl = ISC_FALSE;
                   1306:                                /* CLASS? */
                   1307:                                GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1308:                                if (dns_rdataclass_fromtext(&rdclass,
                   1309:                                            &token.value.as_textregion)
                   1310:                                                == ISC_R_SUCCESS) {
                   1311:                                        GETTOKEN(lctx->lex, 0, &token,
                   1312:                                                 ISC_FALSE);
                   1313:                                }
                   1314:                                /* TTL? */
                   1315:                                if (dns_ttl_fromtext(&token.value.as_textregion,
                   1316:                                                     &lctx->ttl)
                   1317:                                                == ISC_R_SUCCESS) {
                   1318:                                        limit_ttl(callbacks, source, line,
                   1319:                                                  &lctx->ttl);
                   1320:                                        lctx->ttl_known = ISC_TRUE;
                   1321:                                        explicit_ttl = ISC_TRUE;
                   1322:                                        GETTOKEN(lctx->lex, 0, &token,
                   1323:                                                 ISC_FALSE);
                   1324:                                }
                   1325:                                /* CLASS? */
                   1326:                                if (rdclass == 0 &&
                   1327:                                    dns_rdataclass_fromtext(&rdclass,
                   1328:                                                    &token.value.as_textregion)
                   1329:                                                == ISC_R_SUCCESS)
                   1330:                                        GETTOKEN(lctx->lex, 0, &token,
                   1331:                                                 ISC_FALSE);
                   1332:                                /* TYPE */
                   1333:                                gtype = isc_mem_strdup(mctx,
                   1334:                                                       DNS_AS_STR(token));
                   1335:                                if (gtype == NULL) {
                   1336:                                        result = ISC_R_NOMEMORY;
                   1337:                                        goto log_and_cleanup;
                   1338:                                }
                   1339:                                /* RHS */
                   1340:                                GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
                   1341:                                         &token, ISC_FALSE);
                   1342:                                rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
                   1343:                                if (rhs == NULL) {
                   1344:                                        result = ISC_R_NOMEMORY;
                   1345:                                        goto log_and_cleanup;
                   1346:                                }
                   1347:                                if (!lctx->ttl_known &&
                   1348:                                    !lctx->default_ttl_known) {
                   1349:                                        (*callbacks->error)(callbacks,
                   1350:                                            "%s: %s:%lu: no TTL specified",
                   1351:                                            "dns_master_load", source, line);
                   1352:                                        result = DNS_R_NOTTL;
                   1353:                                        if (MANYERRS(lctx, result)) {
                   1354:                                                SETRESULT(lctx, result);
                   1355:                                                lctx->ttl = 0;
                   1356:                                        } else {
                   1357:                                                goto insist_and_cleanup;
                   1358:                                        }
                   1359:                                } else if (!explicit_ttl &&
                   1360:                                           lctx->default_ttl_known) {
                   1361:                                        lctx->ttl = lctx->default_ttl;
                   1362:                                }
                   1363:                                /*
                   1364:                                 * If the class specified does not match the
                   1365:                                 * zone's class print out a error message and
                   1366:                                 * exit.
                   1367:                                 */
                   1368:                                if (rdclass != 0 && rdclass != lctx->zclass) {
                   1369:                                        goto bad_class;
                   1370:                                }
                   1371:                                result = generate(lctx, range, lhs, gtype, rhs,
                   1372:                                                  source, line);
                   1373:                                if (MANYERRS(lctx, result)) {
                   1374:                                        SETRESULT(lctx, result);
                   1375:                                } else if (result != ISC_R_SUCCESS)
                   1376:                                        goto insist_and_cleanup;
                   1377:                                EXPECTEOL;
                   1378:                                continue;
                   1379:                        } else if (strncasecmp(DNS_AS_STR(token),
                   1380:                                               "$", 1) == 0) {
                   1381:                                (callbacks->error)(callbacks,
                   1382:                                           "%s: %s:%lu: "
                   1383:                                           "unknown $ directive '%s'",
                   1384:                                           "dns_master_load", source, line,
                   1385:                                           DNS_AS_STR(token));
                   1386:                                result = DNS_R_SYNTAX;
                   1387:                                if (MANYERRS(lctx, result)) {
                   1388:                                        SETRESULT(lctx, result);
                   1389:                                } else {
                   1390:                                        goto insist_and_cleanup;
                   1391:                                }
                   1392:                        }
                   1393:
                   1394:                        /*
                   1395:                         * Normal processing resumes.
                   1396:                         */
                   1397:                        new_in_use = find_free_name(ictx);
                   1398:                        new_name =
                   1399:                              dns_fixedname_initname(&ictx->fixed[new_in_use]);
                   1400:                        isc_buffer_init(&buffer, token.value.as_region.base,
                   1401:                                        token.value.as_region.length);
                   1402:                        isc_buffer_add(&buffer, token.value.as_region.length);
                   1403:                        isc_buffer_setactive(&buffer,
                   1404:                                             token.value.as_region.length);
                   1405:                        result = dns_name_fromtext(new_name, &buffer,
                   1406:                                          ictx->origin, 0, NULL);
                   1407:                        if (MANYERRS(lctx, result)) {
                   1408:                                SETRESULT(lctx, result);
                   1409:                                LOGIT(result);
                   1410:                                read_till_eol = ISC_TRUE;
                   1411:                                continue;
                   1412:                        } else if (result != ISC_R_SUCCESS)
                   1413:                                goto log_and_cleanup;
                   1414:
                   1415:                        /*
                   1416:                         * Finish $ORIGIN / $INCLUDE processing if required.
                   1417:                         */
                   1418:                        if (finish_origin) {
                   1419:                                if (ictx->origin_in_use != -1)
                   1420:                                        ictx->in_use[ictx->origin_in_use] =
                   1421:                                                ISC_FALSE;
                   1422:                                ictx->origin_in_use = new_in_use;
                   1423:                                ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
                   1424:                                ictx->origin = new_name;
                   1425:                                ictx->origin_changed = ISC_TRUE;
                   1426:                                finish_origin = ISC_FALSE;
                   1427:                                EXPECTEOL;
                   1428:                                continue;
                   1429:                        }
                   1430:                        if (finish_include) {
                   1431:                                finish_include = ISC_FALSE;
                   1432:                                EXPECTEOL;
                   1433:                                result = pushfile(include_file, new_name, lctx);
                   1434:                                if (MANYERRS(lctx, result)) {
                   1435:                                        SETRESULT(lctx, result);
                   1436:                                        LOGITFILE(result, include_file);
                   1437:                                        continue;
                   1438:                                } else if (result != ISC_R_SUCCESS) {
                   1439:                                        LOGITFILE(result, include_file);
                   1440:                                        goto insist_and_cleanup;
                   1441:                                }
                   1442:                                ictx = lctx->inc;
                   1443:                                ictx->origin_changed = ISC_TRUE;
                   1444:                                source = isc_lex_getsourcename(lctx->lex);
                   1445:                                line = isc_lex_getsourceline(lctx->lex);
                   1446:                                POST(line);
                   1447:                                continue;
                   1448:                        }
                   1449:
                   1450:                        /*
                   1451:                         * "$" Processing Finished
                   1452:                         */
                   1453:
                   1454:                        /*
                   1455:                         * If we are processing glue and the new name does
                   1456:                         * not match the current glue name, commit the glue
                   1457:                         * and pop stacks leaving us in 'normal' processing
                   1458:                         * state.  Linked lists are undone by commit().
                   1459:                         */
                   1460:                        if (ictx->glue != NULL &&
                   1461:                            dns_name_compare(ictx->glue, new_name) != 0) {
                   1462:                                result = commit(callbacks, lctx, &glue_list,
                   1463:                                                ictx->glue, source,
                   1464:                                                ictx->glue_line);
                   1465:                                if (MANYERRS(lctx, result)) {
                   1466:                                        SETRESULT(lctx, result);
                   1467:                                } else if (result != ISC_R_SUCCESS)
                   1468:                                        goto insist_and_cleanup;
                   1469:                                if (ictx->glue_in_use != -1)
                   1470:                                        ictx->in_use[ictx->glue_in_use] =
                   1471:                                                ISC_FALSE;
                   1472:                                ictx->glue_in_use = -1;
                   1473:                                ictx->glue = NULL;
                   1474:                                rdcount = rdcount_save;
                   1475:                                rdlcount = rdlcount_save;
                   1476:                                target = target_save;
                   1477:                        }
                   1478:
                   1479:                        /*
                   1480:                         * If we are in 'normal' processing state and the new
                   1481:                         * name does not match the current name, see if the
                   1482:                         * new name is for glue and treat it as such,
                   1483:                         * otherwise we have a new name so commit what we
                   1484:                         * have.
                   1485:                         */
                   1486:                        if ((ictx->glue == NULL) && (ictx->current == NULL ||
                   1487:                            dns_name_compare(ictx->current, new_name) != 0)) {
                   1488:                                if (current_has_delegation &&
                   1489:                                        is_glue(&current_list, new_name)) {
                   1490:                                        rdcount_save = rdcount;
                   1491:                                        rdlcount_save = rdlcount;
                   1492:                                        target_save = target;
                   1493:                                        ictx->glue = new_name;
                   1494:                                        ictx->glue_in_use = new_in_use;
                   1495:                                        ictx->in_use[ictx->glue_in_use] =
                   1496:                                                ISC_TRUE;
                   1497:                                } else {
                   1498:                                        result = commit(callbacks, lctx,
                   1499:                                                        &current_list,
                   1500:                                                        ictx->current,
                   1501:                                                        source,
                   1502:                                                        ictx->current_line);
                   1503:                                        if (MANYERRS(lctx, result)) {
                   1504:                                                SETRESULT(lctx, result);
                   1505:                                        } else if (result != ISC_R_SUCCESS)
                   1506:                                                goto insist_and_cleanup;
                   1507:                                        rdcount = 0;
                   1508:                                        rdlcount = 0;
                   1509:                                        if (ictx->current_in_use != -1)
                   1510:                                            ictx->in_use[ictx->current_in_use] =
                   1511:                                                ISC_FALSE;
                   1512:                                        ictx->current_in_use = new_in_use;
                   1513:                                        ictx->in_use[ictx->current_in_use] =
                   1514:                                                ISC_TRUE;
                   1515:                                        ictx->current = new_name;
                   1516:                                        current_has_delegation = ISC_FALSE;
                   1517:                                        isc_buffer_init(&target, target_mem,
                   1518:                                                        target_size);
                   1519:                                }
                   1520:                                /*
                   1521:                                 * Check for internal wildcards.
                   1522:                                 */
                   1523:                                if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
                   1524:                                                 != 0)
                   1525:                                        check_wildcard(ictx, source, line,
                   1526:                                                       callbacks);
                   1527:
                   1528:                        }
                   1529:                        if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                   1530:                            (lctx->options & DNS_MASTER_SLAVE) == 0 &&
                   1531:                            (lctx->options & DNS_MASTER_KEY) == 0 &&
                   1532:                            !dns_name_issubdomain(new_name, lctx->top))
                   1533:                        {
                   1534:                                char namebuf[DNS_NAME_FORMATSIZE];
                   1535:                                dns_name_format(new_name, namebuf,
                   1536:                                                sizeof(namebuf));
                   1537:                                /*
                   1538:                                 * Ignore out-of-zone data.
                   1539:                                 */
                   1540:                                (*callbacks->warn)(callbacks,
                   1541:                                       "%s:%lu: "
                   1542:                                       "ignoring out-of-zone data (%s)",
                   1543:                                       source, line, namebuf);
                   1544:                                ictx->drop = ISC_TRUE;
                   1545:                        } else
                   1546:                                ictx->drop = ISC_FALSE;
                   1547:                } else {
                   1548:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                   1549:                                         "%s:%lu: isc_lex_gettoken() returned "
                   1550:                                         "unexpected token type (%d)",
                   1551:                                         source, line, token.type);
                   1552:                        result = ISC_R_UNEXPECTED;
                   1553:                        if (MANYERRS(lctx, result)) {
                   1554:                                SETRESULT(lctx, result);
                   1555:                                LOGIT(result);
                   1556:                                continue;
                   1557:                        } else {
                   1558:                                goto insist_and_cleanup;
                   1559:                        }
                   1560:                }
                   1561:
                   1562:                /*
                   1563:                 * Find TTL, class and type.  Both TTL and class are optional
                   1564:                 * and may occur in any order if they exist. TTL and class
                   1565:                 * come before type which must exist.
                   1566:                 *
                   1567:                 * [<TTL>] [<class>] <type> <RDATA>
                   1568:                 * [<class>] [<TTL>] <type> <RDATA>
                   1569:                 */
                   1570:
                   1571:                type = 0;
                   1572:                rdclass = 0;
                   1573:
                   1574:                GETTOKEN(lctx->lex, 0, &token, initialws);
                   1575:
                   1576:                if (initialws) {
                   1577:                        if (token.type == isc_tokentype_eol) {
                   1578:                                read_till_eol = ISC_FALSE;
                   1579:                                continue;               /* blank line */
                   1580:                        }
                   1581:
                   1582:                        if (token.type == isc_tokentype_eof) {
                   1583:                                WARNUNEXPECTEDEOF(lctx->lex);
                   1584:                                read_till_eol = ISC_FALSE;
                   1585:                                isc_lex_ungettoken(lctx->lex, &token);
                   1586:                                continue;
                   1587:                        }
                   1588:
                   1589:                        if (ictx->current == NULL) {
                   1590:                                (*callbacks->error)(callbacks,
                   1591:                                        "%s:%lu: no current owner name",
                   1592:                                        source, line);
                   1593:                                result = DNS_R_NOOWNER;
                   1594:                                if (MANYERRS(lctx, result)) {
                   1595:                                        SETRESULT(lctx, result);
                   1596:                                        read_till_eol = ISC_TRUE;
                   1597:                                        continue;
                   1598:                                } else {
                   1599:                                        goto insist_and_cleanup;
                   1600:                                }
                   1601:                        }
                   1602:
                   1603:                        if (ictx->origin_changed) {
                   1604:                                char cbuf[DNS_NAME_FORMATSIZE];
                   1605:                                char obuf[DNS_NAME_FORMATSIZE];
                   1606:                                dns_name_format(ictx->current, cbuf,
                   1607:                                                sizeof(cbuf));
                   1608:                                dns_name_format(ictx->origin, obuf,
                   1609:                                                sizeof(obuf));
                   1610:                                (*callbacks->warn)(callbacks,
                   1611:                                        "%s:%lu: record with inherited "
                   1612:                                        "owner (%s) immediately after "
                   1613:                                        "$ORIGIN (%s)", source, line,
                   1614:                                        cbuf, obuf);
                   1615:                        }
                   1616:                }
                   1617:
                   1618:                ictx->origin_changed = ISC_FALSE;
                   1619:
                   1620:                if (dns_rdataclass_fromtext(&rdclass,
                   1621:                                            &token.value.as_textregion)
                   1622:                                == ISC_R_SUCCESS)
                   1623:                        GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1624:
                   1625:                explicit_ttl = ISC_FALSE;
                   1626:                result = dns_ttl_fromtext(&token.value.as_textregion,
                   1627:                                          &lctx->ttl);
                   1628:                if (result == ISC_R_SUCCESS) {
                   1629:                        limit_ttl(callbacks, source, line, &lctx->ttl);
                   1630:                        explicit_ttl = ISC_TRUE;
                   1631:                        lctx->ttl_known = ISC_TRUE;
                   1632:                        GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1633:                }
                   1634:
                   1635:                if (token.type != isc_tokentype_string) {
                   1636:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                   1637:                        "isc_lex_gettoken() returned unexpected token type");
                   1638:                        result = ISC_R_UNEXPECTED;
                   1639:                        if (MANYERRS(lctx, result)) {
                   1640:                                SETRESULT(lctx, result);
                   1641:                                read_till_eol = ISC_TRUE;
                   1642:                                continue;
                   1643:                        } else {
                   1644:                                goto insist_and_cleanup;
                   1645:                        }
                   1646:                }
                   1647:
                   1648:                if (rdclass == 0 &&
                   1649:                    dns_rdataclass_fromtext(&rdclass,
                   1650:                                            &token.value.as_textregion)
                   1651:                                == ISC_R_SUCCESS)
                   1652:                        GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1653:
                   1654:                if (token.type != isc_tokentype_string) {
                   1655:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                   1656:                        "isc_lex_gettoken() returned unexpected token type");
                   1657:                        result = ISC_R_UNEXPECTED;
                   1658:                        if (MANYERRS(lctx, result)) {
                   1659:                                SETRESULT(lctx, result);
                   1660:                                read_till_eol = ISC_TRUE;
                   1661:                                continue;
                   1662:                        } else {
                   1663:                                goto insist_and_cleanup;
                   1664:                        }
                   1665:                }
                   1666:
                   1667:                result = dns_rdatatype_fromtext(&type,
                   1668:                                                &token.value.as_textregion);
                   1669:                if (result != ISC_R_SUCCESS) {
                   1670:                        (*callbacks->warn)(callbacks,
                   1671:                                   "%s:%lu: unknown RR type '%.*s'",
                   1672:                                   source, line,
                   1673:                                   token.value.as_textregion.length,
                   1674:                                   token.value.as_textregion.base);
                   1675:                        if (MANYERRS(lctx, result)) {
                   1676:                                SETRESULT(lctx, result);
                   1677:                                read_till_eol = ISC_TRUE;
                   1678:                                continue;
                   1679:                        } else if (result != ISC_R_SUCCESS)
                   1680:                                goto insist_and_cleanup;
                   1681:                }
                   1682:
                   1683:                /*
                   1684:                 * If the class specified does not match the zone's class
                   1685:                 * print out a error message and exit.
                   1686:                 */
                   1687:                if (rdclass != 0 && rdclass != lctx->zclass) {
                   1688:   bad_class:
                   1689:
                   1690:                        dns_rdataclass_format(rdclass, classname1,
                   1691:                                              sizeof(classname1));
                   1692:                        dns_rdataclass_format(lctx->zclass, classname2,
                   1693:                                              sizeof(classname2));
                   1694:                        (*callbacks->error)(callbacks,
                   1695:                                            "%s:%lu: class '%s' != "
                   1696:                                            "zone class '%s'",
                   1697:                                            source, line,
                   1698:                                            classname1, classname2);
                   1699:                        result = DNS_R_BADCLASS;
                   1700:                        if (MANYERRS(lctx, result)) {
                   1701:                                SETRESULT(lctx, result);
                   1702:                                read_till_eol = ISC_TRUE;
                   1703:                                continue;
                   1704:                        } else {
                   1705:                                goto insist_and_cleanup;
                   1706:                        }
                   1707:                }
                   1708:
                   1709:                if (type == dns_rdatatype_ns && ictx->glue == NULL)
                   1710:                        current_has_delegation = ISC_TRUE;
                   1711:
                   1712:                /*
                   1713:                 * RFC1123: MD and MF are not allowed to be loaded from
                   1714:                 * master files.
                   1715:                 */
                   1716:                if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                   1717:                    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
                   1718:                    (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
                   1719:                        char typename[DNS_RDATATYPE_FORMATSIZE];
                   1720:
                   1721:                        result = DNS_R_OBSOLETE;
                   1722:
                   1723:                        dns_rdatatype_format(type, typename, sizeof(typename));
                   1724:                        (*callbacks->error)(callbacks,
                   1725:                                            "%s:%lu: %s '%s': %s",
                   1726:                                            source, line,
                   1727:                                            "type", typename,
                   1728:                                            dns_result_totext(result));
                   1729:                        if (MANYERRS(lctx, result)) {
                   1730:                                SETRESULT(lctx, result);
                   1731:                        } else
                   1732:                                goto insist_and_cleanup;
                   1733:                }
                   1734:
                   1735:                /*
                   1736:                 * RFC2930: TKEY and TSIG are not allowed to be loaded
                   1737:                 * from master files.
                   1738:                 */
                   1739:                if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                   1740:                    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
                   1741:                    dns_rdatatype_ismeta(type))
                   1742:                {
                   1743:                        char typename[DNS_RDATATYPE_FORMATSIZE];
                   1744:
                   1745:                        result = DNS_R_METATYPE;
                   1746:
                   1747:                        dns_rdatatype_format(type, typename, sizeof(typename));
                   1748:                        (*callbacks->error)(callbacks,
                   1749:                                            "%s:%lu: %s '%s': %s",
                   1750:                                            source, line,
                   1751:                                            "type", typename,
                   1752:                                            dns_result_totext(result));
                   1753:                        if (MANYERRS(lctx, result)) {
                   1754:                                SETRESULT(lctx, result);
                   1755:                        } else
                   1756:                                goto insist_and_cleanup;
                   1757:                }
                   1758:
                   1759:                /*
                   1760:                 * Find a rdata structure.
                   1761:                 */
                   1762:                if (rdcount == rdata_size) {
                   1763:                        new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
                   1764:                                               rdata_size, &current_list,
                   1765:                                               &glue_list, mctx);
                   1766:                        if (new_rdata == NULL) {
                   1767:                                result = ISC_R_NOMEMORY;
                   1768:                                goto log_and_cleanup;
                   1769:                        }
                   1770:                        rdata_size += RDSZ;
                   1771:                        rdata = new_rdata;
                   1772:                }
                   1773:
                   1774:                /*
                   1775:                 * Peek at the NS record.
                   1776:                 */
                   1777:                if (type == dns_rdatatype_ns &&
                   1778:                    lctx->zclass == dns_rdataclass_in &&
                   1779:                    (lctx->options & DNS_MASTER_CHECKNS) != 0) {
                   1780:
                   1781:                        GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
                   1782:                        result = check_ns(lctx, &token, source, line);
                   1783:                        isc_lex_ungettoken(lctx->lex, &token);
                   1784:                        if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
                   1785:                                if (MANYERRS(lctx, result)) {
                   1786:                                        SETRESULT(lctx, result);
                   1787:                                } else if (result != ISC_R_SUCCESS)
                   1788:                                        goto insist_and_cleanup;
                   1789:                        }
                   1790:                }
                   1791:
                   1792:                /*
                   1793:                 * Check owner name.
                   1794:                 */
                   1795:                options &= ~DNS_RDATA_CHECKREVERSE;
                   1796:                if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
                   1797:                        isc_boolean_t ok;
                   1798:                        dns_name_t *name;
                   1799:
                   1800:                        name = (ictx->glue != NULL) ? ictx->glue :
                   1801:                                                      ictx->current;
                   1802:                        ok = dns_rdata_checkowner(name, lctx->zclass, type,
                   1803:                                                  ISC_TRUE);
                   1804:                        if (!ok) {
                   1805:                                char namebuf[DNS_NAME_FORMATSIZE];
                   1806:                                const char *desc;
                   1807:                                dns_name_format(name, namebuf, sizeof(namebuf));
                   1808:                                result = DNS_R_BADOWNERNAME;
                   1809:                                desc = dns_result_totext(result);
                   1810:                                if (CHECKNAMESFAIL(lctx->options) ||
                   1811:                                    type == dns_rdatatype_nsec3) {
                   1812:                                        (*callbacks->error)(callbacks,
                   1813:                                                            "%s:%lu: %s: %s",
                   1814:                                                            source, line,
                   1815:                                                            namebuf, desc);
                   1816:                                        if (MANYERRS(lctx, result)) {
                   1817:                                                SETRESULT(lctx, result);
                   1818:                                        } else {
                   1819:                                                goto cleanup;
                   1820:                                        }
                   1821:                                } else {
                   1822:                                        (*callbacks->warn)(callbacks,
                   1823:                                                           "%s:%lu: %s: %s",
                   1824:                                                           source, line,
                   1825:                                                           namebuf, desc);
                   1826:                                }
                   1827:                        }
                   1828:                        if (type == dns_rdatatype_ptr &&
                   1829:                            !dns_name_isdnssd(name) &&
                   1830:                            (dns_name_issubdomain(name, &in_addr_arpa) ||
                   1831:                             dns_name_issubdomain(name, &ip6_arpa) ||
                   1832:                             dns_name_issubdomain(name, &ip6_int)))
                   1833:                                options |= DNS_RDATA_CHECKREVERSE;
                   1834:                }
                   1835:
                   1836:                /*
                   1837:                 * Read rdata contents.
                   1838:                 */
                   1839:                dns_rdata_init(&rdata[rdcount]);
                   1840:                target_ft = target;
                   1841:                result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
                   1842:                                            type, lctx->lex, ictx->origin,
                   1843:                                            options, lctx->mctx, &target,
                   1844:                                            callbacks);
                   1845:                if (MANYERRS(lctx, result)) {
                   1846:                        SETRESULT(lctx, result);
                   1847:                        continue;
                   1848:                } else if (result != ISC_R_SUCCESS)
                   1849:                        goto insist_and_cleanup;
                   1850:
                   1851:                if (ictx->drop) {
                   1852:                        target = target_ft;
                   1853:                        continue;
                   1854:                }
                   1855:
                   1856:                if (type == dns_rdatatype_soa &&
                   1857:                    (lctx->options & DNS_MASTER_ZONE) != 0 &&
                   1858:                    dns_name_compare(ictx->current, lctx->top) != 0) {
                   1859:                        char namebuf[DNS_NAME_FORMATSIZE];
                   1860:                        dns_name_format(ictx->current, namebuf,
                   1861:                                        sizeof(namebuf));
                   1862:                        (*callbacks->error)(callbacks, "%s:%lu: SOA "
                   1863:                                            "record not at top of zone (%s)",
                   1864:                                            source, line, namebuf);
                   1865:                        result = DNS_R_NOTZONETOP;
                   1866:                        if (MANYERRS(lctx, result)) {
                   1867:                                SETRESULT(lctx, result);
                   1868:                                read_till_eol = ISC_TRUE;
                   1869:                                target = target_ft;
                   1870:                                continue;
                   1871:                        } else {
                   1872:                                goto insist_and_cleanup;
                   1873:                        }
                   1874:                }
                   1875:
                   1876:                if (type == dns_rdatatype_rrsig ||
                   1877:                    type == dns_rdatatype_sig)
                   1878:                        covers = dns_rdata_covers(&rdata[rdcount]);
                   1879:                else
                   1880:                        covers = 0;
                   1881:
                   1882:                if (!lctx->ttl_known && !lctx->default_ttl_known) {
                   1883:                        if (type == dns_rdatatype_soa) {
                   1884:                                (*callbacks->warn)(callbacks,
                   1885:                                                   "%s:%lu: no TTL specified; "
                   1886:                                                   "using SOA MINTTL instead",
                   1887:                                                   source, line);
                   1888:                                lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
                   1889:                                limit_ttl(callbacks, source, line, &lctx->ttl);
                   1890:                                lctx->default_ttl = lctx->ttl;
                   1891:                                lctx->default_ttl_known = ISC_TRUE;
                   1892:                        } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
                   1893:                                /*
                   1894:                                 * Zero TTL's are fine for hints.
                   1895:                                 */
                   1896:                                lctx->ttl = 0;
                   1897:                                lctx->default_ttl = lctx->ttl;
                   1898:                                lctx->default_ttl_known = ISC_TRUE;
                   1899:                        } else {
                   1900:                                (*callbacks->warn)(callbacks,
                   1901:                                                   "%s:%lu: no TTL specified; "
                   1902:                                                   "zone rejected",
                   1903:                                                   source, line);
                   1904:                                result = DNS_R_NOTTL;
                   1905:                                if (MANYERRS(lctx, result)) {
                   1906:                                        SETRESULT(lctx, result);
                   1907:                                        lctx->ttl = 0;
                   1908:                                } else {
                   1909:                                        goto insist_and_cleanup;
                   1910:                                }
                   1911:                        }
                   1912:                } else if (!explicit_ttl && lctx->default_ttl_known) {
                   1913:                        lctx->ttl = lctx->default_ttl;
                   1914:                } else if (!explicit_ttl && lctx->warn_1035) {
                   1915:                        (*callbacks->warn)(callbacks,
                   1916:                                           "%s:%lu: "
                   1917:                                           "using RFC1035 TTL semantics",
                   1918:                                           source, line);
                   1919:                        lctx->warn_1035 = ISC_FALSE;
                   1920:                }
                   1921:
                   1922:                if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
                   1923:                        dns_rdata_rrsig_t sig;
                   1924:                        result = dns_rdata_tostruct(&rdata[rdcount], &sig,
                   1925:                                                    NULL);
                   1926:                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
                   1927:                        if (isc_serial_lt(sig.timeexpire, lctx->now)) {
                   1928:                                (*callbacks->warn)(callbacks,
                   1929:                                                   "%s:%lu: "
                   1930:                                                   "signature has expired",
                   1931:                                                   source, line);
                   1932:                                lctx->warn_sigexpired = ISC_FALSE;
                   1933:                        }
                   1934:                }
                   1935:
                   1936:                if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
                   1937:                    lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
                   1938:                    (lctx->options & DNS_MASTER_SLAVE) == 0) {
                   1939:                        (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
                   1940:                                           " zone detected", source, line);
                   1941:                        lctx->warn_tcr = ISC_FALSE;
                   1942:                }
                   1943:
                   1944:                if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
                   1945:                        /*
                   1946:                         * Adjust the TTL for $DATE. If the RR has
                   1947:                         * already expired, set its TTL to 0. This
                   1948:                         * should be okay even if the TTL stretching
                   1949:                         * feature is not in effect, because it will
                   1950:                         * just be quickly expired by the cache, and the
                   1951:                         * way this was written before the patch it
                   1952:                         * could potentially add 0 TTLs anyway.
                   1953:                         */
                   1954:                        if (lctx->ttl < ttl_offset)
                   1955:                                lctx->ttl = 0;
                   1956:                        else
                   1957:                                lctx->ttl -= ttl_offset;
                   1958:                }
                   1959:
                   1960:                /*
                   1961:                 * Find type in rdatalist.
                   1962:                 * If it does not exist create new one and prepend to list
                   1963:                 * as this will minimise list traversal.
                   1964:                 */
                   1965:                if (ictx->glue != NULL)
                   1966:                        this = ISC_LIST_HEAD(glue_list);
                   1967:                else
                   1968:                        this = ISC_LIST_HEAD(current_list);
                   1969:
                   1970:                while (this != NULL) {
                   1971:                        if (this->type == type && this->covers == covers)
                   1972:                                break;
                   1973:                        this = ISC_LIST_NEXT(this, link);
                   1974:                }
                   1975:
                   1976:                if (this == NULL) {
                   1977:                        if (rdlcount == rdatalist_size) {
                   1978:                                new_rdatalist =
                   1979:                                        grow_rdatalist(rdatalist_size + RDLSZ,
                   1980:                                                       rdatalist,
                   1981:                                                       rdatalist_size,
                   1982:                                                       &current_list,
                   1983:                                                       &glue_list,
                   1984:                                                       mctx);
                   1985:                                if (new_rdatalist == NULL) {
                   1986:                                        result = ISC_R_NOMEMORY;
                   1987:                                        goto log_and_cleanup;
                   1988:                                }
                   1989:                                rdatalist = new_rdatalist;
                   1990:                                rdatalist_size += RDLSZ;
                   1991:                        }
                   1992:                        this = &rdatalist[rdlcount++];
                   1993:                        dns_rdatalist_init(this);
                   1994:                        this->type = type;
                   1995:                        this->covers = covers;
                   1996:                        this->rdclass = lctx->zclass;
                   1997:                        this->ttl = lctx->ttl;
                   1998:                        if (ictx->glue != NULL)
                   1999:                                ISC_LIST_INITANDPREPEND(glue_list, this, link);
                   2000:                        else
                   2001:                                ISC_LIST_INITANDPREPEND(current_list, this,
                   2002:                                                        link);
                   2003:                } else if (this->ttl != lctx->ttl) {
                   2004:                        (*callbacks->warn)(callbacks,
                   2005:                                           "%s:%lu: "
                   2006:                                           "TTL set to prior TTL (%lu)",
                   2007:                                           source, line, this->ttl);
                   2008:                        lctx->ttl = this->ttl;
                   2009:                }
                   2010:
                   2011:                if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
                   2012:                    lctx->ttl > lctx->maxttl)
                   2013:                {
                   2014:                        (callbacks->error)(callbacks,
                   2015:                                   "dns_master_load: %s:%lu: "
                   2016:                                   "TTL %d exceeds configured max-zone-ttl %d",
                   2017:                                   source, line, lctx->ttl, lctx->maxttl);
                   2018:                        result = ISC_R_RANGE;
                   2019:                        goto log_and_cleanup;
                   2020:                }
                   2021:
                   2022:                ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
                   2023:                if (ictx->glue != NULL)
                   2024:                        ictx->glue_line = line;
                   2025:                else
                   2026:                        ictx->current_line = line;
                   2027:                rdcount++;
                   2028:
                   2029:                /*
                   2030:                 * We must have at least 64k as rdlen is 16 bits.
                   2031:                 * If we don't commit everything we have so far.
                   2032:                 */
                   2033:                if ((target.length - target.used) < MINTSIZ)
                   2034:                        COMMITALL;
                   2035:  next_line:
                   2036:                ;
                   2037:        } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
                   2038:
                   2039:        /*
                   2040:         * Commit what has not yet been committed.
                   2041:         */
                   2042:        result = commit(callbacks, lctx, &current_list, ictx->current,
                   2043:                        source, ictx->current_line);
                   2044:        if (MANYERRS(lctx, result)) {
                   2045:                SETRESULT(lctx, result);
                   2046:        } else if (result != ISC_R_SUCCESS)
                   2047:                goto insist_and_cleanup;
                   2048:        result = commit(callbacks, lctx, &glue_list, ictx->glue,
                   2049:                        source, ictx->glue_line);
                   2050:        if (MANYERRS(lctx, result)) {
                   2051:                SETRESULT(lctx, result);
                   2052:        } else if (result != ISC_R_SUCCESS)
                   2053:                goto insist_and_cleanup;
                   2054:
                   2055:        if (!done) {
                   2056:                INSIST(lctx->done != NULL && lctx->task != NULL);
                   2057:                result = DNS_R_CONTINUE;
                   2058:        } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
                   2059:                result = lctx->result;
                   2060:        } else if (result == ISC_R_SUCCESS && lctx->seen_include)
                   2061:                result = DNS_R_SEENINCLUDE;
                   2062:        goto cleanup;
                   2063:
                   2064:  log_and_cleanup:
                   2065:        LOGIT(result);
                   2066:
                   2067:  insist_and_cleanup:
                   2068:        INSIST(result != ISC_R_SUCCESS);
                   2069:
                   2070:  cleanup:
                   2071:        while ((this = ISC_LIST_HEAD(current_list)) != NULL)
                   2072:                ISC_LIST_UNLINK(current_list, this, link);
                   2073:        while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
                   2074:                ISC_LIST_UNLINK(glue_list, this, link);
                   2075:        if (rdatalist != NULL)
                   2076:                isc_mem_put(mctx, rdatalist,
                   2077:                            rdatalist_size * sizeof(*rdatalist));
                   2078:        if (rdata != NULL)
                   2079:                isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
                   2080:        if (target_mem != NULL)
                   2081:                isc_mem_put(mctx, target_mem, target_size);
                   2082:        if (include_file != NULL)
                   2083:                isc_mem_free(mctx, include_file);
                   2084:        if (range != NULL)
                   2085:                isc_mem_free(mctx, range);
                   2086:        if (lhs != NULL)
                   2087:                isc_mem_free(mctx, lhs);
                   2088:        if (gtype != NULL)
                   2089:                isc_mem_free(mctx, gtype);
                   2090:        if (rhs != NULL)
                   2091:                isc_mem_free(mctx, rhs);
                   2092:        return (result);
                   2093: }
                   2094:
                   2095: static isc_result_t
                   2096: pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
                   2097:        isc_result_t result;
                   2098:        dns_incctx_t *ictx;
                   2099:        dns_incctx_t *newctx = NULL;
                   2100:        isc_region_t r;
                   2101:
                   2102:        REQUIRE(master_file != NULL);
                   2103:        REQUIRE(DNS_LCTX_VALID(lctx));
                   2104:
                   2105:        ictx = lctx->inc;
                   2106:        lctx->seen_include = ISC_TRUE;
                   2107:
                   2108:        result = incctx_create(lctx->mctx, origin, &newctx);
                   2109:        if (result != ISC_R_SUCCESS)
                   2110:                return (result);
                   2111:
                   2112:        /*
                   2113:         * Push origin_changed.
                   2114:         */
                   2115:        newctx->origin_changed = ictx->origin_changed;
                   2116:
                   2117:        /* Set current domain. */
                   2118:        if (ictx->glue != NULL || ictx->current != NULL) {
                   2119:                newctx->current_in_use = find_free_name(newctx);
                   2120:                newctx->current =
                   2121:                        dns_fixedname_name(&newctx->fixed[newctx->current_in_use]);
                   2122:                newctx->in_use[newctx->current_in_use] = ISC_TRUE;
                   2123:                dns_name_toregion((ictx->glue != NULL) ?
                   2124:                                   ictx->glue : ictx->current, &r);
                   2125:                dns_name_fromregion(newctx->current, &r);
                   2126:                newctx->drop = ictx->drop;
                   2127:        }
                   2128:
                   2129:        result = (lctx->openfile)(lctx, master_file);
                   2130:        if (result != ISC_R_SUCCESS)
                   2131:                goto cleanup;
                   2132:        newctx->parent = ictx;
                   2133:        lctx->inc = newctx;
                   2134:
                   2135:        if (lctx->include_cb != NULL)
                   2136:                lctx->include_cb(master_file, lctx->include_arg);
                   2137:        return (ISC_R_SUCCESS);
                   2138:
                   2139:  cleanup:
                   2140:        incctx_destroy(lctx->mctx, newctx);
                   2141:        return (result);
                   2142: }
                   2143:
                   2144: /*
                   2145:  * Fill/check exists buffer with 'len' bytes.  Track remaining bytes to be
                   2146:  * read when incrementally filling the buffer.
                   2147:  */
                   2148: static inline isc_result_t
                   2149: read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
                   2150:               size_t len, FILE *f, isc_uint32_t *totallen)
                   2151: {
                   2152:        isc_result_t result;
                   2153:
                   2154:        REQUIRE(totallen != NULL);
                   2155:
                   2156:        if (do_read) {
                   2157:                INSIST(isc_buffer_availablelength(buffer) >= len);
                   2158:                result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
                   2159:                                        f, NULL);
                   2160:                if (result != ISC_R_SUCCESS)
                   2161:                        return (result);
                   2162:                isc_buffer_add(buffer, (unsigned int)len);
                   2163:                if (*totallen < len)
                   2164:                        return (ISC_R_RANGE);
                   2165:                *totallen -= (isc_uint32_t)len;
                   2166:        } else if (isc_buffer_remaininglength(buffer) < len)
                   2167:                return (ISC_R_RANGE);
                   2168:
                   2169:        return (ISC_R_SUCCESS);
                   2170: }
                   2171:
                   2172: static isc_result_t
                   2173: load_header(dns_loadctx_t *lctx) {
                   2174:        isc_result_t result = ISC_R_SUCCESS;
                   2175:        dns_masterrawheader_t header;
                   2176:        dns_rdatacallbacks_t *callbacks;
                   2177:        size_t commonlen = sizeof(header.format) + sizeof(header.version);
                   2178:        size_t remainder;
                   2179:        unsigned char data[sizeof(header)];
                   2180:        isc_buffer_t target;
                   2181:
                   2182:        REQUIRE(DNS_LCTX_VALID(lctx));
                   2183:
                   2184:        if (lctx->format != dns_masterformat_raw &&
                   2185:            lctx->format != dns_masterformat_map)
                   2186:                return (ISC_R_NOTIMPLEMENTED);
                   2187:
                   2188:        callbacks = lctx->callbacks;
                   2189:        dns_master_initrawheader(&header);
                   2190:
                   2191:        INSIST(commonlen <= sizeof(header));
                   2192:        isc_buffer_init(&target, data, sizeof(data));
                   2193:
                   2194:        result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
                   2195:        if (result != ISC_R_SUCCESS) {
                   2196:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                   2197:                                 "isc_stdio_read failed: %s",
                   2198:                                 isc_result_totext(result));
                   2199:                return (result);
                   2200:        }
                   2201:
                   2202:        isc_buffer_add(&target, (unsigned int)commonlen);
                   2203:        header.format = isc_buffer_getuint32(&target);
                   2204:        if (header.format != lctx->format) {
                   2205:                (*callbacks->error)(callbacks, "dns_master_load: "
                   2206:                                    "file format mismatch (not %s)",
                   2207:                                    lctx->format == dns_masterformat_map
                   2208:                                            ? "map"
                   2209:                                            : "raw");
                   2210:                return (ISC_R_NOTIMPLEMENTED);
                   2211:        }
                   2212:
                   2213:        header.version = isc_buffer_getuint32(&target);
                   2214:
                   2215:        switch (header.version) {
                   2216:        case 0:
                   2217:                remainder = sizeof(header.dumptime);
                   2218:                break;
                   2219:        case DNS_RAWFORMAT_VERSION:
                   2220:                remainder = sizeof(header) - commonlen;
                   2221:                break;
                   2222:        default:
                   2223:                (*callbacks->error)(callbacks,
                   2224:                                    "dns_master_load: "
                   2225:                                    "unsupported file format version");
                   2226:                return (ISC_R_NOTIMPLEMENTED);
                   2227:        }
                   2228:
                   2229:        result = isc_stdio_read(data + commonlen, 1, remainder, lctx->f, NULL);
                   2230:        if (result != ISC_R_SUCCESS) {
                   2231:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                   2232:                                 "isc_stdio_read failed: %s",
                   2233:                                 isc_result_totext(result));
                   2234:                return (result);
                   2235:        }
                   2236:
                   2237:        isc_buffer_add(&target, (unsigned int)remainder);
                   2238:        header.dumptime = isc_buffer_getuint32(&target);
                   2239:        if (header.version == DNS_RAWFORMAT_VERSION) {
                   2240:                header.flags = isc_buffer_getuint32(&target);
                   2241:                header.sourceserial = isc_buffer_getuint32(&target);
                   2242:                header.lastxfrin = isc_buffer_getuint32(&target);
                   2243:        }
                   2244:
                   2245:        lctx->first = ISC_FALSE;
                   2246:        lctx->header = header;
                   2247:
                   2248:        return (ISC_R_SUCCESS);
                   2249: }
                   2250:
                   2251: static isc_result_t
                   2252: openfile_map(dns_loadctx_t *lctx, const char *master_file) {
                   2253:        isc_result_t result;
                   2254:
                   2255:        result = isc_stdio_open(master_file, "rb", &lctx->f);
                   2256:        if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
                   2257:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                   2258:                                 "isc_stdio_open() failed: %s",
                   2259:                                 isc_result_totext(result));
                   2260:        }
                   2261:
                   2262:        return (result);
                   2263: }
                   2264:
                   2265: /*
                   2266:  * Load a map format file, using mmap() to access RBT trees directly
                   2267:  */
                   2268: static isc_result_t
                   2269: load_map(dns_loadctx_t *lctx) {
                   2270:        isc_result_t result = ISC_R_SUCCESS;
                   2271:        dns_rdatacallbacks_t *callbacks;
                   2272:
                   2273:        REQUIRE(DNS_LCTX_VALID(lctx));
                   2274:
                   2275:        callbacks = lctx->callbacks;
                   2276:
                   2277:        if (lctx->first) {
                   2278:                result = load_header(lctx);
                   2279:                if (result != ISC_R_SUCCESS)
                   2280:                        return (result);
                   2281:
                   2282:                result = (*callbacks->deserialize)
                   2283:                          (callbacks->deserialize_private,
                   2284:                           lctx->f, sizeof(dns_masterrawheader_t));
                   2285:        }
                   2286:
                   2287:        return (result);
                   2288: }
                   2289:
                   2290: static isc_result_t
                   2291: openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
                   2292:        isc_result_t result;
                   2293:
                   2294:        result = isc_stdio_open(master_file, "rb", &lctx->f);
                   2295:        if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
                   2296:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                   2297:                                 "isc_stdio_open() failed: %s",
                   2298:                                 isc_result_totext(result));
                   2299:        }
                   2300:
                   2301:        return (result);
                   2302: }
                   2303:
                   2304: static isc_result_t
                   2305: load_raw(dns_loadctx_t *lctx) {
                   2306:        isc_result_t result = ISC_R_SUCCESS;
                   2307:        isc_boolean_t done = ISC_FALSE;
                   2308:        unsigned int loop_cnt = 0;
                   2309:        dns_rdatacallbacks_t *callbacks;
                   2310:        unsigned char namebuf[DNS_NAME_MAXWIRE];
                   2311:        dns_fixedname_t fixed;
                   2312:        dns_name_t *name;
                   2313:        rdatalist_head_t head, dummy;
                   2314:        dns_rdatalist_t rdatalist;
                   2315:        isc_mem_t *mctx = lctx->mctx;
                   2316:        dns_rdata_t *rdata = NULL;
                   2317:        unsigned int rdata_size = 0;
                   2318:        int target_size = TSIZ;
                   2319:        isc_buffer_t target, buf;
                   2320:        unsigned char *target_mem = NULL;
                   2321:        dns_decompress_t dctx;
                   2322:
                   2323:        callbacks = lctx->callbacks;
                   2324:        dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
                   2325:
                   2326:        if (lctx->first) {
                   2327:                result = load_header(lctx);
                   2328:                if (result != ISC_R_SUCCESS)
                   2329:                        return (result);
                   2330:        }
                   2331:
                   2332:        ISC_LIST_INIT(head);
                   2333:        ISC_LIST_INIT(dummy);
                   2334:
                   2335:        /*
                   2336:         * Allocate target_size of buffer space.  This is greater than twice
                   2337:         * the maximum individual RR data size.
                   2338:         */
                   2339:        target_mem = isc_mem_get(mctx, target_size);
                   2340:        if (target_mem == NULL) {
                   2341:                result = ISC_R_NOMEMORY;
                   2342:                goto cleanup;
                   2343:        }
                   2344:        isc_buffer_init(&target, target_mem, target_size);
                   2345:
                   2346:        name = dns_fixedname_initname(&fixed);
                   2347:
                   2348:        /*
                   2349:         * In the following loop, we regard any error fatal regardless of
                   2350:         * whether "MANYERRORS" is set in the context option.  This is because
                   2351:         * normal errors should already have been checked at creation time.
                   2352:         * Besides, it is very unlikely that we can recover from an error
                   2353:         * in this format, and so trying to continue parsing erroneous data
                   2354:         * does not really make sense.
                   2355:         */
                   2356:        for (loop_cnt = 0;
                   2357:             (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
                   2358:             loop_cnt++) {
                   2359:                unsigned int i, rdcount;
                   2360:                isc_uint16_t namelen;
                   2361:                isc_uint32_t totallen;
                   2362:                size_t minlen, readlen;
                   2363:                isc_boolean_t sequential_read = ISC_FALSE;
                   2364:
                   2365:                /* Read the data length */
                   2366:                isc_buffer_clear(&target);
                   2367:                INSIST(isc_buffer_availablelength(&target) >=
                   2368:                       sizeof(totallen));
                   2369:                result = isc_stdio_read(target.base, 1, sizeof(totallen),
                   2370:                                        lctx->f, NULL);
                   2371:                if (result == ISC_R_EOF) {
                   2372:                        result = ISC_R_SUCCESS;
                   2373:                        done = ISC_TRUE;
                   2374:                        break;
                   2375:                }
                   2376:                if (result != ISC_R_SUCCESS)
                   2377:                        goto cleanup;
                   2378:                isc_buffer_add(&target, sizeof(totallen));
                   2379:                totallen = isc_buffer_getuint32(&target);
                   2380:
                   2381:                /*
                   2382:                 * Validation: the input data must at least contain the common
                   2383:                 * header.
                   2384:                 */
                   2385:                minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
                   2386:                        sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
                   2387:                        sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
                   2388:                if (totallen < minlen) {
                   2389:                        result = ISC_R_RANGE;
                   2390:                        goto cleanup;
                   2391:                }
                   2392:                totallen -= sizeof(totallen);
                   2393:
                   2394:                isc_buffer_clear(&target);
                   2395:                if (totallen > isc_buffer_availablelength(&target)) {
                   2396:                        /*
                   2397:                         * The default buffer size should typically be large
                   2398:                         * enough to store the entire RRset.  We could try to
                   2399:                         * allocate enough space if this is not the case, but
                   2400:                         * it might cause a hazardous result when "totallen"
                   2401:                         * is forged.  Thus, we'd rather take an inefficient
                   2402:                         * but robust approach in this atypical case: read
                   2403:                         * data step by step, and commit partial data when
                   2404:                         * necessary.  Note that the buffer must be large
                   2405:                         * enough to store the "header part", owner name, and
                   2406:                         * at least one rdata (however large it is).
                   2407:                         */
                   2408:                        sequential_read = ISC_TRUE;
                   2409:                        readlen = minlen - sizeof(totallen);
                   2410:                } else {
                   2411:                        /*
                   2412:                         * Typical case.  We can read the whole RRset at once
                   2413:                         * with the default buffer.
                   2414:                         */
                   2415:                        readlen = totallen;
                   2416:                }
                   2417:                result = isc_stdio_read(target.base, 1, readlen,
                   2418:                                        lctx->f, NULL);
                   2419:                if (result != ISC_R_SUCCESS)
                   2420:                        goto cleanup;
                   2421:                isc_buffer_add(&target, (unsigned int)readlen);
                   2422:                totallen -= (isc_uint32_t)readlen;
                   2423:
                   2424:                /* Construct RRset headers */
                   2425:                dns_rdatalist_init(&rdatalist);
                   2426:                rdatalist.rdclass = isc_buffer_getuint16(&target);
                   2427:                if (lctx->zclass != rdatalist.rdclass) {
                   2428:                        result = DNS_R_BADCLASS;
                   2429:                        goto cleanup;
                   2430:                }
                   2431:                rdatalist.type = isc_buffer_getuint16(&target);
                   2432:                rdatalist.covers = isc_buffer_getuint16(&target);
                   2433:                rdatalist.ttl =  isc_buffer_getuint32(&target);
                   2434:                rdcount = isc_buffer_getuint32(&target);
                   2435:                if (rdcount == 0 || rdcount > 0xffff) {
                   2436:                        result = ISC_R_RANGE;
                   2437:                        goto cleanup;
                   2438:                }
                   2439:                INSIST(isc_buffer_consumedlength(&target) <= readlen);
                   2440:
                   2441:                /* Owner name: length followed by name */
                   2442:                result = read_and_check(sequential_read, &target,
                   2443:                                        sizeof(namelen), lctx->f, &totallen);
                   2444:                if (result != ISC_R_SUCCESS)
                   2445:                        goto cleanup;
                   2446:                namelen = isc_buffer_getuint16(&target);
                   2447:                if (namelen > sizeof(namebuf)) {
                   2448:                        result = ISC_R_RANGE;
                   2449:                        goto cleanup;
                   2450:                }
                   2451:
                   2452:                result = read_and_check(sequential_read, &target, namelen,
                   2453:                                        lctx->f, &totallen);
                   2454:                if (result != ISC_R_SUCCESS)
                   2455:                        goto cleanup;
                   2456:
                   2457:                isc_buffer_setactive(&target, (unsigned int)namelen);
                   2458:                result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
                   2459:                if (result != ISC_R_SUCCESS)
                   2460:                        goto cleanup;
                   2461:
                   2462:                if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
                   2463:                    rdatalist.ttl > lctx->maxttl)
                   2464:                {
                   2465:                        (callbacks->error)(callbacks,
                   2466:                                           "dns_master_load: "
                   2467:                                           "TTL %d exceeds configured "
                   2468:                                           "max-zone-ttl %d",
                   2469:                                           rdatalist.ttl, lctx->maxttl);
                   2470:                        result = ISC_R_RANGE;
                   2471:                        goto cleanup;
                   2472:                }
                   2473:
                   2474:                /* Rdata contents. */
                   2475:                if (rdcount > rdata_size) {
                   2476:                        dns_rdata_t *new_rdata = NULL;
                   2477:
                   2478:                        new_rdata = grow_rdata(rdcount + RDSZ, rdata,
                   2479:                                               rdata_size, &head,
                   2480:                                               &dummy, mctx);
                   2481:                        if (new_rdata == NULL) {
                   2482:                                result = ISC_R_NOMEMORY;
                   2483:                                goto cleanup;
                   2484:                        }
                   2485:                        rdata_size = rdcount + RDSZ;
                   2486:                        rdata = new_rdata;
                   2487:                }
                   2488:
                   2489:        continue_read:
                   2490:                for (i = 0; i < rdcount; i++) {
                   2491:                        isc_uint16_t rdlen;
                   2492:
                   2493:                        dns_rdata_init(&rdata[i]);
                   2494:
                   2495:                        if (sequential_read &&
                   2496:                            isc_buffer_availablelength(&target) < MINTSIZ) {
                   2497:                                unsigned int j;
                   2498:
                   2499:                                INSIST(i > 0); /* detect an infinite loop */
                   2500:
                   2501:                                /* Partial Commit. */
                   2502:                                ISC_LIST_APPEND(head, &rdatalist, link);
                   2503:                                result = commit(callbacks, lctx, &head, name,
                   2504:                                                NULL, 0);
                   2505:                                for (j = 0; j < i; j++) {
                   2506:                                        ISC_LIST_UNLINK(rdatalist.rdata,
                   2507:                                                        &rdata[j], link);
                   2508:                                        dns_rdata_reset(&rdata[j]);
                   2509:                                }
                   2510:                                if (result != ISC_R_SUCCESS)
                   2511:                                        goto cleanup;
                   2512:
                   2513:                                /* Rewind the buffer and continue */
                   2514:                                isc_buffer_clear(&target);
                   2515:
                   2516:                                rdcount -= i;
                   2517:
                   2518:                                goto continue_read;
                   2519:                        }
                   2520:
                   2521:                        /* rdata length */
                   2522:                        result = read_and_check(sequential_read, &target,
                   2523:                                                sizeof(rdlen), lctx->f,
                   2524:                                                &totallen);
                   2525:                        if (result != ISC_R_SUCCESS)
                   2526:                                goto cleanup;
                   2527:                        rdlen = isc_buffer_getuint16(&target);
                   2528:
                   2529:                        /* rdata */
                   2530:                        result = read_and_check(sequential_read, &target,
                   2531:                                                rdlen, lctx->f, &totallen);
                   2532:                        if (result != ISC_R_SUCCESS)
                   2533:                                goto cleanup;
                   2534:                        isc_buffer_setactive(&target, (unsigned int)rdlen);
                   2535:                        /*
                   2536:                         * It is safe to have the source active region and
                   2537:                         * the target available region be the same if
                   2538:                         * decompression is disabled (see dctx above) and we
                   2539:                         * are not downcasing names (options == 0).
                   2540:                         */
                   2541:                        isc_buffer_init(&buf, isc_buffer_current(&target),
                   2542:                                        (unsigned int)rdlen);
                   2543:                        result = dns_rdata_fromwire(&rdata[i],
                   2544:                                                    rdatalist.rdclass,
                   2545:                                                    rdatalist.type, &target,
                   2546:                                                    &dctx, 0, &buf);
                   2547:                        if (result != ISC_R_SUCCESS)
                   2548:                                goto cleanup;
                   2549:                        ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
                   2550:                }
                   2551:
                   2552:                /*
                   2553:                 * Sanity check.  Still having remaining space is not
                   2554:                 * necessarily critical, but it very likely indicates broken
                   2555:                 * or malformed data.
                   2556:                 */
                   2557:                if (isc_buffer_remaininglength(&target) != 0 || totallen != 0) {
                   2558:                        result = ISC_R_RANGE;
                   2559:                        goto cleanup;
                   2560:                }
                   2561:
                   2562:                ISC_LIST_APPEND(head, &rdatalist, link);
                   2563:
                   2564:                /* Commit this RRset.  rdatalist will be unlinked. */
                   2565:                result = commit(callbacks, lctx, &head, name, NULL, 0);
                   2566:
                   2567:                for (i = 0; i < rdcount; i++) {
                   2568:                        ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
                   2569:                        dns_rdata_reset(&rdata[i]);
                   2570:                }
                   2571:
                   2572:                if (result != ISC_R_SUCCESS)
                   2573:                        goto cleanup;
                   2574:        }
                   2575:
                   2576:        if (!done) {
                   2577:                INSIST(lctx->done != NULL && lctx->task != NULL);
                   2578:                result = DNS_R_CONTINUE;
                   2579:        } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
                   2580:                result = lctx->result;
                   2581:
                   2582:        if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL)
                   2583:                (*callbacks->rawdata)(callbacks->zone, &lctx->header);
                   2584:
                   2585:  cleanup:
                   2586:        if (rdata != NULL)
                   2587:                isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
                   2588:        if (target_mem != NULL)
                   2589:                isc_mem_put(mctx, target_mem, target_size);
                   2590:        if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
                   2591:                (*callbacks->error)(callbacks, "dns_master_load: %s",
                   2592:                                    dns_result_totext(result));
                   2593:        }
                   2594:
                   2595:        return (result);
                   2596: }
                   2597:
                   2598: isc_result_t
                   2599: dns_master_loadfile(const char *master_file, dns_name_t *top,
                   2600:                    dns_name_t *origin,
                   2601:                    dns_rdataclass_t zclass, unsigned int options,
                   2602:                    dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
                   2603: {
                   2604:        return (dns_master_loadfile5(master_file, top, origin, zclass,
                   2605:                                     options, 0, callbacks, NULL, NULL,
                   2606:                                     mctx, dns_masterformat_text, 0));
                   2607: }
                   2608:
                   2609: isc_result_t
                   2610: dns_master_loadfile2(const char *master_file, dns_name_t *top,
                   2611:                     dns_name_t *origin,
                   2612:                     dns_rdataclass_t zclass, unsigned int options,
                   2613:                     dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
                   2614:                     dns_masterformat_t format)
                   2615: {
                   2616:        return (dns_master_loadfile5(master_file, top, origin, zclass,
                   2617:                                     options, 0, callbacks, NULL, NULL,
                   2618:                                     mctx, format, 0));
                   2619: }
                   2620:
                   2621: isc_result_t
                   2622: dns_master_loadfile3(const char *master_file, dns_name_t *top,
                   2623:                     dns_name_t *origin, dns_rdataclass_t zclass,
                   2624:                     unsigned int options, isc_uint32_t resign,
                   2625:                     dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
                   2626:                     dns_masterformat_t format)
                   2627: {
                   2628:        return (dns_master_loadfile5(master_file, top, origin, zclass,
                   2629:                                     options, resign, callbacks, NULL, NULL,
                   2630:                                     mctx, format, 0));
                   2631: }
                   2632:
                   2633: isc_result_t
                   2634: dns_master_loadfile4(const char *master_file, dns_name_t *top,
                   2635:                     dns_name_t *origin, dns_rdataclass_t zclass,
                   2636:                     unsigned int options, isc_uint32_t resign,
                   2637:                     dns_rdatacallbacks_t *callbacks,
                   2638:                     dns_masterincludecb_t include_cb, void *include_arg,
                   2639:                     isc_mem_t *mctx, dns_masterformat_t format)
                   2640: {
                   2641:        return (dns_master_loadfile5(master_file, top, origin, zclass,
                   2642:                                     options, resign, callbacks,
                   2643:                                     include_cb, include_arg,
                   2644:                                     mctx, format, 0));
                   2645: }
                   2646:
                   2647: isc_result_t
                   2648: dns_master_loadfile5(const char *master_file, dns_name_t *top,
                   2649:                     dns_name_t *origin, dns_rdataclass_t zclass,
                   2650:                     unsigned int options, isc_uint32_t resign,
                   2651:                     dns_rdatacallbacks_t *callbacks,
                   2652:                     dns_masterincludecb_t include_cb, void *include_arg,
                   2653:                     isc_mem_t *mctx, dns_masterformat_t format,
                   2654:                     dns_ttl_t maxttl)
                   2655: {
                   2656:        dns_loadctx_t *lctx = NULL;
                   2657:        isc_result_t result;
                   2658:
                   2659:        result = loadctx_create(format, mctx, options, resign, top, zclass,
                   2660:                                origin, callbacks, NULL, NULL, NULL,
                   2661:                                include_cb, include_arg, NULL, &lctx);
                   2662:        if (result != ISC_R_SUCCESS)
                   2663:                return (result);
                   2664:
                   2665:        lctx->maxttl = maxttl;
                   2666:
                   2667:        result = (lctx->openfile)(lctx, master_file);
                   2668:        if (result != ISC_R_SUCCESS)
                   2669:                goto cleanup;
                   2670:
                   2671:        result = (lctx->load)(lctx);
                   2672:        INSIST(result != DNS_R_CONTINUE);
                   2673:
                   2674:  cleanup:
                   2675:        dns_loadctx_detach(&lctx);
                   2676:        return (result);
                   2677: }
                   2678:
                   2679: isc_result_t
                   2680: dns_master_loadfileinc(const char *master_file, dns_name_t *top,
                   2681:                       dns_name_t *origin, dns_rdataclass_t zclass,
                   2682:                       unsigned int options, dns_rdatacallbacks_t *callbacks,
                   2683:                       isc_task_t *task, dns_loaddonefunc_t done,
                   2684:                       void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
                   2685: {
                   2686:        return (dns_master_loadfileinc4(master_file, top, origin, zclass,
                   2687:                                        options, 0, callbacks, task, done,
                   2688:                                        done_arg, lctxp, NULL, NULL, mctx,
                   2689:                                        dns_masterformat_text));
                   2690: }
                   2691:
                   2692: isc_result_t
                   2693: dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
                   2694:                        dns_name_t *origin, dns_rdataclass_t zclass,
                   2695:                        unsigned int options, dns_rdatacallbacks_t *callbacks,
                   2696:                        isc_task_t *task, dns_loaddonefunc_t done,
                   2697:                        void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
                   2698:                        dns_masterformat_t format)
                   2699: {
                   2700:        return (dns_master_loadfileinc4(master_file, top, origin, zclass,
                   2701:                                        options, 0, callbacks, task, done,
                   2702:                                        done_arg, lctxp, NULL, NULL, mctx,
                   2703:                                        format));
                   2704: }
                   2705:
                   2706: isc_result_t
                   2707: dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
                   2708:                        dns_name_t *origin, dns_rdataclass_t zclass,
                   2709:                        unsigned int options, isc_uint32_t resign,
                   2710:                        dns_rdatacallbacks_t *callbacks, isc_task_t *task,
                   2711:                        dns_loaddonefunc_t done, void *done_arg,
                   2712:                        dns_loadctx_t **lctxp, isc_mem_t *mctx,
                   2713:                        dns_masterformat_t format)
                   2714: {
                   2715:        return (dns_master_loadfileinc4(master_file, top, origin, zclass,
                   2716:                                        options, resign, callbacks, task,
                   2717:                                        done, done_arg, lctxp, NULL, NULL,
                   2718:                                        mctx, format));
                   2719: }
                   2720:
                   2721: isc_result_t
                   2722: dns_master_loadfileinc4(const char *master_file, dns_name_t *top,
                   2723:                        dns_name_t *origin, dns_rdataclass_t zclass,
                   2724:                        unsigned int options, isc_uint32_t resign,
                   2725:                        dns_rdatacallbacks_t *callbacks,
                   2726:                        isc_task_t *task, dns_loaddonefunc_t done,
                   2727:                        void *done_arg, dns_loadctx_t **lctxp,
                   2728:                        dns_masterincludecb_t include_cb, void *include_arg,
                   2729:                        isc_mem_t *mctx, dns_masterformat_t format)
                   2730: {
                   2731:        options &= ~DNS_MASTER_CHECKTTL;
                   2732:        return (dns_master_loadfileinc5(master_file, top, origin, zclass,
                   2733:                                        options, resign, callbacks, task,
                   2734:                                        done, done_arg, lctxp, include_cb,
                   2735:                                        include_arg, mctx, format, 0));
                   2736: }
                   2737:
                   2738: isc_result_t
                   2739: dns_master_loadfileinc5(const char *master_file, dns_name_t *top,
                   2740:                        dns_name_t *origin, dns_rdataclass_t zclass,
                   2741:                        unsigned int options, isc_uint32_t resign,
                   2742:                        dns_rdatacallbacks_t *callbacks,
                   2743:                        isc_task_t *task, dns_loaddonefunc_t done,
                   2744:                        void *done_arg, dns_loadctx_t **lctxp,
                   2745:                        dns_masterincludecb_t include_cb, void *include_arg,
                   2746:                        isc_mem_t *mctx, dns_masterformat_t format,
                   2747:                        isc_uint32_t maxttl)
                   2748: {
                   2749:        dns_loadctx_t *lctx = NULL;
                   2750:        isc_result_t result;
                   2751:
                   2752:        REQUIRE(task != NULL);
                   2753:        REQUIRE(done != NULL);
                   2754:
                   2755:        result = loadctx_create(format, mctx, options, resign, top, zclass,
                   2756:                                origin, callbacks, task, done, done_arg,
                   2757:                                include_cb, include_arg, NULL, &lctx);
                   2758:        if (result != ISC_R_SUCCESS)
                   2759:                return (result);
                   2760:
                   2761:        lctx->maxttl = maxttl;
                   2762:
                   2763:        result = (lctx->openfile)(lctx, master_file);
                   2764:        if (result != ISC_R_SUCCESS)
                   2765:                goto cleanup;
                   2766:
                   2767:        result = task_send(lctx);
                   2768:        if (result == ISC_R_SUCCESS) {
                   2769:                dns_loadctx_attach(lctx, lctxp);
                   2770:                return (DNS_R_CONTINUE);
                   2771:        }
                   2772:
                   2773:  cleanup:
                   2774:        dns_loadctx_detach(&lctx);
                   2775:        return (result);
                   2776: }
                   2777:
                   2778: isc_result_t
                   2779: dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
                   2780:                      dns_rdataclass_t zclass, unsigned int options,
                   2781:                      dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
                   2782: {
                   2783:        isc_result_t result;
                   2784:        dns_loadctx_t *lctx = NULL;
                   2785:
                   2786:        REQUIRE(stream != NULL);
                   2787:
                   2788:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2789:                                zclass, origin, callbacks, NULL, NULL, NULL,
                   2790:                                NULL, NULL, NULL, &lctx);
                   2791:        if (result != ISC_R_SUCCESS)
                   2792:                goto cleanup;
                   2793:
                   2794:        result = isc_lex_openstream(lctx->lex, stream);
                   2795:        if (result != ISC_R_SUCCESS)
                   2796:                goto cleanup;
                   2797:
                   2798:        result = (lctx->load)(lctx);
                   2799:        INSIST(result != DNS_R_CONTINUE);
                   2800:
                   2801:  cleanup:
                   2802:        if (lctx != NULL)
                   2803:                dns_loadctx_detach(&lctx);
                   2804:        return (result);
                   2805: }
                   2806:
                   2807: isc_result_t
                   2808: dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
                   2809:                         dns_rdataclass_t zclass, unsigned int options,
                   2810:                         dns_rdatacallbacks_t *callbacks, isc_task_t *task,
                   2811:                         dns_loaddonefunc_t done, void *done_arg,
                   2812:                         dns_loadctx_t **lctxp, isc_mem_t *mctx)
                   2813: {
                   2814:        isc_result_t result;
                   2815:        dns_loadctx_t *lctx = NULL;
                   2816:
                   2817:        REQUIRE(stream != NULL);
                   2818:        REQUIRE(task != NULL);
                   2819:        REQUIRE(done != NULL);
                   2820:
                   2821:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2822:                                zclass, origin, callbacks, task, done,
                   2823:                                done_arg, NULL, NULL, NULL, &lctx);
                   2824:        if (result != ISC_R_SUCCESS)
                   2825:                goto cleanup;
                   2826:
                   2827:        result = isc_lex_openstream(lctx->lex, stream);
                   2828:        if (result != ISC_R_SUCCESS)
                   2829:                goto cleanup;
                   2830:
                   2831:        result = task_send(lctx);
                   2832:        if (result == ISC_R_SUCCESS) {
                   2833:                dns_loadctx_attach(lctx, lctxp);
                   2834:                return (DNS_R_CONTINUE);
                   2835:        }
                   2836:
                   2837:  cleanup:
                   2838:        if (lctx != NULL)
                   2839:                dns_loadctx_detach(&lctx);
                   2840:        return (result);
                   2841: }
                   2842:
                   2843: isc_result_t
                   2844: dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
                   2845:                      dns_name_t *origin, dns_rdataclass_t zclass,
                   2846:                      unsigned int options,
                   2847:                      dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
                   2848: {
                   2849:        isc_result_t result;
                   2850:        dns_loadctx_t *lctx = NULL;
                   2851:
                   2852:        REQUIRE(buffer != NULL);
                   2853:
                   2854:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2855:                                zclass, origin, callbacks, NULL, NULL, NULL,
                   2856:                                NULL, NULL, NULL, &lctx);
                   2857:        if (result != ISC_R_SUCCESS)
                   2858:                return (result);
                   2859:
                   2860:        result = isc_lex_openbuffer(lctx->lex, buffer);
                   2861:        if (result != ISC_R_SUCCESS)
                   2862:                goto cleanup;
                   2863:
                   2864:        result = (lctx->load)(lctx);
                   2865:        INSIST(result != DNS_R_CONTINUE);
                   2866:
                   2867:  cleanup:
                   2868:        dns_loadctx_detach(&lctx);
                   2869:        return (result);
                   2870: }
                   2871:
                   2872: isc_result_t
                   2873: dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
                   2874:                         dns_name_t *origin, dns_rdataclass_t zclass,
                   2875:                         unsigned int options,
                   2876:                         dns_rdatacallbacks_t *callbacks, isc_task_t *task,
                   2877:                         dns_loaddonefunc_t done, void *done_arg,
                   2878:                         dns_loadctx_t **lctxp, isc_mem_t *mctx)
                   2879: {
                   2880:        isc_result_t result;
                   2881:        dns_loadctx_t *lctx = NULL;
                   2882:
                   2883:        REQUIRE(buffer != NULL);
                   2884:        REQUIRE(task != NULL);
                   2885:        REQUIRE(done != NULL);
                   2886:
                   2887:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2888:                                zclass, origin, callbacks, task, done,
                   2889:                                done_arg, NULL, NULL, NULL, &lctx);
                   2890:        if (result != ISC_R_SUCCESS)
                   2891:                return (result);
                   2892:
                   2893:        result = isc_lex_openbuffer(lctx->lex, buffer);
                   2894:        if (result != ISC_R_SUCCESS)
                   2895:                goto cleanup;
                   2896:
                   2897:        result = task_send(lctx);
                   2898:        if (result == ISC_R_SUCCESS) {
                   2899:                dns_loadctx_attach(lctx, lctxp);
                   2900:                return (DNS_R_CONTINUE);
                   2901:        }
                   2902:
                   2903:  cleanup:
                   2904:        dns_loadctx_detach(&lctx);
                   2905:        return (result);
                   2906: }
                   2907:
                   2908: isc_result_t
                   2909: dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
                   2910:                     dns_name_t *origin, dns_rdataclass_t zclass,
                   2911:                     unsigned int options,
                   2912:                     dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
                   2913: {
                   2914:        isc_result_t result;
                   2915:        dns_loadctx_t *lctx = NULL;
                   2916:
                   2917:        REQUIRE(lex != NULL);
                   2918:
                   2919:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2920:                                zclass, origin, callbacks, NULL, NULL, NULL,
                   2921:                                NULL, NULL, lex, &lctx);
                   2922:        if (result != ISC_R_SUCCESS)
                   2923:                return (result);
                   2924:
                   2925:        result = (lctx->load)(lctx);
                   2926:        INSIST(result != DNS_R_CONTINUE);
                   2927:
                   2928:        dns_loadctx_detach(&lctx);
                   2929:        return (result);
                   2930: }
                   2931:
                   2932: isc_result_t
                   2933: dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
                   2934:                        dns_name_t *origin, dns_rdataclass_t zclass,
                   2935:                        unsigned int options,
                   2936:                        dns_rdatacallbacks_t *callbacks, isc_task_t *task,
                   2937:                        dns_loaddonefunc_t done, void *done_arg,
                   2938:                        dns_loadctx_t **lctxp, isc_mem_t *mctx)
                   2939: {
                   2940:        isc_result_t result;
                   2941:        dns_loadctx_t *lctx = NULL;
                   2942:
                   2943:        REQUIRE(lex != NULL);
                   2944:        REQUIRE(task != NULL);
                   2945:        REQUIRE(done != NULL);
                   2946:
                   2947:        result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
                   2948:                                zclass, origin, callbacks, task, done,
                   2949:                                done_arg, NULL, NULL, lex, &lctx);
                   2950:        if (result != ISC_R_SUCCESS)
                   2951:                return (result);
                   2952:
                   2953:        result = task_send(lctx);
                   2954:        if (result == ISC_R_SUCCESS) {
                   2955:                dns_loadctx_attach(lctx, lctxp);
                   2956:                return (DNS_R_CONTINUE);
                   2957:        }
                   2958:
                   2959:        dns_loadctx_detach(&lctx);
                   2960:        return (result);
                   2961: }
                   2962:
                   2963: /*
                   2964:  * Grow the slab of dns_rdatalist_t structures.
                   2965:  * Re-link glue and current list.
                   2966:  */
                   2967: static dns_rdatalist_t *
                   2968: grow_rdatalist(int new_len, dns_rdatalist_t *oldlist, int old_len,
                   2969:               rdatalist_head_t *current, rdatalist_head_t *glue,
                   2970:               isc_mem_t *mctx)
                   2971: {
                   2972:        dns_rdatalist_t *newlist;
                   2973:        int rdlcount = 0;
                   2974:        ISC_LIST(dns_rdatalist_t) save;
                   2975:        dns_rdatalist_t *this;
                   2976:
                   2977:        newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
                   2978:        if (newlist == NULL)
                   2979:                return (NULL);
                   2980:
                   2981:        ISC_LIST_INIT(save);
                   2982:        while ((this = ISC_LIST_HEAD(*current)) != NULL) {
                   2983:                ISC_LIST_UNLINK(*current, this, link);
                   2984:                ISC_LIST_APPEND(save, this, link);
                   2985:        }
                   2986:        while ((this = ISC_LIST_HEAD(save)) != NULL) {
                   2987:                ISC_LIST_UNLINK(save, this, link);
                   2988:                INSIST(rdlcount < new_len);
                   2989:                newlist[rdlcount] = *this;
                   2990:                ISC_LIST_APPEND(*current, &newlist[rdlcount], link);
                   2991:                rdlcount++;
                   2992:        }
                   2993:
                   2994:        ISC_LIST_INIT(save);
                   2995:        while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
                   2996:                ISC_LIST_UNLINK(*glue, this, link);
                   2997:                ISC_LIST_APPEND(save, this, link);
                   2998:        }
                   2999:        while ((this = ISC_LIST_HEAD(save)) != NULL) {
                   3000:                ISC_LIST_UNLINK(save, this, link);
                   3001:                INSIST(rdlcount < new_len);
                   3002:                newlist[rdlcount] = *this;
                   3003:                ISC_LIST_APPEND(*glue, &newlist[rdlcount], link);
                   3004:                rdlcount++;
                   3005:        }
                   3006:
                   3007:        INSIST(rdlcount == old_len);
                   3008:        if (oldlist != NULL)
                   3009:                isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
                   3010:        return (newlist);
                   3011: }
                   3012:
                   3013: /*
                   3014:  * Grow the slab of rdata structs.
                   3015:  * Re-link the current and glue chains.
                   3016:  */
                   3017: static dns_rdata_t *
                   3018: grow_rdata(int new_len, dns_rdata_t *oldlist, int old_len,
                   3019:           rdatalist_head_t *current, rdatalist_head_t *glue,
                   3020:           isc_mem_t *mctx)
                   3021: {
                   3022:        dns_rdata_t *newlist;
                   3023:        int rdcount = 0;
                   3024:        ISC_LIST(dns_rdata_t) save;
                   3025:        dns_rdatalist_t *this;
                   3026:        dns_rdata_t *rdata;
                   3027:
                   3028:        newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
                   3029:        if (newlist == NULL)
                   3030:                return (NULL);
                   3031:        memset(newlist, 0, new_len * sizeof(*newlist));
                   3032:
                   3033:        /*
                   3034:         * Copy current relinking.
                   3035:         */
                   3036:        this = ISC_LIST_HEAD(*current);
                   3037:        while (this != NULL) {
                   3038:                ISC_LIST_INIT(save);
                   3039:                while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
                   3040:                        ISC_LIST_UNLINK(this->rdata, rdata, link);
                   3041:                        ISC_LIST_APPEND(save, rdata, link);
                   3042:                }
                   3043:                while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
                   3044:                        ISC_LIST_UNLINK(save, rdata, link);
                   3045:                        INSIST(rdcount < new_len);
                   3046:                        newlist[rdcount] = *rdata;
                   3047:                        ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
                   3048:                        rdcount++;
                   3049:                }
                   3050:                this = ISC_LIST_NEXT(this, link);
                   3051:        }
                   3052:
                   3053:        /*
                   3054:         * Copy glue relinking.
                   3055:         */
                   3056:        this = ISC_LIST_HEAD(*glue);
                   3057:        while (this != NULL) {
                   3058:                ISC_LIST_INIT(save);
                   3059:                while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
                   3060:                        ISC_LIST_UNLINK(this->rdata, rdata, link);
                   3061:                        ISC_LIST_APPEND(save, rdata, link);
                   3062:                }
                   3063:                while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
                   3064:                        ISC_LIST_UNLINK(save, rdata, link);
                   3065:                        INSIST(rdcount < new_len);
                   3066:                        newlist[rdcount] = *rdata;
                   3067:                        ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
                   3068:                        rdcount++;
                   3069:                }
                   3070:                this = ISC_LIST_NEXT(this, link);
                   3071:        }
                   3072:        INSIST(rdcount == old_len || rdcount == 0);
                   3073:        if (oldlist != NULL)
                   3074:                isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
                   3075:        return (newlist);
                   3076: }
                   3077:
                   3078: static isc_uint32_t
                   3079: resign_fromlist(dns_rdatalist_t *this, dns_loadctx_t *lctx) {
                   3080:        dns_rdata_t *rdata;
                   3081:        dns_rdata_rrsig_t sig;
                   3082:        isc_uint32_t when;
                   3083:
                   3084:        rdata = ISC_LIST_HEAD(this->rdata);
                   3085:        INSIST(rdata != NULL);
                   3086:        (void)dns_rdata_tostruct(rdata, &sig, NULL);
                   3087:        if (isc_serial_gt(sig.timesigned, lctx->now))
                   3088:                when = lctx->now;
                   3089:        else
                   3090:                when = sig.timeexpire - lctx->resign;
                   3091:
                   3092:        rdata = ISC_LIST_NEXT(rdata, link);
                   3093:        while (rdata != NULL) {
                   3094:                (void)dns_rdata_tostruct(rdata, &sig, NULL);
                   3095:                if (isc_serial_gt(sig.timesigned, lctx->now))
                   3096:                        when = lctx->now;
                   3097:                else if (sig.timeexpire - lctx->resign < when)
                   3098:                        when = sig.timeexpire - lctx->resign;
                   3099:                rdata = ISC_LIST_NEXT(rdata, link);
                   3100:        }
                   3101:        return (when);
                   3102: }
                   3103:
                   3104: /*
                   3105:  * Convert each element from a rdatalist_t to rdataset then call commit.
                   3106:  * Unlink each element as we go.
                   3107:  */
                   3108:
                   3109: static isc_result_t
                   3110: commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
                   3111:        rdatalist_head_t *head, dns_name_t *owner,
                   3112:        const char *source, unsigned int line)
                   3113: {
                   3114:        dns_rdatalist_t *this;
                   3115:        dns_rdataset_t dataset;
                   3116:        isc_result_t result;
                   3117:        char namebuf[DNS_NAME_FORMATSIZE];
                   3118:        void    (*error)(struct dns_rdatacallbacks *, const char *, ...);
                   3119:
                   3120:        this = ISC_LIST_HEAD(*head);
                   3121:        error = callbacks->error;
                   3122:
                   3123:        if (this == NULL)
                   3124:                return (ISC_R_SUCCESS);
                   3125:        do {
                   3126:                dns_rdataset_init(&dataset);
                   3127:                RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
                   3128:                              == ISC_R_SUCCESS);
                   3129:                dataset.trust = dns_trust_ultimate;
                   3130:                /*
                   3131:                 * If this is a secure dynamic zone set the re-signing time.
                   3132:                 */
                   3133:                if (dataset.type == dns_rdatatype_rrsig &&
                   3134:                    (lctx->options & DNS_MASTER_RESIGN) != 0) {
                   3135:                        dataset.attributes |= DNS_RDATASETATTR_RESIGN;
                   3136:                        dataset.resign = resign_fromlist(this, lctx);
                   3137:                }
                   3138:                result = ((*callbacks->add)(callbacks->add_private, owner,
                   3139:                                            &dataset));
                   3140:                if (result == ISC_R_NOMEMORY) {
                   3141:                        (*error)(callbacks, "dns_master_load: %s",
                   3142:                                 dns_result_totext(result));
                   3143:                } else if (result != ISC_R_SUCCESS) {
                   3144:                        dns_name_format(owner, namebuf, sizeof(namebuf));
                   3145:                        if (source != NULL) {
                   3146:                                (*error)(callbacks, "%s: %s:%lu: %s: %s",
                   3147:                                         "dns_master_load", source, line,
                   3148:                                         namebuf, dns_result_totext(result));
                   3149:                        } else {
                   3150:                                (*error)(callbacks, "%s: %s: %s",
                   3151:                                         "dns_master_load", namebuf,
                   3152:                                         dns_result_totext(result));
                   3153:                        }
                   3154:                }
                   3155:                if (MANYERRS(lctx, result))
                   3156:                        SETRESULT(lctx, result);
                   3157:                else if (result != ISC_R_SUCCESS)
                   3158:                        return (result);
                   3159:                ISC_LIST_UNLINK(*head, this, link);
                   3160:                this = ISC_LIST_HEAD(*head);
                   3161:        } while (this != NULL);
                   3162:        return (ISC_R_SUCCESS);
                   3163: }
                   3164:
                   3165: /*
                   3166:  * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
                   3167:  */
                   3168:
                   3169: static isc_boolean_t
                   3170: is_glue(rdatalist_head_t *head, dns_name_t *owner) {
                   3171:        dns_rdatalist_t *this;
                   3172:        dns_rdata_t *rdata;
                   3173:        isc_region_t region;
                   3174:        dns_name_t name;
                   3175:
                   3176:        /*
                   3177:         * Find NS rrset.
                   3178:         */
                   3179:        this = ISC_LIST_HEAD(*head);
                   3180:        while (this != NULL) {
                   3181:                if (this->type == dns_rdatatype_ns)
                   3182:                        break;
                   3183:                this = ISC_LIST_NEXT(this, link);
                   3184:        }
                   3185:        if (this == NULL)
                   3186:                return (ISC_FALSE);
                   3187:
                   3188:        rdata = ISC_LIST_HEAD(this->rdata);
                   3189:        while (rdata != NULL) {
                   3190:                dns_name_init(&name, NULL);
                   3191:                dns_rdata_toregion(rdata, &region);
                   3192:                dns_name_fromregion(&name, &region);
                   3193:                if (dns_name_compare(&name, owner) == 0)
                   3194:                        return (ISC_TRUE);
                   3195:                rdata = ISC_LIST_NEXT(rdata, link);
                   3196:        }
                   3197:        return (ISC_FALSE);
                   3198: }
                   3199:
                   3200: static void
                   3201: load_quantum(isc_task_t *task, isc_event_t *event) {
                   3202:        isc_result_t result;
                   3203:        dns_loadctx_t *lctx;
                   3204:
                   3205:        REQUIRE(event != NULL);
                   3206:        lctx = event->ev_arg;
                   3207:        REQUIRE(DNS_LCTX_VALID(lctx));
                   3208:
                   3209:        if (lctx->canceled)
                   3210:                result = ISC_R_CANCELED;
                   3211:        else
                   3212:                result = (lctx->load)(lctx);
                   3213:        if (result == DNS_R_CONTINUE) {
                   3214:                event->ev_arg = lctx;
                   3215:                isc_task_send(task, &event);
                   3216:        } else {
                   3217:                (lctx->done)(lctx->done_arg, result);
                   3218:                isc_event_free(&event);
                   3219:                dns_loadctx_detach(&lctx);
                   3220:        }
                   3221: }
                   3222:
                   3223: static isc_result_t
                   3224: task_send(dns_loadctx_t *lctx) {
                   3225:        isc_event_t *event;
                   3226:
                   3227:        event = isc_event_allocate(lctx->mctx, NULL,
                   3228:                                   DNS_EVENT_MASTERQUANTUM,
                   3229:                                   load_quantum, lctx, sizeof(*event));
                   3230:        if (event == NULL)
                   3231:                return (ISC_R_NOMEMORY);
                   3232:        isc_task_send(lctx->task, &event);
                   3233:        return (ISC_R_SUCCESS);
                   3234: }
                   3235:
                   3236: void
                   3237: dns_loadctx_cancel(dns_loadctx_t *lctx) {
                   3238:        REQUIRE(DNS_LCTX_VALID(lctx));
                   3239:
                   3240:        LOCK(&lctx->lock);
                   3241:        lctx->canceled = ISC_TRUE;
                   3242:        UNLOCK(&lctx->lock);
                   3243: }
                   3244:
                   3245: void
                   3246: dns_master_initrawheader(dns_masterrawheader_t *header) {
                   3247:        memset(header, 0, sizeof(dns_masterrawheader_t));
                   3248: }

CVSweb <webmaster@jp.NetBSD.org>