Esempio n. 1
0
void
dnscore_stop_timer()
{
    /*
     * Timer thread stop
     */

    int mypid = getpid();

    if(mypid == dnscore_timer_creator_pid)
    {
        smp_int_set(&dnscore_running, 0);

        if(dnscore_timer_thread_id != 0)
        {
            log_debug("stopping timer");

            pthread_join(dnscore_timer_thread_id, NULL);
            pthread_detach(dnscore_timer_thread_id);
            
            dnscore_timer_creator_pid = 0;
            dnscore_timer_thread_id = 0;
        }
    }
    else
    {
#ifndef NDEBUG
        log_debug("timer owned by %d (0 meaning stopped already), not touching it (I'm %d)", dnscore_timer_creator_pid, mypid);
#endif
    }
    
    logger_flush();
}
Esempio n. 2
0
void log_assert__(bool b, const char *txt, const char *file, int line)
{
    if(!b)
    {
        log_err("assert: at %s:%d: %s", file, line, txt); /* this is in zassert */
        logger_flush();
        sleep(10);                  /* be nice */
        exit(-1);
    }
}
Esempio n. 3
0
int
logger_timer_cb (void *data, int remaining_calls)
{
    /* make C compiler happy */
    (void) data;
    (void) remaining_calls;

    logger_flush ();

    return WEECHAT_RC_OK;
}
Esempio n. 4
0
int
logger_command_cb (void *data, struct t_gui_buffer *buffer,
                   int argc, char **argv, char **argv_eol)
{
    /* make C compiler happy */
    (void) data;
    (void) argv_eol;

    if ((argc == 1)
        || ((argc == 2) && (weechat_strcasecmp (argv[1], "list") == 0)))
    {
        logger_list ();
        return WEECHAT_RC_OK;
    }

    if (argc > 1)
    {
        if (weechat_strcasecmp (argv[1], "set") == 0)
        {
            if (argc > 2)
                logger_set_buffer (buffer, argv[2]);
            return WEECHAT_RC_OK;
        }

        if (weechat_strcasecmp (argv[1], "flush") == 0)
        {
            logger_flush ();
            return WEECHAT_RC_OK;
        }

        if (weechat_strcasecmp (argv[1], "disable") == 0)
        {
            logger_set_buffer (buffer, "0");
        }
    }

    return WEECHAT_RC_OK;
}
Esempio n. 5
0
static void*
dnscore_timer_thread(void * unused0)
{
    thread_pool_setup_random_ctx();

    int last_call = time(NULL);
    dnscore_timer_tick = last_call;

    while(smp_int_get(&dnscore_running) != 0)
    {
        /* log & term output flush handling */
        stdstream_flush_both_terms();

        logger_flush();

        /* alarm callback handling */        
        int period = dnscore_timer_period;

        do
        {
            sleep(period);

            dnscore_timer_tick = time(NULL);

            period = dnscore_timer_tick - last_call;
        }
        while((period < dnscore_timer_period) && (smp_int_get(&dnscore_running) != 0));

        alarm_run_tick(dnscore_timer_tick);
        
        last_call = dnscore_timer_tick;
    }

    pthread_exit(NULL);

    return NULL;
}
Esempio n. 6
0
ya_result
zdb_icmtl_replay(zdb_zone *zone)
{
    ya_result return_value;
    u32 serial;
    
    zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);

    return_value = zdb_zone_getserial(zone, &serial); // zone is locked
    
    if(FAIL(return_value))
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        log_err("journal: %{dnsname}: error reading serial for zone: %r", zone->origin, return_value);
        
        return return_value;
    }

    input_stream is;
    
#if ICMTL_DUMP_JOURNAL_RECORDS
    log_debug("journal: zdb_icmtl_replay(%{dnsname})", zone->origin);
    logger_flush();
#endif
    
    u32 first_serial;
    u32 last_serial;
        
    if(FAIL(return_value = zdb_zone_journal_get_serial_range(zone, &first_serial, &last_serial)))
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        if(return_value == ZDB_ERROR_ICMTL_NOTFOUND)
        {
            return_value = SUCCESS;
        }
        else
        {
            log_err("journal: %{dnsname}: error opening journal for zone: %r", zone->origin, return_value);
        }
                
        return return_value;
    }
    
    log_debug("journal: %{dnsname}: zone serial is %i, journal covers serials from %i to %i", zone->origin, serial, first_serial, last_serial);
    
    if(last_serial == serial)
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        log_debug("journal: %{dnsname}: nothing to read from the journal", zone->origin);
        return 0;
    }
    
    if(serial_lt(serial, first_serial))
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        log_warn("journal: %{dnsname}: first serial from the journal is after the zone", zone->origin);
        // should invalidate the journal
        zdb_zone_journal_delete(zone);
        return 0;
    }
    
    if(serial_gt(serial, last_serial))
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        log_warn("journal: %{dnsname}: last serial from the journal is before the zone", zone->origin);
        // should invalidate the journal
        zdb_zone_journal_delete(zone);
        return 0;
    }
    
    if(FAIL(return_value = zdb_zone_journal_get_ixfr_stream_at_serial(zone, serial, &is, NULL)))
    {
        zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
        
        log_err("journal: %{dnsname}: error reading journal from serial %d: %r",zone->origin, serial, return_value);

        return return_value;
    }
    
    log_info("journal: %{dnsname}: replaying from serial %u",zone->origin, serial);

    buffer_input_stream_init(&is, &is, ZDB_ICMTL_REPLAY_BUFFER_SIZE);    

    u16 shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD;
    
    u32 current_serial = serial;
    
    /*
     * Read all records from [ SOA ... SOA ... [ SOA in memory
     */
    
    output_stream baos;
    input_stream bais;
    dns_resource_record rr;
    
    int baos_rr_count = 0;
    int baos_soa_count = 0;
    
    bool was_nsec3 = zdb_zone_is_nsec3(zone);

    bytearray_output_stream_init_ex(&baos, NULL, ZDB_ICMTL_REPLAY_BUFFER_SIZE, BYTEARRAY_DYNAMIC);
    dns_resource_record_init(&rr);    
           
    // 0: gather, 1: commit, 2: commit & stop
    
    for(int replay_state = ZDB_ICMTL_REPLAY_GATHER; replay_state != ZDB_ICMTL_REPLAY_COMMIT_AND_STOP;)
    {
        // ensure it's not supposed to shutdown (every few iterations)
        
        if(--shutdown_test_countdown <= 0)
        {
            if(dnscore_shuttingdown())
            {
                return_value = STOPPED_BY_APPLICATION_SHUTDOWN;
                break;
            }
            
            shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD;
        }
        
        // read the next record
        
        if((return_value = dns_resource_record_read(&rr, &is)) <= 0)
        {
            if(ISOK(return_value))
            {
                log_info("journal: %{dnsname}: reached the end of the journal file", zone->origin);
                replay_state = ZDB_ICMTL_REPLAY_COMMIT_AND_STOP;
            }
            else
            {
                log_err("journal: broken journal: %r", return_value);
                logger_flush(); // broken journal (flush is slow, but this is bad, so : keep it)
                replay_state = ZDB_ICMTL_REPLAY_STOP;
            }
        }
        else // first record must be an SOA (or it's wrong)        
        if(baos_rr_count == 0) // first record ?
        {
            if(rr.tctr.qtype != TYPE_SOA) // must be SOA
            {
                // expected an SOA
                return_value = ERROR;
                break;
            }
            
            ++baos_soa_count; // 0 -> 1 // this is not mandatory but clearer to read
        }
        else // the page ends with an SOA or end of stream
        if(rr.tctr.qtype == TYPE_SOA)
        {
            if(baos_soa_count == 2)
            {
                // this record is the start of the next stream, keep it for the next iteration
                replay_state = ZDB_ICMTL_REPLAY_COMMIT;
            }
            
            ++baos_soa_count;
        }
        
        ++baos_rr_count;
        
        if((replay_state & ZDB_ICMTL_REPLAY_COMMIT) != 0)
        {
            log_info("journal: %{dnsname}: committing changes", zone->origin);
            u64 ts_start = timeus();
            zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
            bytearray_input_stream_init_const(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos));
            
            return_value = zdb_icmtl_replay_commit(zone, &bais, &current_serial);
            
            zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER);
            input_stream_close(&bais);
            u64 ts_stop = timeus();
            if(ts_stop < ts_start) // time change
            {
                ts_stop = ts_start;
            }
            
            u64 ts_delta = ts_stop - ts_start;
            
            if(ISOK(return_value))
            {
                if(ts_delta < 1000)
                {            
                    log_info("journal: %{dnsname}: committed changes (%lluus)", zone->origin, ts_delta);
                }
                else if(ts_delta < 1000000)
                {
                    double ts_delta_s = ts_delta;
                    ts_delta_s /= 1000.0;
                    log_info("journal: %{dnsname}: committed changes (%5.2fms)", zone->origin, ts_delta_s);
                }
                else
                {
                    double ts_delta_s = ts_delta;
                    ts_delta_s /= 1000000.0;
                    log_info("journal: %{dnsname}: committed changes (%5.2fs)", zone->origin, ts_delta_s);
                }
            }
            else
            {
                log_err("journal: %{dnsname}: failed to committed changes", zone->origin);
                break;
            }
                    
            // the current page has been processed
            
            if(replay_state == ZDB_ICMTL_REPLAY_COMMIT_AND_STOP)
            {
                // no more page to read
                break;
            }
            
            // reset the state for the next page
            // note: the next written record will be the last read SOA
                        
            baos_rr_count = 1;
            baos_soa_count = 1;
            replay_state = ZDB_ICMTL_REPLAY_GATHER;
            bytearray_output_stream_reset(&baos);
                       
        } // end if replay_state is ZDB_ICMTL_REPLAY_COMMIT (mask)
                
        dns_resource_record_write(&rr, &baos);
    }
   
    input_stream_close(&is);
    output_stream_close(&baos);
    dns_resource_record_clear(&rr);
    
    // cleanup destroyed nsec3 chains
    
    if(ISOK(return_value))
    {
        bool is_nsec3 = zdb_zone_is_nsec3(zone);

        if(is_nsec3 && !was_nsec3)
        {
            // the chain has just been created, but is probably missing internal links
            log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: updating links", zone->origin);

            zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
            nsec3_zone_update_chain0_links(zone);
            zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER);

            log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: links updated", zone->origin);
        }

        if(FAIL(return_value = zdb_zone_getserial(zone, &serial))) // zone is locked
        {
            zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);

            log_err("journal: %{dnsname}: error reading confirmation serial for zone: %r",zone->origin, return_value);

            return return_value;
        }

        if(serial != last_serial)
        {
            log_warn("journal: %{dnsname}: expected serial to be %i but it is %i instead",zone->origin, last_serial, serial);
        }

#if 0 // ICMTL_DUMP_JOURNAL_RECORDS
        if(is_nsec)
        {
            nsec_logdump_tree(zone);
            logger_flush();
        }
#endif
    }
    
    zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD);
    
    log_info("journal: %{dnsname}: done", zone->origin);

    return return_value;
}
Esempio n. 7
0
ya_result
zdb_icmtl_replay_commit(zdb_zone *zone, input_stream *is, u32 *current_serialp)
{
    ya_result ret;
    /*
     * 0: DELETE, 1: ADD
     * The mode is switched every time an SOA is found.
     */

    yassert(zdb_zone_islocked(zone));
    
#if ZDB_HAS_NSEC3_SUPPORT
    bool has_nsec3 = zdb_zone_is_nsec3(zone);
#endif
#if ZDB_HAS_NSEC_SUPPORT
    bool has_nsec = zdb_zone_is_nsec(zone);
#endif
    
#if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT
    if(has_nsec3 && has_nsec)
    {
        log_err("journal: %{dnsname}: zone has both NSEC and NSEC3 status, which is not supported by YADIFA", zone->origin);
        return ERROR;
    }
#endif
    
    u8 mode = 1; // the first SOA will switch the mode to delete
    s32 changes = 0;
    
    zdb_ttlrdata ttlrdata;
    dns_resource_record rr;
    dns_resource_record_init(&rr);
    const u8 *fqdn = rr.name;
    dnslabel_vector labels;

    ttlrdata.next = NULL;
    


    /*
     * The plan for NSEC3 :
     * Store the fqdn + type class ttl rdata in collections
     * => the delete collection
     * => the add collection
     * Then there is the NSEC3 covered labels: keep a reference to them for later
     *
     * When a pass of SOA-/SOA+ has finished:
     * _ replace the NSEC3 in both collections (reading from delete)
     * _ delete NSEC3 to delete
     * _ add NSEC3 to add
     *
     * _ and finally update the NSEC3 for the labels kept above
     */

#if ZDB_HAS_NSEC3_SUPPORT
    chain_replay nsec3replay;
    nsec3_chain_replay_init(&nsec3replay, zone);
#endif
    
#if ZDB_HAS_NSEC_SUPPORT
    chain_replay nsecreplay;
    nsec_chain_replay_init(&nsecreplay, zone);
#endif
    
#if ZDB_HAS_NSEC3_SUPPORT
    ptr_set downed_fqdn = PTR_SET_DNSNAME_EMPTY;
#endif

    /* 
     * At this point : the next record, if it exists AND is not an SOA , has to be deleted
     * 
     */
    
    bool did_remove_soa = FALSE;

    // something has to be committed

    for(;;)
    {
        /*
         * read the full record
         * 
         * == 0 : no record (EOF)
         *  < 0 : failed
         */

        if((ret = dns_resource_record_read(&rr, is)) <= 0)
        {
            if(ISOK(ret))
            {
                log_info("journal: %{dnsname}: reached the end of the journal page", zone->origin);
            }
            else
            {
                log_err("journal: %{dnsname}: broken journal: %r", zone->origin, ret);
                logger_flush(); // broken journal (bad, keep me)
            }

            break;
        }
        
        ttlrdata.ttl = ntohl(rr.tctr.ttl);
        ttlrdata.rdata_pointer = rr.rdata;
        ttlrdata.rdata_size = rr.rdata_size;

        /*
         * Stop at the SOA
         */

        if(rr.tctr.qtype == TYPE_SOA)
        {
            mode ^= 1;

            if(mode == 0)
            {
                /* ADD */

#if ZDB_HAS_NSEC3_SUPPORT
                // NSEC3
                {
                    ret = nsec3replay.vtbl->execute(&nsec3replay);

                    if(FAIL(ret))
                    {
                        dns_resource_record_clear(&rr);
                        // DO NOT: input_stream_close(is);

                        nsec3replay.vtbl->finalise(&nsec3replay);
                        
#if ZDB_HAS_NSEC_SUPPORT
                        nsecreplay.vtbl->finalise(&nsecreplay);
#endif // ZDB_HAS_NSEC_SUPPORT
                        return ret;
                    }
                }
#endif
                
#if ZDB_HAS_NSEC_SUPPORT
                // NSEC
                ret = nsecreplay.vtbl->execute(&nsecreplay);
#endif //ZDB_HAS_NSEC_SUPPORT
            }
        }

        if(!did_remove_soa)
        {
            log_info("journal: %{dnsname}: removing obsolete SOA", zone->origin);

            if(FAIL(ret = zdb_record_delete(&zone->apex->resource_record_set, TYPE_SOA)))
            {
                /**
                * complain
                */

                log_err("journal: %{dnsname}: removing current SOA gave an error: %r", zone->origin, ret);

                /* That's VERY bad ... */

                changes = ret;

                break;
            }

            did_remove_soa = TRUE;
        }

        s32 top = dnsname_to_dnslabel_vector(fqdn, labels);

        if(mode == 0)
        {
            /*
             * "TO DEL" record
             */

#if ICMTL_DUMP_JOURNAL_RECORDS
            rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, rr.rdata };
            log_debug("journal: del %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata);
            logger_flush();
#endif
            bool added_in_chain = FALSE;

#if ZDB_HAS_NSEC3_SUPPORT
            
            // 0 : proceed
            // 1 : ignore
            // ? : error
            
            if((added_in_chain = (nsec3replay.vtbl->record_del(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0)))
            {
                // add everything up until a non-empty terminal is found (the apex will thus be automatically avoided)
                // if the record is a delegation, add everything down too
                /*
                if((top > zone->origin_vector.size) &&
                        (rr.tctr.qtype != TYPE_NSEC3) &&
                        (   (rr.tctr.qtype != TYPE_RRSIG) ||
                            ((rr.tctr.qtype == TYPE_RRSIG) && (GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(&ttlrdata)) != TYPE_NSEC3))
                        )
                    )
                {
                    
                }
                */
                ++changes;
            }
            else
            {
                if(top > zone->origin_vector.size)
                {
                    const u8 *above_fqdn = fqdn;
                    for(int i = 1; i < top - zone->origin_vector.size; ++i)
                    {
                        zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i);
                        if(above != NULL)
                        {
                            if(btree_notempty(above->resource_record_set))
                            {
                                break;
                            }
                        }

                        above_fqdn += above_fqdn[0] + 1;
                        nsec3replay.vtbl->record_del(&nsec3replay, above_fqdn, TYPE_NONE, NULL);
                    }

                    zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1);
                    if(rr_label != NULL)
                    {
                        zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_del_cb, &nsec3replay);
                    }
                }
            }
#endif
#if ZDB_HAS_NSEC_SUPPORT
            
            // 0 : proceed
            // 1 : ignore
            // ? : error
            
            if(!added_in_chain && (added_in_chain = nsecreplay.vtbl->record_del(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0))
            {
                ++changes;
            }
            //else
#endif
            if(!added_in_chain)
            switch(rr.tctr.qtype)
            {
                case TYPE_SOA:
                {
                    rdata_desc rdata = {TYPE_SOA, ttlrdata.rdata_size, ttlrdata.rdata_pointer};
                    log_info("journal: %{dnsname}: SOA: del %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata);

                    s32 m1 = (top - zone->origin_vector.size) - 1;

                    if(m1 == -1)
                    {
                        if(FAIL(ret = zdb_record_delete_exact(&zone->apex->resource_record_set, TYPE_SOA, &ttlrdata))) /* FB done, APEX : no delegation, source is the journal */
                        {
                            if(!did_remove_soa)
                            {
                                log_err("journal: %{dnsname}: SOA: %r", zone->origin, ret);
                            }
                        }
                    }
                    else
                    {
                        if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal
                        {
                            if(!did_remove_soa)
                            {
                                log_err("journal: %{dnsname}: SOA: (2) %r", zone->origin, ret);
                            }
                        }
                    }
                    break;
                }

                default:
                {
#if ZDB_HAS_NSEC3_SUPPORT
                    // NSEC3
                    if(rr.tctr.qtype != TYPE_NSEC3)
                    {
                        if((rr.tctr.qtype != TYPE_RRSIG) && (rrsig_get_type_covered_from_rdata(rr.rdata, rr.rdata_size) != TYPE_NSEC3))
                        {
                            if(ptr_set_avl_find(&downed_fqdn, fqdn) == NULL)
                            {
                                ptr_set_avl_insert(&downed_fqdn, dnsname_dup(fqdn));
                            }
                        }
                    }
                    else
                    {
                        if(!NSEC3_RDATA_IS_OPTOUT(rr.rdata))
                        {
                            zone->_flags &= ~ZDB_ZONE_HAS_OPTOUT_COVERAGE;
                        }
                    }
#endif
                    if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal
                    {
                        // signatures can be removed automatically by maintenance
                        
                        if((rr.tctr.qtype != TYPE_RRSIG) && (ret != ZDB_ERROR_KEY_NOTFOUND))
                        {
                            log_err("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr);
                            log_err("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret);
                        }
                        else
                        {
                            log_debug("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr);
                            log_debug("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret);
                        }
                    }
                }
            }
        }
        else
        {
            /*
             * "TO ADD" record
             */
            
            bool added_in_chain = FALSE;
            
#if ZDB_HAS_NSEC3_SUPPORT

            // returns the number of changes taken into account (0 or 1)
            // 0 : proceed
            // 1 : ignore
            // ? : error
            
            if((added_in_chain = (nsec3replay.vtbl->record_add(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0)))
            {
                ++changes;
            }
            else
            {
                if( (top > zone->origin_vector.size) &&
                    (rr.tctr.qtype != TYPE_NSEC3) &&
                    (   (rr.tctr.qtype != TYPE_RRSIG) ||
                        ((rr.tctr.qtype == TYPE_RRSIG) && (GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(&ttlrdata)) != TYPE_NSEC3))
                        )
                    )
                {
                    const u8 *above_fqdn = fqdn;
                    for(int i = 1; i < top - zone->origin_vector.size; ++i)
                    {
                        zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i);
                        if(above != NULL)
                        {
                            if(btree_notempty(above->resource_record_set))
                            {
                                break;
                            }
                        }

                        above_fqdn += above_fqdn[0] + 1;
                        nsec3replay.vtbl->record_add(&nsec3replay, above_fqdn, TYPE_NONE, NULL);
                    }

                    zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1);
                    if(rr_label != NULL)
                    {
                        zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_add_cb, &nsec3replay);
                    }
                }
            }
#endif
#if ZDB_HAS_NSEC_SUPPORT
            
            // returns the number of changes taken into account (0 or 1)
            // 0 : proceed
            // 1 : ignore
            // ? : error
            
            if(!added_in_chain && (added_in_chain = (nsecreplay.vtbl->record_add(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0)))
            {
                ++changes;
            }
            //else
#endif
            if(!added_in_chain)
            switch(rr.tctr.qtype)
            {
#if ZDB_HAS_NSEC3_SUPPORT
                case TYPE_NSEC3CHAINSTATE:
                {
                    // create chain if missing ...
                    
                    nsec3_zone_add_from_rdata(zone, rr.rdata_size, rr.rdata);
                    
                    // add the record
                    
                    zdb_packed_ttlrdata *packed_ttlrdata;

                    ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size);
                    packed_ttlrdata->next = NULL;
                    MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size);
                    zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified
                    
                    break;
                }
#endif // ZDB_HAS_NSEC3_SUPPORT
#
                default:
                {
                    zdb_packed_ttlrdata *packed_ttlrdata;

                    ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size);
                    packed_ttlrdata->next = NULL;
                    MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size);

#if ICMTL_DUMP_JOURNAL_RECORDS
                    rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata) };
                    log_debug("journal: add %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata);
                    logger_flush();
#endif
                    if(rr.tctr.qtype == TYPE_SOA)
                    {
                        rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), current_serialp);
                        rdata_desc rdata = {TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata)};
                        log_info("journal: %{dnsname}: SOA: add %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata);
                    }
                    
                    zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified
                }
            }            
        } // end if ADD

        changes++;
    }

    /*
     * Yes, I know.  If 2^32 changes (add batch + del batch) occurs then it will be seen as an error ...
     */

    if(ISOK(changes))
    {
#if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT
        
        if(has_nsec3 && has_nsec)
        {
            log_warn("journal: %{dnsname}: both NSEC3 and NSEC operations happened, which is not supported by YADIFA. Keeping the original one.", zone->origin);
            
            has_nsec3 = zdb_zone_is_nsec3(zone);
            has_nsec = zdb_zone_is_nsec(zone);
        }        
#endif
        
#if ZDB_HAS_NSEC3_SUPPORT
        nsec3replay.vtbl->execute(&nsec3replay);
#endif

#if ZDB_HAS_NSEC_SUPPORT
        nsecreplay.vtbl->execute(&nsecreplay);
#endif
    }
    
#if ZDB_HAS_NSEC3_SUPPORT
    // has_nsec3 = zdb_zone_is_nsec3(zone);
    nsec3replay.vtbl->finalise(&nsec3replay);
#endif
#if ZDB_HAS_NSEC_SUPPORT
    // has_nsec = zdb_zone_is_nsec(zone);
    nsecreplay.vtbl->finalise(&nsecreplay);
#endif
    
    dns_resource_record_clear(&rr);


    
    return changes;
}
Esempio n. 8
0
void
dnscore_finalize()
{
    /*
     * No need to "finalize" format, dnsformat and rfc
     */

    if(dnscore_finalizing)
    {
        /* OOPS : ALREADY BUSY SHUTTING DOWN */

        /* DO NOT USE LOGGER HERE ! */
        
        return;
    }

    dnscore_finalizing = TRUE;
    
    dnscore_shutdown();

#ifndef NDEBUG
    log_debug("exit: destroying the thread pool");
#endif
    
    logger_flush();

    thread_pool_destroy();
    
#ifdef DEBUG
    log_debug("exit: bye (pid=%hd)", getpid());
    
    logger_flush();
#endif
    
    scheduler_finalize();

    logger_flush();

    logger_finalize();  /** @note does a logger_stop */

    logger_handle_finalize();

#ifndef NDEBUG
    /*
     *  It may not be required right now, but in case the stdstream are filtered/buffered
     *  this will flush them.
     */

#if HAS_TSIG_SUPPORT
    tsig_finalize();
#endif

    stdstream_flush_both_terms();

    error_unregister_all();

    rfc_finalize();

    format_class_finalize();

#endif
    
#ifndef NDEBUG
#if ZDB_DEBUG_MALLOC != 0
    debug_stat(TRUE);
#endif
#endif

    stdstream_flush_both_terms();
    
    output_stream_close(&__termerr__);
    output_stream_close(&__termout__);
}
Esempio n. 9
0
ya_result
scheduler_do_next_job()
{
    /** @todo use the pool counters
     *	    _ Readers
     *	    _ Writers
     *	    _ Current Task : I can have a task that works bit by bit and continues until the last bit is done (RRSIG)
     */

    /* Dequeue a job */

    if(threaded_queue_size(&scheduler_queue) == 0)
    {
        return SCHEDULER_TASK_NOTHING;
    }

    scheduler_task *task = threaded_queue_dequeue(&scheduler_queue);

    /* Do (part) of the job */

    scheduler_task_callback *callback = task->task;
    void* args = task->args;
    free(task);

    ya_result return_code;

    switch(return_code = callback(args))
    {
        default:
            /* An error occurred */

            log_err("scheduler: unexpected callback return code %r", return_code);

        case SCHEDULER_TASK_FINISHED:

#ifndef NDEBUG
            log_debug("scheduler: task finished");
#endif
            /**
             * Retrieve and start the next thread
             * 
             * @todo EXCEPT IF A SHUTDOWN HAS BEEN REQUESTED ?
             */
            
        case SCHEDULER_TASK_DEQUEUE_DELAYED:
            
            if(dnscore_shuttingdown())
            {
                log_info("scheduler: shutdown in progress : ignoring next job");
                logger_flush();
                
                return STOPPED_BY_APPLICATION_SHUTDOWN;
            }

            pthread_mutex_lock(&scheduler_delayed_queue_mutex);

            scheduler_thread_running = FALSE;

            if(!scheduler_thread_queue_isempty(&scheduler_delayed_queue))
            {
                scheduler_thread* thread = scheduler_thread_queue_dequeue(&scheduler_delayed_queue);

#ifndef NDEBUG
                log_debug("scheduler: dequeued thread %s::(%p, %p, %p, %p@%u)", thread->categoryname, thread->task_init, thread->task, thread->args, thread, thread->debug_count);
                log_debug("scheduler: starting thread %u", thread->debug_count);

                log_debug("scheduler: next thread init");
#endif
                if(thread->task_init != NULL)
                {
                    thread->task_init(thread->args);
                }

#ifndef NDEBUG
                log_debug("scheduler: next thread ready");
#endif
                
                if(thread->task != NULL)
                {
#ifndef NDEBUG
                    log_debug("scheduler: next thread start");
#endif
                    scheduler_thread_running = TRUE;

                    thread_pool_schedule_job(thread->task, thread->args, &scheduler_threads_counter, thread->categoryname);
                }

                free(thread);
            }

            pthread_mutex_unlock(&scheduler_delayed_queue_mutex);

            break;

        case SCHEDULER_TASK_PROGRESS:
            /* NOP */
#ifndef NDEBUG
            log_debug("scheduler: task progress");
#endif
            break;
    }

    return return_code;
}
Esempio n. 10
0
File: signals.c Progetto: lye/yadifa
static void
signal_handler(int signo, siginfo_t* info, void* context)
{
    /*
    int status;
    int i;
    */

    /*    ------------------------------------------------------------    */

    switch(signo)
    {
    case SIGHUP:
    {
        signal_task_logger_handle_reopen_all();
        break;
    }
    case SIGUSR1:
    {
        /* write all (dirty) zones to disk */

        signal_task_database_save_all_zones_to_disk();

        break;
    }
    case SIGUSR2:
    {
        // Used to break a syscall (sync)
        break;
    }
    case SIGINT:
    case SIGTERM:
    {
        /*
         * We are shutting down : ignore other "command" signals
         */

        signal(SIGHUP, SIG_IGN);
        signal(SIGUSR1, SIG_IGN);
        signal(SIGINT, SIG_IGN);
        signal(SIGTERM, SIG_IGN);

        signal_task_shutdown();

        break;
    }
#if SIGNAL_HOOK_COREDUMP == 0
    case SIGBUS:
    case SIGFPE:
    case SIGILL:
    case SIGSEGV:
    {
        signal(signo, SIG_DFL);

        if(sigsegv_trytrace)
        {
            char filepath[1024];
            FILE *f;

            /* So if we crashed while trying to dump, we will not do it anymore */
            sigsegv_trytrace = FALSE;

            snprintf(filepath, sizeof(filepath), "%ssig%i.%i", config->log_path, signo, getpid());

            f = fopen(filepath, "a+");

            if(f == NULL)
            {
                snprintf(filepath, sizeof(filepath), "/tmp/yadifa.sig%i.%i", signo, getpid());

                f = fopen(filepath, "a+");
            }

            if(f != NULL)
            {

#if defined(__linux__)
                void* buffer[MAXTRACE];
                char** strings;
                int n = backtrace(buffer, MAXTRACE);
                int i;
                time_t now = time(NULL);

                fprintf(f, "Signal %i at time=%li for address %p\n", signo, now, info->si_addr);

                fflush(f);

                strings = backtrace_symbols(buffer, n);

                if(strings != NULL)
                {
                    for(i = 0; i < n; i++)
                    {
                        fprintf(f, "\t[%3i]: %s\n", i, strings[i]);
                    }
                }
                else
                {
                    fprintf(f, "No backtrace available (%s)\n", strerror(errno));
                }
                fflush(f);
                fprintf(f, "pid: %i\n", getpid());
                fprintf(f, "thread id: %d",  (u32)pthread_self());
#else
                fprintf(f, "Got signal %i.  No backtrace available\n", signo);
#endif
                fclose(f);
            }

            /**
             * Do NOT free(strings) :
             * If the memory is corrupted, this is one more chance to crash
             *
             */
        }

        /* There COULD be some relevant information in the logger */
        /* try to flush it */

        if(sigsegv_tryloggerflush)
        {
            sigsegv_tryloggerflush = FALSE;
            logger_flush();
            log_err("CRITICAL ERROR");
            logger_flush();
        }

        /* trigger the original signal (to dump a core if possible ) */

        raise(signo);

        /* should never be reached : Exit without disabling stuff (no atexit registered function called) */

        _exit(EXIT_CODE_SELFCHECK_ERROR);

        break;
    }
#endif

    /*
    case SIGUSR2:
    case SIGCHLD:
    */
    default:
    {
        break;
    }
    }
}