GNUnet  0.19.4
gnunet-dns-monitor.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dns_service.h"
30 
34 static struct GNUNET_DNS_Handle *handle;
35 
39 static int inbound_only;
40 
44 static int outbound_only;
45 
49 static int ret;
50 
54 static unsigned int verbosity;
55 
56 
63 static const char *
64 get_type (uint16_t type)
65 {
66  static char buf[6];
67 
68  switch (type)
69  {
70  case GNUNET_DNSPARSER_TYPE_A: return "A";
71 
72  case GNUNET_DNSPARSER_TYPE_NS: return "NS";
73 
74  case GNUNET_DNSPARSER_TYPE_CNAME: return "CNAME";
75 
76  case GNUNET_DNSPARSER_TYPE_SOA: return "SOA";
77 
78  case GNUNET_DNSPARSER_TYPE_PTR: return "PTR";
79 
80  case GNUNET_DNSPARSER_TYPE_MX: return "MX";
81 
82  case GNUNET_DNSPARSER_TYPE_TXT: return "TXT";
83 
84  case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA";
85 
86  case GNUNET_DNSPARSER_TYPE_SRV: return "SRV";
87  }
88  GNUNET_snprintf (buf, sizeof(buf), "%u", (unsigned int) type);
89  return buf;
90 }
91 
92 
99 static const char *
100 get_class (uint16_t class)
101 {
102  static char buf[6];
103 
104  switch (class)
105  {
106  case GNUNET_TUN_DNS_CLASS_INTERNET: return "IN";
107 
108  case GNUNET_TUN_DNS_CLASS_CHAOS: return "CHAOS";
109 
110  case GNUNET_TUN_DNS_CLASS_HESIOD: return "HESIOD";
111  }
112  GNUNET_snprintf (buf, sizeof(buf), "%u", (unsigned int) class);
113  return buf;
114 }
115 
116 
122 static void
124 {
125  fprintf (stdout,
126  "\t\t%s %s: %s\n",
127  get_class (query->dns_traffic_class),
128  get_type (query->type),
129  query->name);
130 }
131 
132 
138 static void
140 {
141  const char *format;
142  char buf[INET6_ADDRSTRLEN];
143  char *tmp;
144 
145  tmp = NULL;
146  switch (record->type)
147  {
149  if (record->data.raw.data_len != sizeof(struct in_addr))
150  format = "<invalid>";
151  else
152  format = inet_ntop (AF_INET, record->data.raw.data, buf, sizeof(buf));
153  break;
154 
156  if (record->data.raw.data_len != sizeof(struct in6_addr))
157  format = "<invalid>";
158  else
159  format = inet_ntop (AF_INET6, record->data.raw.data, buf, sizeof(buf));
160  break;
161 
165  format = record->data.hostname;
166  break;
167 
169  if (NULL == record->data.soa)
170  format = "<invalid>";
171  else
172  {
173  GNUNET_asprintf (&tmp,
174  "origin: %s, mail: %s, serial = %u, refresh = %u s, retry = %u s, expire = %u s, minimum = %u s",
175  record->data.soa->mname,
176  record->data.soa->rname,
177  (unsigned int) record->data.soa->serial,
178  (unsigned int) record->data.soa->refresh,
179  (unsigned int) record->data.soa->retry,
180  (unsigned int) record->data.soa->expire,
181  (unsigned int) record->data.soa->minimum_ttl);
182  format = tmp;
183  }
184  break;
185 
187  if (record->data.mx == NULL)
188  format = "<invalid>";
189  else
190  {
191  GNUNET_asprintf (&tmp,
192  "%u: %s",
193  record->data.mx->preference,
194  record->data.mx->mxhost);
195  format = tmp;
196  }
197  break;
198 
200  if (NULL == record->data.srv)
201  format = "<invalid>";
202  else
203  {
204  GNUNET_asprintf (&tmp,
205  "priority %u, weight = %u, port = %u, target = %s",
206  (unsigned int) record->data.srv->priority,
207  (unsigned int) record->data.srv->weight,
208  (unsigned int) record->data.srv->port,
209  record->data.srv->target);
210  format = tmp;
211  }
212  break;
213 
215  GNUNET_asprintf (&tmp,
216  "%.*s",
217  (unsigned int) record->data.raw.data_len,
218  (char*) record->data.raw.data);
219  format = tmp;
220  break;
221 
222  default:
223  format = "<payload>";
224  break;
225  }
226  fprintf (stdout,
227  "\t\t%s %s: %s = %s (%u s)\n",
228  get_class (record->dns_traffic_class),
229  get_type (record->type),
230  record->name,
231  format,
232  (unsigned int) (GNUNET_TIME_absolute_get_remaining (
233  record->expiration_time).rel_value_us / 1000LL
234  / 1000LL));
235  GNUNET_free (tmp);
236 }
237 
238 
262 static void
263 display_request (void *cls,
265  size_t request_length,
266  const char *request)
267 {
268  static const char *return_codes[] = {
269  "No error", "Format error", "Server failure", "Name error",
270  "Not implemented", "Refused", "YXDomain", "YXRRset",
271  "NXRRset", "NOT AUTH", "NOT ZONE", "<invalid>",
272  "<invalid>", "<invalid>", "<invalid>", "<invalid>"
273  };
274  static const char *op_codes[] = {
275  "Query", "Inverse query", "Status", "<invalid>",
276  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
277  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
278  "<invalid>", "<invalid>", "<invalid>", "<invalid>"
279  };
280  struct GNUNET_DNSPARSER_Packet *p;
281  unsigned int i;
282 
283  p = GNUNET_DNSPARSER_parse (request, request_length);
284  if (NULL == p)
285  {
286  fprintf (stderr, "Received malformed DNS packet!\n");
287  // FIXME: drop instead?
289  return;
290  }
291  fprintf (stdout,
292  "%s with ID: %5u Flags: %s%s%s%s%s%s, Return Code: %s, Opcode: %s\n",
293  p->flags.query_or_response ? "Response" : "Query",
294  p->id,
295  p->flags.recursion_desired ? "RD " : "",
296  p->flags.message_truncated ? "MT " : "",
297  p->flags.authoritative_answer ? "AA " : "",
298  p->flags.checking_disabled ? "CD " : "",
299  p->flags.authenticated_data ? "AD " : "",
300  p->flags.recursion_available ? "RA " : "",
301  return_codes[p->flags.return_code & 15],
302  op_codes[p->flags.opcode & 15]);
303  if (p->num_queries > 0)
304  fprintf (stdout,
305  "\tQueries:\n");
306  for (i = 0; i < p->num_queries; i++)
307  display_query (&p->queries[i]);
308 
309  if (p->num_answers > 0)
310  fprintf (stdout,
311  "\tAnswers:\n");
312  for (i = 0; i < p->num_answers; i++)
313  display_record (&p->answers[i]);
314  fprintf (stdout, "\n");
317 }
318 
319 
323 static void
324 do_disconnect (void *cls)
325 {
326  if (NULL != handle)
327  {
329  handle = NULL;
330  }
331 }
332 
333 
342 static void
343 run (void *cls, char *const *args, const char *cfgfile,
344  const struct GNUNET_CONFIGURATION_Handle *cfg)
345 {
346  enum GNUNET_DNS_Flags flags;
347 
350  flags = 0;
351  if (inbound_only)
353  if (outbound_only)
355  handle =
357  flags,
359  NULL);
361 }
362 
363 
364 int
365 main (int argc, char *const *argv)
366 {
369  "inbound-only",
370  gettext_noop ("only monitor DNS queries"),
371  &inbound_only),
372 
374  "outbound-only",
375  gettext_noop ("only monitor DNS queries"),
376  &outbound_only),
377 
380  };
381 
382  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
383  return 2;
384  ret = (GNUNET_OK ==
385  GNUNET_PROGRAM_run (argc, argv, "gnunet-dns-monitor",
387  ("Monitor DNS queries."), options,
388  &run, NULL)) ? ret : 1;
389  GNUNET_free_nz ((void *) argv);
390  return ret;
391 }
392 
393 
394 /* end of gnunet-dns-monitor.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define gettext_noop(String)
Definition: gettext.h:70
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static void do_disconnect(void *cls)
Shutdown.
static const char * get_type(uint16_t type)
Convert numeric DNS record type to a string.
static unsigned int verbosity
Selected level of verbosity.
static void display_record(const struct GNUNET_DNSPARSER_Record *record)
Output the given DNS record to stdout.
static const char * get_class(uint16_t class)
Convert numeric DNS record class to a string.
static void display_query(const struct GNUNET_DNSPARSER_Query *query)
Output the given DNS query to stdout.
static int ret
Global return value (0 success).
static int inbound_only
Option -i.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main function that will be run by the scheduler.
static int outbound_only
Option -o.
int main(int argc, char *const *argv)
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
static void display_request(void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request)
Signature of a function that is called whenever the DNS service encounters a DNS request and needs to...
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
API to access the DNS service.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_DNSPARSER_TYPE_PTR
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
Definition: dnsparser.c:656
#define GNUNET_DNSPARSER_TYPE_NS
#define GNUNET_DNSPARSER_TYPE_CNAME
#define GNUNET_DNSPARSER_TYPE_AAAA
#define GNUNET_DNSPARSER_TYPE_MX
#define GNUNET_DNSPARSER_TYPE_TXT
struct GNUNET_DNS_Handle * GNUNET_DNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_DNS_Flags flags, GNUNET_DNS_RequestHandler rh, void *rh_cls)
Connect to the service-dns.
Definition: dns_api.c:340
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:363
void GNUNET_DNS_request_forward(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the request is given to other clients or the glob...
Definition: dns_api.c:237
GNUNET_DNS_Flags
Flags that specify when to call the client's handler.
@ GNUNET_DNS_FLAG_RESPONSE_MONITOR
Set this flag to see all requests just before they are returned to the network.
@ GNUNET_DNS_FLAG_REQUEST_MONITOR
Set this flag to see all requests first prior to resolution (for monitoring).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_verbose(unsigned int *level)
Define the '-V' verbosity option.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
@ GNUNET_OK
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1334
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1222
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
#define GNUNET_TUN_DNS_CLASS_HESIOD
#define GNUNET_TUN_DNS_CLASS_CHAOS
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we'r...
Easy-to-process, parsed version of a DNS packet.
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
A DNS response record.
DNS handle.
Definition: dns_api.c:57
GNUNET_DNS_RequestHandler rh
Function to call to get replies.
Definition: dns_api.c:71
Handle to identify an individual DNS request.
Definition: dns_api.c:35
Definition of a command line option.
uint64_t rel_value_us
The actual value.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model