summaryrefslogtreecommitdiffstats
path: root/src/dnscap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dnscap.c')
-rw-r--r--src/dnscap.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/dnscap.c b/src/dnscap.c
new file mode 100644
index 0000000..56e1ac1
--- /dev/null
+++ b/src/dnscap.c
@@ -0,0 +1,249 @@
+/* dnscap - DNS capture utility
+ *
+ * By Paul Vixie (ISC) and Duane Wessels (Measurement Factory), 2007.
+ */
+
+/*
+ * Copyright (c) 2016-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "dnscap.h"
+#include "args.h"
+#include "bpft.h"
+#include "pcaps.h"
+#include "dumper.h"
+#include "daemon.h"
+#include "log.h"
+#include "sig.h"
+
+#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_CONF_H) && defined(HAVE_OPENSSL_ERR_H) && defined(HAVE_OPENSSL_EVP_H)
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#define INIT_OPENSSL 1
+#endif
+
+plugin_list plugins;
+const char* ProgramName = "amnesia";
+int dumptrace = 0;
+int flush = FALSE;
+vlan_list vlans_excl;
+vlan_list vlans_incl;
+unsigned msg_wanted = MSG_QUERY;
+unsigned dir_wanted = DIR_INITIATE | DIR_RESPONSE;
+unsigned end_hide = 0U;
+unsigned err_wanted = ERR_NO | ERR_YES; /* accept all by default */
+tcpstate_list tcpstates;
+int tcpstate_count = 0;
+endpoint_list initiators, not_initiators;
+endpoint_list responders, not_responders;
+endpoint_list drop_responders; /* drops only responses from these hosts */
+myregex_list myregexes;
+mypcap_list mypcaps;
+mypcap_ptr pcap_offline = NULL;
+const char* dump_base = NULL;
+char* dump_suffix = 0;
+char* extra_bpf = NULL;
+enum dump_type dump_type = nowhere;
+enum dump_state dump_state = dumper_closed;
+const char* kick_cmd = NULL;
+unsigned limit_seconds = 0U;
+time_t next_interval = 0;
+unsigned limit_packets = 0U;
+size_t limit_pcapfilesize = 0U;
+pcap_t* pcap_dead;
+pcap_dumper_t* dumper;
+time_t dumpstart;
+unsigned msgcount;
+size_t capturedbytes = 0;
+char * dumpname, *dumpnamepart;
+char* bpft;
+unsigned dns_port = DNS_PORT;
+int promisc = TRUE;
+int monitor_mode = FALSE;
+int immediate_mode = FALSE;
+int background = FALSE;
+char errbuf[PCAP_ERRBUF_SIZE];
+int wantgzip = 0;
+int wantfrags = FALSE;
+int wanticmp = FALSE;
+int wanttcp = FALSE;
+int preso = FALSE;
+#ifdef USE_SECCOMP
+int use_seccomp = FALSE;
+#endif
+int main_exit = FALSE;
+int alarm_set = FALSE;
+time_t start_time = 0;
+time_t stop_time = 0;
+int print_pcap_stats = FALSE;
+uint64_t pcap_drops = 0;
+my_bpftimeval last_ts = { 0, 0 };
+unsigned long long mem_limit = (unsigned)MEM_MAX; /* process memory limit */
+int mem_limit_set = 1; /* TODO: Should be configurable */
+const char DROPTOUSER[] = "nobody";
+pcap_thread_t pcap_thread = PCAP_THREAD_T_INIT;
+int only_offline_pcaps = FALSE;
+int dont_drop_privileges = FALSE;
+options_t options = OPTIONS_T_DEFAULTS;
+
+ldns_rr_type match_qtype = 0, nmatch_qtype = 0;
+
+int main(int argc, char* argv[])
+{
+ struct plugin* p;
+ struct timeval now;
+
+#ifdef INIT_OPENSSL
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ OPENSSL_config(0);
+#endif
+#endif
+
+ parse_args(argc, argv);
+ gettimeofday(&now, 0);
+ if (!only_offline_pcaps && start_time) {
+ if (now.tv_sec < start_time) {
+ char when[100];
+ struct tm tm;
+ gmtime_r(&start_time, &tm);
+ strftime(when, sizeof when, "%F %T", &tm);
+ fprintf(stderr, "Sleeping for %d seconds until %s UTC\n",
+ (int)(start_time - now.tv_sec), when);
+ sleep(start_time - now.tv_sec);
+ fprintf(stderr, "Awake.\n");
+ }
+ }
+ prepare_bpft();
+ open_pcaps();
+ if (dump_type == to_stdout) {
+ if (dumper_open(now)) {
+ fprintf(stderr, "%s: dumper_open() to stdout failed\n", ProgramName);
+ exit(1);
+ }
+ }
+ INIT_LIST(tcpstates);
+
+ if (!dont_drop_privileges && !only_offline_pcaps) {
+ drop_privileges();
+ }
+
+ for (p = HEAD(plugins); p != NULL; p = NEXT(p, link)) {
+ if (p->start)
+ if (0 != (*p->start)(logerr)) {
+ logerr("%s_start returned non-zero", p->name);
+ exit(1);
+ }
+ }
+ if (dump_type == nowhere)
+ dumpstart = time(NULL);
+ if (background)
+ daemonize();
+
+#if HAVE_PTHREAD
+ /*
+ * Defer signal setup until we have dropped privileges and daemonized,
+ * otherwise signals might not reach us because different threads
+ * are running under different users/access
+ */
+ {
+ sigset_t set;
+ int err;
+ pthread_t thread;
+
+ sigfillset(&set);
+ if ((err = pthread_sigmask(SIG_BLOCK, &set, 0))) {
+ logerr("pthread_sigmask: %s", strerror(err));
+ exit(1);
+ }
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGALRM);
+ sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGQUIT);
+
+ if ((err = pthread_create(&thread, 0, &sigthread, (void*)&set))) {
+ logerr("pthread_create: %s", strerror(err));
+ exit(1);
+ }
+ }
+#else
+ {
+ sigset_t set;
+
+ sigfillset(&set);
+ sigdelset(&set, SIGHUP);
+ sigdelset(&set, SIGINT);
+ sigdelset(&set, SIGALRM);
+ sigdelset(&set, SIGTERM);
+ sigdelset(&set, SIGQUIT);
+
+ if (sigprocmask(SIG_BLOCK, &set, 0)) {
+ logerr("sigprocmask: %s", strerror(errno));
+ exit(1);
+ }
+ }
+
+ setsig(SIGHUP, TRUE);
+ setsig(SIGINT, TRUE);
+ setsig(SIGALRM, FALSE);
+ setsig(SIGTERM, TRUE);
+ setsig(SIGQUIT, TRUE);
+#endif
+
+ while (!main_exit)
+ poll_pcaps();
+ /* close PCAPs after dumper_close() to have statistics still available during dumper_close() */
+ if (dumper_opened == dump_state)
+ (void)dumper_close(last_ts);
+ close_pcaps();
+ for (p = HEAD(plugins); p != NULL; p = NEXT(p, link)) {
+ if (p->stop)
+ (*p->stop)();
+ }
+ options_free(&options);
+
+#ifdef INIT_OPENSSL
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ ERR_free_strings();
+#endif
+
+ return 0;
+}