1 /* dnscap - DNS capture utility
2  *
3  * By Paul Vixie (ISC) and Duane Wessels (Measurement Factory), 2007.
4  */
5 
6 /*
7  * Copyright (c) 2016-2021, OARC, Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in
19  *    the documentation and/or other materials provided with the
20  *    distribution.
21  *
22  * 3. Neither the name of the copyright holder nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include "config.h"
41 
42 #include "dnscap.h"
43 #include "args.h"
44 #include "bpft.h"
45 #include "pcaps.h"
46 #include "dumper.h"
47 #include "daemon.h"
48 #include "log.h"
49 #include "sig.h"
50 
51 #if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_CONF_H) && defined(HAVE_OPENSSL_ERR_H) && defined(HAVE_OPENSSL_EVP_H)
52 #include <openssl/conf.h>
53 #include <openssl/evp.h>
54 #include <openssl/err.h>
55 #define INIT_OPENSSL 1
56 #endif
57 
58 plugin_list     plugins;
59 const char*     ProgramName = "amnesia";
60 int             dumptrace   = 0;
61 int             flush       = FALSE;
62 vlan_list       vlans_excl;
63 vlan_list       vlans_incl;
64 unsigned        msg_wanted = MSG_QUERY;
65 unsigned        dir_wanted = DIR_INITIATE | DIR_RESPONSE;
66 unsigned        end_hide   = 0U;
67 unsigned        err_wanted = ERR_NO | ERR_YES; /* accept all by default */
68 tcpstate_list   tcpstates;
69 int             tcpstate_count = 0;
70 endpoint_list   initiators, not_initiators;
71 endpoint_list   responders, not_responders;
72 endpoint_list   drop_responders; /* drops only responses from these hosts */
73 myregex_list    myregexes;
74 mypcap_list     mypcaps;
75 mypcap_ptr      pcap_offline       = NULL;
76 const char*     dump_base          = NULL;
77 char*           dump_suffix        = 0;
78 char*           extra_bpf          = NULL;
79 enum dump_type  dump_type          = nowhere;
80 enum dump_state dump_state         = dumper_closed;
81 const char*     kick_cmd           = NULL;
82 unsigned        limit_seconds      = 0U;
83 time_t          next_interval      = 0;
84 unsigned        limit_packets      = 0U;
85 size_t          limit_pcapfilesize = 0U;
86 pcap_t*         pcap_dead;
87 pcap_dumper_t*  dumper;
88 time_t          dumpstart;
89 unsigned        msgcount;
90 size_t          capturedbytes = 0;
91 char *          dumpname, *dumpnamepart;
92 char*           bpft;
93 unsigned        dns_port       = DNS_PORT;
94 int             promisc        = TRUE;
95 int             monitor_mode   = FALSE;
96 int             immediate_mode = FALSE;
97 int             background     = FALSE;
98 char            errbuf[PCAP_ERRBUF_SIZE];
99 int             wantgzip  = 0;
100 int             wantfrags = FALSE;
101 int             wanticmp  = FALSE;
102 int             wanttcp   = FALSE;
103 int             preso     = FALSE;
104 #ifdef USE_SECCOMP
105 int use_seccomp = FALSE;
106 #endif
107 int                main_exit            = FALSE;
108 int                alarm_set            = FALSE;
109 time_t             start_time           = 0;
110 time_t             stop_time            = 0;
111 int                print_pcap_stats     = FALSE;
112 uint64_t           pcap_drops           = 0;
113 my_bpftimeval      last_ts              = { 0, 0 };
114 unsigned long long mem_limit            = (unsigned)MEM_MAX; /* process memory limit */
115 int                mem_limit_set        = 1; /* TODO: Should be configurable */
116 const char         DROPTOUSER[]         = "nobody";
117 pcap_thread_t      pcap_thread          = PCAP_THREAD_T_INIT;
118 int                only_offline_pcaps   = FALSE;
119 int                dont_drop_privileges = FALSE;
120 options_t          options              = OPTIONS_T_DEFAULTS;
121 
122 ldns_rr_type match_qtype = 0, nmatch_qtype = 0;
123 
main(int argc,char * argv[])124 int main(int argc, char* argv[])
125 {
126     struct plugin* p;
127     struct timeval now;
128 
129 #ifdef INIT_OPENSSL
130     ERR_load_crypto_strings();
131     OpenSSL_add_all_algorithms();
132 #if OPENSSL_VERSION_NUMBER < 0x10100000L
133     OPENSSL_config(0);
134 #endif
135 #endif
136 
137     parse_args(argc, argv);
138     gettimeofday(&now, 0);
139     if (!only_offline_pcaps && start_time) {
140         if (now.tv_sec < start_time) {
141             char      when[100];
142             struct tm tm;
143             gmtime_r(&start_time, &tm);
144             strftime(when, sizeof when, "%F %T", &tm);
145             fprintf(stderr, "Sleeping for %d seconds until %s UTC\n",
146                 (int)(start_time - now.tv_sec), when);
147             sleep(start_time - now.tv_sec);
148             fprintf(stderr, "Awake.\n");
149         }
150     }
151     prepare_bpft();
152     open_pcaps();
153     if (dump_type == to_stdout) {
154         if (dumper_open(now)) {
155             fprintf(stderr, "%s: dumper_open() to stdout failed\n", ProgramName);
156             exit(1);
157         }
158     }
159     INIT_LIST(tcpstates);
160 
161     if (!dont_drop_privileges && !only_offline_pcaps) {
162         drop_privileges();
163     }
164 
165     for (p = HEAD(plugins); p != NULL; p = NEXT(p, link)) {
166         if (p->start)
167             if (0 != (*p->start)(logerr)) {
168                 logerr("%s_start returned non-zero", p->name);
169                 exit(1);
170             }
171     }
172     if (dump_type == nowhere)
173         dumpstart = time(NULL);
174     if (background)
175         daemonize();
176 
177 #if HAVE_PTHREAD
178     /*
179      * Defer signal setup until we have dropped privileges and daemonized,
180      * otherwise signals might not reach us because different threads
181      * are running under different users/access
182      */
183     {
184         sigset_t  set;
185         int       err;
186         pthread_t thread;
187 
188         sigfillset(&set);
189         if ((err = pthread_sigmask(SIG_BLOCK, &set, 0))) {
190             logerr("pthread_sigmask: %s", strerror(err));
191             exit(1);
192         }
193 
194         sigemptyset(&set);
195         sigaddset(&set, SIGHUP);
196         sigaddset(&set, SIGINT);
197         sigaddset(&set, SIGALRM);
198         sigaddset(&set, SIGTERM);
199         sigaddset(&set, SIGQUIT);
200 
201         if ((err = pthread_create(&thread, 0, &sigthread, (void*)&set))) {
202             logerr("pthread_create: %s", strerror(err));
203             exit(1);
204         }
205     }
206 #else
207     {
208         sigset_t set;
209 
210         sigfillset(&set);
211         sigdelset(&set, SIGHUP);
212         sigdelset(&set, SIGINT);
213         sigdelset(&set, SIGALRM);
214         sigdelset(&set, SIGTERM);
215         sigdelset(&set, SIGQUIT);
216 
217         if (sigprocmask(SIG_BLOCK, &set, 0)) {
218             logerr("sigprocmask: %s", strerror(errno));
219             exit(1);
220         }
221     }
222 
223     setsig(SIGHUP, TRUE);
224     setsig(SIGINT, TRUE);
225     setsig(SIGALRM, FALSE);
226     setsig(SIGTERM, TRUE);
227     setsig(SIGQUIT, TRUE);
228 #endif
229 
230     while (!main_exit)
231         poll_pcaps();
232     /* close PCAPs after dumper_close() to have statistics still available during dumper_close() */
233     if (dumper_opened == dump_state)
234         (void)dumper_close(last_ts);
235     close_pcaps();
236     for (p = HEAD(plugins); p != NULL; p = NEXT(p, link)) {
237         if (p->stop)
238             (*p->stop)();
239     }
240     options_free(&options);
241 
242 #ifdef INIT_OPENSSL
243     EVP_cleanup();
244     CRYPTO_cleanup_all_ex_data();
245     ERR_free_strings();
246 #endif
247 
248     return 0;
249 }
250