#include #include #include #include "conf.h" #include "coredump.h" #include "logdump.h" #include "net.h" static bool is_all_zero(u8 *buf, size_t size) { for (; size > 0; size--, buf++) { if (*buf) { return false; } } return true; } static int avm_coredump(struct notifier_block *this, unsigned long event, void *ptr) { #define CHECK_FIELD(field, msg) if (is_all_zero((void*)&conf->field, sizeof(conf->field))) { pr_err(LOG_PREFIX msg); return NOTIFY_OK; } if (conf->crashed) { return NOTIFY_OK; } conf->crashed = 1; CHECK_FIELD(family, "no family set. Abort..."); CHECK_FIELD(target_ip, "no target ip set. Abort..."); CHECK_FIELD(target_mac, "no target mac set. Abort..."); CHECK_FIELD(source_ip, "no source ip set. Abort..."); CHECK_FIELD(source_mac, "no source mac set. Abort..."); CHECK_FIELD(source_port, "no source port set. Abort..."); avm_coredump_net_setup(); #if IS_MODULE(CONFIG_AVM_COREDUMP) if (conf->coredump_port != 0) { avm_coredump_coredump_do(); } #endif if (conf->logdump_port != 0) { avm_coredump_logdump_do(); } avm_coredump_net_teardown(); #undef CHECK_FIELD return NOTIFY_OK; } static struct notifier_block panic_block = { .notifier_call = avm_coredump, .priority = 1, }; static int avm_coredump_init(void) { int ret; conf = kzalloc(sizeof(struct avm_coredump_conf), GFP_KERNEL); if (conf == NULL) { pr_err(LOG_PREFIX "Could not allocate avm_coredump_conf"); return -ENOMEM; } ret = avm_coredump_conf_init(); if (ret != 0) { goto fail; } #if IS_MODULE(CONFIG_AVM_COREDUMP) ret = avm_coredump_coredump_init(); if (ret != 0) { goto fail; } #endif ret = avm_coredump_logdump_init(); if (ret != 0) { goto fail; } ret = avm_coredump_net_init(); if (ret != 0) { goto fail; } atomic_notifier_chain_register(&panic_notifier_list, &panic_block); #if IS_MODULE(CONFIG_AVM_COREDUMP) pr_err(LOG_PREFIX "Module loaded with support for coredump and logdump.\n"); #else pr_err(LOG_PREFIX "Builtin module with support for logdump.\n"); #endif return ret; fail: pr_err(LOG_PREFIX "Module loading failed: %d\n", ret); return ret; } static void avm_coredump_exit(void) { atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); avm_coredump_coredump_exit(); avm_coredump_net_exit(); avm_coredump_conf_exit(); kfree(conf); conf = NULL; pr_info(LOG_PREFIX "Module unloaded.\n"); } #if IS_BUILTIN(CONFIG_AVM_COREDUMP) pure_initcall(avm_coredump_init); #else module_init(avm_coredump_init); #endif module_exit(avm_coredump_exit); MODULE_AUTHOR("AVM GmbH"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AVM CoreDump over network");