~andreserl/ubuntu/lucid/bind9/bind9-apport-533601

« back to all changes in this revision

Viewing changes to lib/dns/zone.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2006-01-05 12:29:28 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060105122928-oih7ttkkmpb90q8q
Tags: 1:9.3.2-1
* New upstream
* use lsb-base for start/stop messages in init.d.
* switch to debhelper 4

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * PERFORMANCE OF THIS SOFTWARE.
16
16
 */
17
17
 
18
 
/* $Id: zone.c,v 1.333.2.23.2.55 2005/02/03 23:50:45 marka Exp $ */
 
18
/* $Id: zone.c,v 1.333.2.23.2.59 2005/07/29 00:38:33 marka Exp $ */
19
19
 
20
20
#include <config.h>
21
21
 
167
167
 
168
168
        isc_sockaddr_t          *masters;
169
169
        dns_name_t              **masterkeynames;
 
170
        isc_boolean_t           *mastersok;
170
171
        unsigned int            masterscnt;
171
172
        unsigned int            curmaster;
172
173
        isc_sockaddr_t          masteraddr;
536
537
        zone->minretry = DNS_ZONE_MINRETRY;
537
538
        zone->masters = NULL;
538
539
        zone->masterkeynames = NULL;
 
540
        zone->mastersok = NULL;
539
541
        zone->masterscnt = 0;
540
542
        zone->curmaster = 0;
541
543
        zone->notify = NULL;
590
592
 
591
593
 free_mutex:
592
594
        DESTROYLOCK(&zone->lock);
593
 
        return (ISC_R_NOMEMORY);
 
595
        isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
 
596
        return (result);
594
597
}
595
598
 
596
599
/*
1250
1253
        isc_uint32_t serial, refresh, retry, expire, minimum;
1251
1254
        isc_time_t now;
1252
1255
        isc_boolean_t needdump = ISC_FALSE;
 
1256
        isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1253
1257
 
1254
1258
        TIME_NOW(&now);
1255
1259
 
1355
1359
                if (result != ISC_R_SUCCESS)
1356
1360
                        goto cleanup;
1357
1361
                if (zone->db != NULL) {
1358
 
                        if (!isc_serial_ge(serial, zone->serial)) {
 
1362
                        /*
 
1363
                         * This is checked in zone_replacedb() for slave zones
 
1364
                         * as they don't reload from disk.
 
1365
                         */
 
1366
                        if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
 
1367
                            !isc_serial_gt(serial, zone->serial)) {
 
1368
                                isc_uint32_t serialmin, serialmax;
 
1369
 
 
1370
                                INSIST(zone->type == dns_zone_master);
 
1371
 
 
1372
                                serialmin = (zone->serial + 1) & 0xffffffffU;
 
1373
                                serialmax = (zone->serial + 0x7fffffffU) &
 
1374
                                             0xffffffffU;
 
1375
                                dns_zone_log(zone, ISC_LOG_ERROR,
 
1376
                                             "ixfr-from-differences: "
 
1377
                                             "new serial (%u) out of range "
 
1378
                                             "[%u - %u]", serial, serialmin,
 
1379
                                             serialmax);
 
1380
                                result = DNS_R_BADZONE;
 
1381
                                goto cleanup;
 
1382
                        } else if (!isc_serial_ge(serial, zone->serial))
1359
1383
                                dns_zone_log(zone, ISC_LOG_ERROR,
1360
1384
                                             "zone serial has gone backwards");
1361
 
                        }
 
1385
                        else if (serial == zone->serial && !hasinclude) 
 
1386
                                dns_zone_log(zone, ISC_LOG_ERROR,
 
1387
                                             "zone serial unchanged");
1362
1388
                }
1363
1389
                zone->serial = serial;
1364
1390
                zone->refresh = RANGE(refresh,
1943
1969
        isc_sockaddr_t *new;
1944
1970
        isc_result_t result = ISC_R_SUCCESS;
1945
1971
        dns_name_t **newname;
 
1972
        isc_boolean_t *newok;
1946
1973
        unsigned int i;
1947
1974
 
1948
1975
        REQUIRE(DNS_ZONE_VALID(zone));
1972
1999
                            zone->masterscnt * sizeof(dns_name_t *));
1973
2000
                zone->masterkeynames = NULL;
1974
2001
        }
 
2002
        if (zone->mastersok != NULL) {
 
2003
                isc_mem_put(zone->mctx, zone->mastersok,
 
2004
                            zone->masterscnt * sizeof(isc_boolean_t));
 
2005
                zone->mastersok = NULL;
 
2006
        }
1975
2007
        zone->masterscnt = 0;
1976
2008
        /*
1977
 
         * If count == 0, don't allocate any space for masters or keynames
1978
 
         * so internally, those pointers are NULL if count == 0
 
2009
         * If count == 0, don't allocate any space for masters, mastersok or
 
2010
         * keynames so internally, those pointers are NULL if count == 0
1979
2011
         */
1980
2012
        if (count == 0)
1981
2013
                goto unlock;
1983
2015
        /*
1984
2016
         * masters must countain count elements!
1985
2017
         */
1986
 
        new = isc_mem_get(zone->mctx,
1987
 
                          count * sizeof(isc_sockaddr_t));
 
2018
        new = isc_mem_get(zone->mctx, count * sizeof(*new));
1988
2019
        if (new == NULL) {
1989
2020
                result = ISC_R_NOMEMORY;
1990
2021
                goto unlock;
1991
2022
        }
1992
2023
        memcpy(new, masters, count * sizeof(*new));
1993
 
        zone->masters = new;
1994
 
        zone->masterscnt = count;
1995
 
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
 
2024
        
 
2025
        /*
 
2026
         * Similarly for mastersok.
 
2027
         */
 
2028
        newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
 
2029
        if (newok == NULL) {
 
2030
                result = ISC_R_NOMEMORY;
 
2031
                isc_mem_put(zone->mctx, new, count * sizeof(*new));
 
2032
                goto unlock;
 
2033
        };
 
2034
        for (i = 0; i < count; i++)
 
2035
                newok[i] = ISC_FALSE;
1996
2036
 
1997
2037
        /*
1998
2038
         * if keynames is non-NULL, it must contain count elements!
1999
2039
         */
 
2040
        newname = NULL;
2000
2041
        if (keynames != NULL) {
2001
 
                newname = isc_mem_get(zone->mctx,
2002
 
                                      count * sizeof(dns_name_t *));
 
2042
                newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
2003
2043
                if (newname == NULL) {
2004
2044
                        result = ISC_R_NOMEMORY;
2005
 
                        isc_mem_put(zone->mctx, zone->masters,
2006
 
                                    count * sizeof(*new));
 
2045
                        isc_mem_put(zone->mctx, new, count * sizeof(*new));
 
2046
                        isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
2007
2047
                        goto unlock;
2008
2048
                }
2009
2049
                for (i = 0; i < count; i++)
2024
2064
                                                        dns_name_free(
2025
2065
                                                               newname[i],
2026
2066
                                                               zone->mctx);
2027
 
                                        isc_mem_put(zone->mctx, zone->masters,
 
2067
                                        isc_mem_put(zone->mctx, new,
2028
2068
                                                    count * sizeof(*new));
 
2069
                                        isc_mem_put(zone->mctx, newok,
 
2070
                                                    count * sizeof(*newok));
2029
2071
                                        isc_mem_put(zone->mctx, newname,
2030
2072
                                                    count * sizeof(*newname));
2031
2073
                                        goto unlock;
2032
2074
                                }
2033
2075
                        }
2034
2076
                }
2035
 
                zone->masterkeynames = newname;
2036
2077
        }
 
2078
 
 
2079
        /*
 
2080
         * Everything is ok so attach to the zone.
 
2081
         */
 
2082
        zone->masters = new;
 
2083
        zone->mastersok = newok;
 
2084
        zone->masterkeynames = newname;
 
2085
        zone->masterscnt = count;
 
2086
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
 
2087
 
2037
2088
 unlock:
2038
2089
        UNLOCK_ZONE(zone);
2039
2090
        return (result);
2222
2273
dns_zone_refresh(dns_zone_t *zone) {
2223
2274
        isc_interval_t i;
2224
2275
        isc_uint32_t oldflags;
 
2276
        unsigned int j;
2225
2277
 
2226
2278
        REQUIRE(DNS_ZONE_VALID(zone));
2227
2279
 
2266
2318
                zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
2267
2319
 
2268
2320
        zone->curmaster = 0;
 
2321
        for (j = 0; j < zone->masterscnt; j++)
 
2322
                zone->mastersok[j] = ISC_FALSE;
2269
2323
        /* initiate soa query */
2270
2324
        queue_soa_query(zone);
2271
2325
 unlock:
3186
3240
        isc_time_t now;
3187
3241
        isc_boolean_t exiting = ISC_FALSE;
3188
3242
        isc_interval_t i;
 
3243
        unsigned int j;
3189
3244
 
3190
3245
        stub = revent->ev_arg;
3191
3246
        INSIST(DNS_STUB_VALID(stub));
3360
3415
        isc_event_free(&event);
3361
3416
        LOCK_ZONE(zone);
3362
3417
        dns_request_destroy(&zone->request);
3363
 
        zone->curmaster++;
 
3418
        /*
 
3419
         * Skip to next failed / untried master.
 
3420
         */
 
3421
        do {
 
3422
                zone->curmaster++;
 
3423
        } while (zone->curmaster < zone->masterscnt &&
 
3424
                 zone->mastersok[zone->curmaster]);
3364
3425
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3365
3426
        if (exiting || zone->curmaster >= zone->masterscnt) {
 
3427
                isc_boolean_t done = ISC_TRUE;
3366
3428
                if (!exiting &&
3367
3429
                    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
3368
3430
                    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
 
3431
                        /*
 
3432
                         * Did we get a good answer from all the masters?
 
3433
                         */
 
3434
                        for (j = 0; j < zone->masterscnt; j++)
 
3435
                                if (zone->mastersok[j] == ISC_FALSE) {
 
3436
                                        done = ISC_FALSE;
 
3437
                                        break;
 
3438
                                }
 
3439
                } else
 
3440
                        done = ISC_TRUE;
 
3441
                if (!done) {
3369
3442
                        zone->curmaster = 0;
 
3443
                        /*
 
3444
                         * Find the next failed master.
 
3445
                         */
 
3446
                        while (zone->curmaster < zone->masterscnt &&
 
3447
                               zone->mastersok[zone->curmaster])
 
3448
                                zone->curmaster++;
3370
3449
                        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3371
3450
                } else {
3372
3451
                        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3420
3499
        dns_rdata_soa_t soa;
3421
3500
        isc_result_t result;
3422
3501
        isc_uint32_t serial;
 
3502
        unsigned int j;
3423
3503
 
3424
3504
        zone = revent->ev_arg;
3425
3505
        INSIST(DNS_ZONE_VALID(zone));
3668
3748
                }
3669
3749
                DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
3670
3750
                DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
 
3751
                zone->mastersok[zone->curmaster] = ISC_TRUE;
3671
3752
                goto next_master;
3672
3753
        } else {
3673
3754
                if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
3676
3757
                                     soa.serial, master, zone->serial);
3677
3758
                else
3678
3759
                        zone_debuglog(zone, me, 1, "ahead");
 
3760
                zone->mastersok[zone->curmaster] = ISC_TRUE;
3679
3761
                goto next_master;
3680
3762
        }
3681
3763
        if (msg != NULL)
3688
3770
        isc_event_free(&event);
3689
3771
        LOCK_ZONE(zone);
3690
3772
        dns_request_destroy(&zone->request);
3691
 
        zone->curmaster++;
 
3773
        /*
 
3774
         * Skip to next failed / untried master.
 
3775
         */
 
3776
        do {
 
3777
                zone->curmaster++;
 
3778
        } while (zone->curmaster < zone->masterscnt &&
 
3779
                 zone->mastersok[zone->curmaster]);
3692
3780
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3693
3781
        if (zone->curmaster >= zone->masterscnt) {
 
3782
                isc_boolean_t done = ISC_TRUE;
3694
3783
                if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
3695
3784
                    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
 
3785
                        /*
 
3786
                         * Did we get a good answer from all the masters?
 
3787
                         */
 
3788
                        for (j = 0; j < zone->masterscnt; j++)
 
3789
                                if (zone->mastersok[j] == ISC_FALSE) {
 
3790
                                        done = ISC_FALSE;
 
3791
                                        break;
 
3792
                                }
 
3793
                } else
 
3794
                        done = ISC_TRUE;
 
3795
                if (!done) {
3696
3796
                        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3697
3797
                        zone->curmaster = 0;
 
3798
                        /*
 
3799
                         * Find the next failed master.
 
3800
                         */
 
3801
                        while (zone->curmaster < zone->masterscnt &&
 
3802
                               zone->mastersok[zone->curmaster])
 
3803
                                zone->curmaster++;
3698
3804
                        goto requeue;
3699
3805
                }
3700
3806
                DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4023
4129
 skip_master:
4024
4130
        if (key != NULL)
4025
4131
                dns_tsigkey_detach(&key);
4026
 
        zone->curmaster++;
 
4132
        /*
 
4133
         * Skip to next failed / untried master.
 
4134
         */
 
4135
        do {
 
4136
                zone->curmaster++;
 
4137
        } while (zone->curmaster < zone->masterscnt &&
 
4138
                 zone->mastersok[zone->curmaster]);
4027
4139
        if (zone->curmaster < zone->masterscnt)
4028
4140
                goto again;
4029
4141
        zone->curmaster = 0;
5275
5387
         * is enabled in the configuration.
5276
5388
         */
5277
5389
        if (zone->db != NULL && zone->journal != NULL &&
5278
 
            DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
5279
 
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5280
 
                              DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5281
 
                              "generating diffs");
5282
 
                result = dns_db_diff(zone->mctx, db, ver,
5283
 
                                     zone->db, NULL /* XXX */,
 
5390
            DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
 
5391
            !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
 
5392
                isc_uint32_t serial;
 
5393
 
 
5394
                dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
 
5395
 
 
5396
                result = dns_db_getsoaserial(db, ver, &serial);
 
5397
                if (result != ISC_R_SUCCESS) {
 
5398
                        dns_zone_log(zone, ISC_LOG_ERROR,
 
5399
                                     "ixfr-from-differences: unable to get "
 
5400
                                     "new serial");
 
5401
                        goto fail;
 
5402
                }
 
5403
 
 
5404
                /*
 
5405
                 * This is checked in zone_postload() for master zones.
 
5406
                 */
 
5407
                if (zone->type == dns_zone_slave &&
 
5408
                    !isc_serial_gt(serial, zone->serial)) {
 
5409
                        isc_uint32_t serialmin, serialmax;
 
5410
                        serialmin = (zone->serial + 1) & 0xffffffffU;
 
5411
                        serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
 
5412
                        dns_zone_log(zone, ISC_LOG_ERROR,
 
5413
                                     "ixfr-from-differences: failed: "
 
5414
                                     "new serial (%u) out of range [%u - %u]",
 
5415
                                     serial, serialmin, serialmax);
 
5416
                        result = ISC_R_RANGE;
 
5417
                        goto fail;
 
5418
                }
 
5419
 
 
5420
                result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
5284
5421
                                     zone->journal);
5285
5422
                if (result != ISC_R_SUCCESS)
5286
5423
                        goto fail;
5287
5424
                if (dump)
5288
5425
                        zone_needdump(zone, DNS_DUMP_DELAY);
5289
5426
                else if (zone->journalsize != -1) {
5290
 
                        isc_uint32_t serial;
5291
 
 
5292
 
                        result = dns_db_getsoaserial(db, ver, &serial);
5293
 
                        if (result == ISC_R_SUCCESS) {
5294
 
                                result = dns_journal_compact(zone->mctx,
5295
 
                                                             zone->journal,
5296
 
                                                             serial,
5297
 
                                                             zone->journalsize);
5298
 
                                switch (result) {
5299
 
                                case ISC_R_SUCCESS:
5300
 
                                case ISC_R_NOSPACE:
5301
 
                                case ISC_R_NOTFOUND:
5302
 
                                        dns_zone_log(zone, ISC_LOG_DEBUG(3),
5303
 
                                                     "dns_journal_compact: %s",
5304
 
                                                     dns_result_totext(result));
5305
 
                                        break;
5306
 
                                default:
5307
 
                                        dns_zone_log(zone, ISC_LOG_ERROR,
 
5427
                        result = dns_journal_compact(zone->mctx, zone->journal,
 
5428
                                                     serial, zone->journalsize);
 
5429
                        switch (result) {
 
5430
                        case ISC_R_SUCCESS:
 
5431
                        case ISC_R_NOSPACE:
 
5432
                        case ISC_R_NOTFOUND:
 
5433
                                dns_zone_log(zone, ISC_LOG_DEBUG(3),
 
5434
                                             "dns_journal_compact: %s",
 
5435
                                             dns_result_totext(result));
 
5436
                                break;
 
5437
                        default:
 
5438
                                dns_zone_log(zone, ISC_LOG_ERROR,
5308
5439
                                             "dns_journal_compact failed: %s",
5309
 
                                                     dns_result_totext(result));
5310
 
                                        break;
5311
 
                                }
 
5440
                                             dns_result_totext(result));
 
5441
                                break;
5312
5442
                        }
5313
5443
                }
5314
5444
        } else {
5503
5633
 
5504
5634
        default:
5505
5635
        next_master:
5506
 
                zone->curmaster++;
 
5636
                /*
 
5637
                 * Skip to next failed / untried master.
 
5638
                 */
 
5639
                do {
 
5640
                        zone->curmaster++;
 
5641
                } while (zone->curmaster < zone->masterscnt &&
 
5642
                         zone->mastersok[zone->curmaster]);
 
5643
                /* FALLTHROUGH */
5507
5644
        same_master:
5508
5645
                if (zone->curmaster >= zone->masterscnt) {
5509
5646
                        zone->curmaster = 0;
5511
5648
                            !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
5512
5649
                                DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
5513
5650
                                DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
 
5651
                                while (zone->curmaster < zone->masterscnt &&
 
5652
                                       zone->mastersok[zone->curmaster])
 
5653
                                        zone->curmaster++;
5514
5654
                                again = ISC_TRUE;
5515
5655
                        } else
5516
5656
                                DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
5697
5837
                             "requesting AXFR of "
5698
5838
                             "initial version from %s", mastertext);
5699
5839
                xfrtype = dns_rdatatype_axfr;
5700
 
        } else if (dns_zone_isforced(zone)) {
 
5840
        } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
 
5841
                dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
 
5842
                             "set, requesting AXFR from %s", mastertext);
 
5843
                xfrtype = dns_rdatatype_axfr;
 
5844
        } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
5701
5845
                dns_zone_log(zone, ISC_LOG_DEBUG(1),
5702
5846
                             "forced reload, requesting AXFR of "
5703
5847
                             "initial version from %s", mastertext);
6663
6807
dns_zone_forcereload(dns_zone_t *zone) {
6664
6808
        REQUIRE(DNS_ZONE_VALID(zone));
6665
6809
 
 
6810
        if (zone->type == dns_zone_master)
 
6811
                return;
 
6812
 
6666
6813
        LOCK_ZONE(zone);
6667
6814
        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6668
6815
        UNLOCK_ZONE(zone);