// The MIT License (MIT) // Copyright (c) 2018 Yun-Chih Chen // Copyright (c) 2013 Florian Richter (nflogtable) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #include "collect.h" #include "sql.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include const char *help_text = "Usage: " PACKAGE " [OPTION]\n" "\n" "Options:\n" " -c --compression= compression algorithm to use (default: no " "compression)\n" " -d --storage= sqlite database storage file\n" " -h --help print this help\n" " -g --nflog_group= the group id to collect\n" " -s --storage_size= maximum DB size in MiB\n" " -V --vacuum vacuum the database on startup\n" " -v --version print version information\n" "\n"; static Netlink netlink_fd; static void sig_handler(int signo) { if (signo == SIGHUP) { puts("Terminated due to SIGHUP ..."); collect_close_netlink(&netlink_fd); } } int main(int argc, char *argv[]) { uint32_t storage_size = 0; Global g; int nflog_group_id = -1; char *compression_flag = NULL, *storage = NULL; bool do_vacuum = false; struct option longopts[] = {/* name, has_args, flag, val */ {"nflog_group", required_argument, NULL, 'g'}, {"storage", required_argument, NULL, 'd'}, {"storage_size", required_argument, NULL, 's'}, {"compression", optional_argument, NULL, 'z'}, {"vacuum", optional_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {0, 0, 0, 0}}; int opt; while ((opt = getopt_long(argc, argv, "c:g:d:s:hVvp:", longopts, NULL)) != -1) { switch (opt) { case 'h': printf("%s", help_text); exit(0); break; case 'v': printf("%s %s", PACKAGE, VERSION); exit(0); break; case 'c': compression_flag = optarg; break; case 'd': storage = strdup(optarg); break; case 'g': nflog_group_id = atoi(optarg); break; case 's': storage_size = atoi(optarg); break; case 'V': do_vacuum = true; break; case '?': fprintf(stderr, "Unknown argument, see --help\n"); exit(1); } } // verify arguments ASSERT(nflog_group_id != -1, "You must provide a nflog group (see --help)!\n"); ASSERT(storage != NULL, "You must provide a storage file (see --help)\n"); ASSERT(storage_size != 0, "You must provide the desired size of log file " "(in MiB) (see --help)\n"); g.compression_type = get_compression(compression_flag); if (check_basedir_exist(storage) < 0) FATAL("Storage directory: %s does not exist", storage); // register signal handler if (signal(SIGHUP, sig_handler) == SIG_ERR) ERROR("Could not set SIGHUP handler"); // Vacuum and get current space consumption if (do_vacuum && check_file_exist(storage)) { INFO(PACKAGE ": vacuum database on startup"); sqlite3 *db = NULL; db_open(&db, storage); db_vacuum(db); db_close(db); } pthread_mutex_init(&g.storage_consumed_lock, NULL); g.storage_budget = storage_size * 1024 * 1024; // MB g.storage_consumed = check_file_size(storage); g.storage_file = (const char *)storage; g.max_nr_entries = g_max_nr_entries_default; collect_open_netlink(&netlink_fd, nflog_group_id); pthread_t worker; State *state; INFO(PACKAGE ": storing in file '%s' (current size: %.2f MB), capped by %d MiB", g.storage_file, (float)g.storage_consumed / 1024.0 / 1024.0, storage_size); INFO(PACKAGE ": workers started, entries per block = %d", g.max_nr_entries); while (true) { state_init(&state, &netlink_fd, &g); pthread_create(&worker, NULL, collect_worker, (void *)state); pthread_join(worker, NULL); } collect_close_netlink(&netlink_fd); }