static void cleanup() { int rc; DB *db; DB_ENV *dbenv; rc = get_db(&db, 0); assert(! rc); rc = get_dbenv(&dbenv, 0); assert(! rc); if (dbkey.data) free(dbkey.data); if (db) call_db(db->close(db, 0), "DB close"); if (dbenv) { rc = call_db(db_create(&db, dbenv, 0), "db_create"); if (!rc) if (! db->remove(db, "tls_stats.db", 0, 0)) syslog(LOG_NOTICE, "Unused database tls_stats.db removed"); call_db(dbenv->txn_checkpoint(dbenv, 100 * 1024, 24 * 60, 0), "txn_checkpoint"); call_db(dbenv->log_archive(dbenv, NULL, DB_ARCH_REMOVE), "log_archive"); call_db(dbenv->close(dbenv, 0), "DB_ENV close"); } policy_cleanup(); }
/* Return the current Berkeley DB environment. If "force" is not zero then force creating the environment if it does not yet exist. Note that if "force" is zero then the function can not fail. */ static int get_dbenv(DB_ENV **dbenv_ret, int force) { static DB_ENV *dbenv = NULL; int rc = 0; if (dbenv == NULL && force) { rc = call_db(db_env_create(&dbenv, 0), "db_env_create"); if (!rc) { dbenv->set_errcall(dbenv, db_errcall_fcn); rc = call_db(dbenv->set_lk_detect(dbenv, DB_LOCK_YOUNGEST), "dbenv->set_lk_detect DB_LOCK_YOUNGEST, expired triplets will not be deleted"); if (!rc) deadlock_detect = 1; rc = call_db(dbenv->open(dbenv, db_home, #ifdef DB_REGISTER /* DB_REGISTER appears in Berkeley DB 4.4 [#11511] http://docs.oracle.com/cd/E17076_02/html/upgrading/changelog_4_4_16.html#idp51982816 */ DB_REGISTER | DB_RECOVER | #endif DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_CREATE, 0), "dbenv->open"); if (rc) { dbenv->close(dbenv, 0); dbenv = 0; } } } if (dbenv_ret) *dbenv_ret = dbenv; return rc; }
void uvm_ml_config_rsrc::process_bp_notification ( uvm_ml_resource_notify_action action, const char * item_scope, const char * item_name, unsigned int stream_size, uvm_ml_stream_t stream, uvm_ml_time_unit time_unit, double time_value, const char * cntxt ) { unsigned int data_size = stream_size - UVM_ML_BLOCK_SIZE; std::string str_val; uvm_object * obj_val; sc_dt::sc_bv_base bv_val((int) data_size); std::vector<unsigned> vec; uvm_ml_packer_int packer; bp_set_config = true; uvm_ml_stream_t stream_data = stream; uvm_ml_packed_obj& packed_obj = uvm_ml_utils::get_static_mlupo(); // ENTER_CO_SIMULATION_CONTEXT(); switch (stream[0]) { case UVM_ML_STREAM_STRING: stream_data++; uvm_ml_utils::fill_mlupo(packed_obj, data_size, stream_data); packer.set_from_uvm_ml_packed_obj(&packed_obj); packer >> str_val; call_db(action, cntxt, item_scope, item_name, str_val); break; case UVM_ML_STREAM_TYPED_OBJECT: uvm_ml_utils::fill_mlupo(packed_obj, stream_size, stream); packer.set_from_uvm_ml_packed_obj(&packed_obj); packer >> obj_val; call_db(action, cntxt, item_scope, item_name, obj_val); break; case UVM_ML_STREAM_RAW: stream_data++; uvm_ml_utils::fill_mlupo(packed_obj, data_size, stream_data); packer.set_from_uvm_ml_packed_obj(&packed_obj); packer >> bv_val; call_db(action, cntxt, item_scope, item_name, bv_val); break; default: break; }; //EXIT_CO_SIMULATION_CONTEXT(); } // process_bp_notification()
void uvm_ml_config_rsrc::process_bp_notification ( uvm_ml_resource_notify_action action, const char * item_scope, const char * item_name, unsigned int stream_size, uvm_ml_stream_t stream, uvm_ml_time_unit time_unit, double time_value, const char * cntxt ) { unsigned int data_size = stream_size - UVM_ML_BLOCK_SIZE; std::string str_val; uvm_object * obj_val; sc_dt::sc_bv_base bv_val((int) data_size); std::vector<unsigned> vec; uvm_ml_packer_int packer; bp_set_config = true; uvm_ml_stream_t stream_data = stream; uvm_ml_packed_obj& packed_obj = uvm_ml_utils::get_static_mlupo(); switch (stream[0]) { case UVM_ML_STREAM_STRING: stream_data++; uvm_ml_utils::fill_mlupo(packed_obj, data_size, stream_data); packer.set_from_uvm_ml_packed_obj(&packed_obj); packer >> str_val; call_db(action, cntxt, item_scope, item_name, str_val); break; case UVM_ML_STREAM_TYPED_OBJECT: { uvm_ml_utils::fill_mlupo(packed_obj, stream_size, stream); packer.set_from_uvm_ml_packed_obj(&packed_obj); if (packer.check_obj_header()) { // Else silently drop it (until tracing is not added) - probably not intended for SC packer >> obj_val; call_db(action, cntxt, item_scope, item_name, obj_val); } break; } case UVM_ML_STREAM_RAW: stream_data++; uvm_ml_utils::fill_mlupo(packed_obj, data_size, stream_data); packer.set_from_uvm_ml_packed_obj(&packed_obj); packer >> bv_val; call_db(action, cntxt, item_scope, item_name, bv_val); break; default: break; };
static int get_db(DB **db_ret, int force) { static DB *db = NULL; int rc = 0; if (db == NULL && force) { DB_ENV *dbenv; rc = get_dbenv(&dbenv, force); if (rc) return rc; rc = call_db(db_create(&db, dbenv, 0), "db_create"); if (!rc) { /* XXX do not use call_db: it is normal for this call to fail with ENOENT if the database has to be upgraded or created from scratch */ rc = db_open(db, DB_FILE_NAME, NULL, DB_BTREE, DB_AUTO_COMMIT, 0644); if (rc == ENOENT) { /* Try and upgrade from an old version */ rc = call_db(upgrade_from_v0(dbenv), "upgrade_from_v0"); if (!rc) rc = call_db(db_open(db, DB_FILE_NAME, NULL, DB_BTREE, DB_AUTO_COMMIT | DB_CREATE, 0644), "db->open 2"); } else if (rc) call_db(rc, "db->open"); if (rc) { db->close(db, 0); db = 0; } } } if (db_ret) *db_ret = db; return rc; }
static int process_smtp_rcpt(int crypted) { double delay; int rc; DB_ENV *dbenv; DB *db; DB_TXN *txn = NULL; if (setjmp(defect_jmp_buf)) { if (defect_msg) { printf(STR_ACTION "WARN %s\n", defect_msg); defect_msg = 0; } else puts(STR_ACTION "WARN " PACKAGE_STRING " is not working properly"); if (txn) call_db(txn->abort(txn), "Failed to abort transaction"); return 1; } rc = get_dbenv(&dbenv, 1); if (rc) jmperr("get_dbenv failed"); rc = get_db(&db, 1); if (rc) jmperr("get_db failed"); rc = call_db(dbenv->txn_begin(dbenv, NULL, &txn, 0), "txn_begin failed in process_smtp_rcpt"); if (rc) jmperr("txn_begin failed"); get_grey_data(db, txn); if (triplet_data.crypted != crypted) { triplet_data.crypted = crypted; if (debug_me) syslog(LOG_DEBUG,"crypted field changed for some reason"); } delay = difftime(triplet_data.access_time, triplet_data.create_time); /* Block inbound mail that is from a previously unknown (ip, from, to) triplet */ /* However we want different behavior for crypted stuff */ if(crypted > 0) { if(delay < cryptlist_delay) { triplet_data.block_count++; fputs(STR_ACTION, stdout); printf_action(reject_action_fmt, greylist_delay - delay); putchar('\n'); } else if (triplet_data.pass_count++) puts(STR_ACTION "DUNNO"); else { fputs(STR_ACTION, stdout); printf_action(cryptlisted_action_fmt, delay); putchar('\n'); } } else { if(delay < greylist_delay || block_unencrypted) { triplet_data.block_count++; fputs(STR_ACTION, stdout); if(block_unencrypted == 1) { printf_action(reject_unencrypted_action_fmt, (3600*24)); // block it for a day } else { printf_action(reject_unencrypted_action_fmt, greylist_delay - delay); } putchar('\n'); } else if (triplet_data.pass_count++) puts(STR_ACTION "DUNNO"); else { fputs(STR_ACTION, stdout); printf_action(greylisted_action_fmt, delay); putchar('\n'); } } rc = put_grey_data(db, txn); if (rc) call_db(txn->abort(txn), "abort failed"); else call_db(txn->commit(txn, 0), "commit failed"); return rc; }
static int put_grey_data(DB *db, DB_TXN *txn) { return call_db(db->put(db, txn, &dbkey, &dbdata, 0), "put"); }
/* Upgrade the database from v0 format to the new format */ static int upgrade_from_v0(DB_ENV *dbenv) { DB *db0 = NULL, *db1 = NULL; DB_TXN *tid = NULL; DBC *cursor = NULL; DBT key = { 0 }, data = { 0 }; int rc = call_db(dbenv->txn_begin(dbenv, NULL, &tid, 0), "upgrade_from_v0 dbenv->txn_begin"); if (!rc) rc = call_db(db_create(&db0, dbenv, 0), "upgrade_from_v0 db_create 0"); if (!rc) { /* XXX do not use call_db: it is normal for this call to fail, if there is no database to upgrade from. */ rc = db0->open(db0, tid, DB_FILE_NAME_V0, NULL, DB_UNKNOWN, 0, 0644); if (rc == ENOENT) { call_db(db0->close(db0, 0), "upgrade_from_v0 db0->close 0"); call_db(tid->commit(tid, 0), "upgrade_from_v0 tid->commit 0"); return 0; } } if (!rc) { syslog(LOG_WARNING, "Upgrading from database format v0"); rc = call_db(db_create(&db1, dbenv, 0), "upgrade_from_v0 db_create 1"); } if (!rc) rc = call_db(db1->open(db1, tid, DB_FILE_NAME, NULL, DB_BTREE, DB_CREATE | DB_EXCL, 0644), "upgrade_from_v0 db1->open"); if (!rc) rc = call_db(db0->cursor(db0, tid, &cursor, 0), "upgrade_from_v0 db0->cursor"); size_t buffer_size = 0; char *buffer = 0; while (!rc) { rc = cursor->get(cursor, &key, &data, DB_NEXT); if (rc == DB_NOTFOUND) { /* this is expected result, do commit this transaction */ rc = 0; break; } else if (rc) { call_db(rc, "upgrade_from_v0 cursor->get"); break; } /* Convert this entry to new format */ char *s, *ip, *from, *to; size_t iplen, fromlen, tolen; ip = key.data; iplen = strlen(ip); from = ip + iplen + 1; fromlen = strlen(from); to = from + fromlen + 1; tolen = key.size - fromlen - iplen - 2; int count = 0; for (s = strchr(ip, '.'); s != NULL; s = strchr(s + 1, '.')) count++; s = ensure_dbkey_reserve(MAX(MAX(sizeof(struct in_addr), sizeof(struct in6_addr)), iplen + 1) + fromlen + tolen + 2); if (count) { /* This is supposedly an IPv4 address. Complete it with trailing zeroes. A complete IPv4 address has 3 dots and 4 numbers. For each missing dot, add the dot and a 0. */ size_t needed = iplen + 2 * (3 - count) + 1; if (buffer_size < needed) { buffer = xrealloc(buffer, needed); buffer_size = needed; } strcpy(buffer, ip); while (count++ < 3) strcat(buffer, ".0"); *s++ = DBKEY_T_IP4; rc = inet_pton(AF_INET, buffer, s); s += sizeof(struct in_addr); if (rc == -1) rc = errno; else if (rc == 1) rc = 0; else rc = EINVAL; if (rc) break; /* error */ } else { /* Try it as an IPv6 address. v0 format did not abbreviate IPv6 addresses. */ *s++ = DBKEY_T_IP6; if (inet_pton(AF_INET6, ip, s) == 1) s += sizeof(struct in6_addr); else { /* Not IPv4 neither IPv6. Keep it in its raw form */ *s++ = DBKEY_T_RAW; strcpy(s, ip); s += iplen + 1; } } strcpy(s, from); s += fromlen + 1; memcpy(s, to, tolen); s += tolen; dbkey.size = s - (char*)dbkey.data; rc = call_db(db1->put(db1, tid, &dbkey, &data, DB_NOOVERWRITE), "upgrade_from_v0 db1->put"); } if (buffer != NULL) free(buffer); if (cursor != NULL) call_db(cursor->close(cursor), "upgrade_from_v0 cursor->close"); if (db1 != NULL) call_db(db1->close(db1, 0), "upgrade_from_v0 db1->close"); if (db0 != NULL) call_db(db0->close(db0, 0), "upgrade_from_v0 db0->close"); if (!rc) rc = call_db(dbenv->dbremove(dbenv, tid, DB_FILE_NAME_V0, NULL, 0), "upgrade_from_v0 dbenv->dbremove"); if (tid != NULL) { if (rc) call_db(tid->abort(tid), "upgrade_from_v0 tid->abort"); else call_db(tid->commit(tid, 0), "upgrade_from_v0 tid->commit"); } return rc; }
static void run_expiry() { DB_ENV *dbenv; DB *db; DB_TXN *txn; DBC *dbcp; int rc; time_t now; DBT key = { 0 }; unsigned int count = 0; if (exit_requested) return; /* Cursor operations can hold several locks and therefore deadlock so don't run expiry if deadlock detection does not work http://docs.oracle.com/cd/E17076_02/html/programmer_reference/lock_notxn.html */ rc = get_db(&db, 0); assert(! rc); if (db == 0 || deadlock_detect == 0) return; rc = get_dbenv(&dbenv, 0); assert(! rc && dbenv); if (time(&now) == (time_t)-1) { syslog(LOG_ERR, "time failed during run_expiry"); return; } muffle_error++; rc = dbenv->txn_begin(dbenv, NULL, &txn, DB_TXN_NOWAIT); if (rc) { if (rc == DB_LOCK_DEADLOCK) syslog(LOG_DEBUG, "skipping concurrent expiry avoids " "deadlocks and unnecessary work"); else log_db_error("txn_begin failed during run_expiry", rc); goto out; } #if DB_VERSION_MAJOR >= 5 call_db(txn->set_priority(txn, 50), "TXN->set_priority"); #endif rc = call_db(db->cursor(db, txn, &dbcp, 0), "db->cursor failed during expiry run"); if (rc) goto txn_fail; while ((rc = dbcp->c_get(dbcp, &key, &dbdata, DB_NEXT | DB_RMW)) == 0) { time_t ref_time; double age_max, age; if (triplet_data.pass_count) { ref_time = triplet_data.access_time; age_max = pass_max_idle; } else { ref_time = triplet_data.create_time; age_max = bloc_max_idle; } age = difftime(now, ref_time); if (age > age_max) { if (opt_verbose) { syslog(LOG_INFO, "Expiring %s %s after %.0f seconds idle", db_key_ntop(key.data), triplet_data.pass_count ? "pass" : "block", age); } rc = call_db(dbcp->c_del(dbcp, 0), "dbcp->c_del failed"); if (rc) goto cursor_fail; count++; } if (exit_requested) break; } if (rc && rc != DB_NOTFOUND) { if (rc == DB_LOCK_DEADLOCK) syslog(LOG_NOTICE, "Aborting concurrent expiry due to deadlock"); else log_db_error("dbcp->c_get failed", rc); goto cursor_fail; } if (call_db(dbcp->c_close(dbcp), "dbcp->c_close failed")) goto txn_fail; call_db(txn->commit(txn, 0), "commit failed in run_expiry"); if (count) syslog(LOG_NOTICE, "Expired %u triplets", count); goto out; cursor_fail: call_db(dbcp->c_close(dbcp), "dbcp->c_close failed"); txn_fail: call_db(txn->abort(txn), "failed to abort"); out: muffle_error--; return; }