GNUnet  0.10.x
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 #include "gnunet_dnsparser_lib.h"
31 
35 static struct GNUNET_DNS_Handle *handle;
36 
40 static int inbound_only;
41 
45 static int outbound_only;
46 
50 static int ret;
51 
55 static unsigned int verbosity;
56 
57 
64 static const char *
65 get_type (uint16_t type)
66 {
67  static char buf[6];
68  switch (type)
69  {
70  case GNUNET_DNSPARSER_TYPE_A: return "A";
71  case GNUNET_DNSPARSER_TYPE_NS: return "NS";
72  case GNUNET_DNSPARSER_TYPE_CNAME: return "CNAME";
73  case GNUNET_DNSPARSER_TYPE_SOA: return "SOA";
74  case GNUNET_DNSPARSER_TYPE_PTR: return "PTR";
75  case GNUNET_DNSPARSER_TYPE_MX: return "MX";
76  case GNUNET_DNSPARSER_TYPE_TXT: return "TXT";
77  case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA";
78  case GNUNET_DNSPARSER_TYPE_SRV: return "SRV";
79  }
80  GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) type);
81  return buf;
82 }
83 
84 
91 static const char *
92 get_class (uint16_t class)
93 {
94  static char buf[6];
95  switch (class)
96  {
97  case GNUNET_TUN_DNS_CLASS_INTERNET: return "IN";
98  case GNUNET_TUN_DNS_CLASS_CHAOS: return "CHAOS";
99  case GNUNET_TUN_DNS_CLASS_HESIOD: return "HESIOD";
100  }
101  GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) class);
102  return buf;
103 }
104 
105 
111 static void
113 {
114  fprintf (stdout,
115  "\t\t%s %s: %s\n",
116  get_class (query->dns_traffic_class),
117  get_type (query->type),
118  query->name);
119 }
120 
121 
127 static void
129 {
130  const char *format;
131  char buf[INET6_ADDRSTRLEN];
132  char *tmp;
133 
134  tmp = NULL;
135  switch (record->type)
136  {
138  if (record->data.raw.data_len != sizeof (struct in_addr))
139  format = "<invalid>";
140  else
141  format = inet_ntop (AF_INET, record->data.raw.data, buf, sizeof (buf));
142  break;
144  if (record->data.raw.data_len != sizeof (struct in6_addr))
145  format = "<invalid>";
146  else
147  format = inet_ntop (AF_INET6, record->data.raw.data, buf, sizeof (buf));
148  break;
152  format = record->data.hostname;
153  break;
155  if (NULL == record->data.soa)
156  format = "<invalid>";
157  else
158  {
159  GNUNET_asprintf (&tmp,
160  "origin: %s, mail: %s, serial = %u, refresh = %u s, retry = %u s, expire = %u s, minimum = %u s",
161  record->data.soa->mname,
162  record->data.soa->rname,
163  (unsigned int) record->data.soa->serial,
164  (unsigned int) record->data.soa->refresh,
165  (unsigned int) record->data.soa->retry,
166  (unsigned int) record->data.soa->expire,
167  (unsigned int) record->data.soa->minimum_ttl);
168  format = tmp;
169  }
170  break;
172  if (record->data.mx == NULL)
173  format = "<invalid>";
174  else
175  {
176  GNUNET_asprintf (&tmp,
177  "%u: %s",
178  record->data.mx->preference,
179  record->data.mx->mxhost);
180  format = tmp;
181  }
182  break;
184  if (NULL == record->data.srv)
185  format = "<invalid>";
186  else
187  {
188  GNUNET_asprintf (&tmp,
189  "priority %u, weight = %s, port = %u, target = %s",
190  (unsigned int) record->data.srv->priority,
191  (unsigned int) record->data.srv->weight,
192  (unsigned int) record->data.srv->port,
193  record->data.srv->target);
194  format = tmp;
195  }
196  break;
198  GNUNET_asprintf (&tmp,
199  "%.*s",
200  (unsigned int) record->data.raw.data_len,
201  record->data.raw.data);
202  format = tmp;
203  break;
204  default:
205  format = "<payload>";
206  break;
207  }
208  fprintf (stdout,
209  "\t\t%s %s: %s = %s (%u s)\n",
210  get_class (record->dns_traffic_class),
211  get_type (record->type),
212  record->name,
213  format,
214  (unsigned int) (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL));
215  GNUNET_free_non_null (tmp);
216 }
217 
218 
242 static void
243 display_request (void *cls,
245  size_t request_length,
246  const char *request)
247 {
248  static const char *return_codes[] =
249  {
250  "No error", "Format error", "Server failure", "Name error",
251  "Not implemented", "Refused", "YXDomain", "YXRRset",
252  "NXRRset", "NOT AUTH", "NOT ZONE", "<invalid>",
253  "<invalid>", "<invalid>", "<invalid>", "<invalid>"
254  };
255  static const char *op_codes[] =
256  {
257  "Query", "Inverse query", "Status", "<invalid>",
258  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
259  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
260  "<invalid>", "<invalid>", "<invalid>", "<invalid>"
261  };
262  struct GNUNET_DNSPARSER_Packet *p;
263  unsigned int i;
264 
265  p = GNUNET_DNSPARSER_parse (request, request_length);
266  if (NULL == p)
267  {
268  fprintf (stderr, "Received malformed DNS packet!\n");
269  // FIXME: drop instead?
271  return;
272  }
273  fprintf (stdout,
274  "%s with ID: %5u Flags: %s%s%s%s%s%s, Return Code: %s, Opcode: %s\n",
275  p->flags.query_or_response ? "Response" : "Query",
276  p->id,
277  p->flags.recursion_desired ? "RD " : "",
278  p->flags.message_truncated ? "MT " : "",
279  p->flags.authoritative_answer ? "AA " : "",
280  p->flags.checking_disabled ? "CD " : "",
281  p->flags.authenticated_data ? "AD " : "",
282  p->flags.recursion_available ? "RA " : "",
283  return_codes[p->flags.return_code & 15],
284  op_codes[p->flags.opcode & 15]);
285  if (p->num_queries > 0)
286  fprintf (stdout,
287  "\tQueries:\n");
288  for (i=0;i<p->num_queries;i++)
289  display_query (&p->queries[i]);
290 
291  if (p->num_answers > 0)
292  fprintf (stdout,
293  "\tAnswers:\n");
294  for (i=0;i<p->num_answers;i++)
295  display_record (&p->answers[i]);
296  fprintf (stdout, "\n");
299 }
300 
301 
305 static void
306 do_disconnect (void *cls)
307 {
308  if (NULL != handle)
309  {
310  GNUNET_DNS_disconnect (handle);
311  handle = NULL;
312  }
313 }
314 
315 
324 static void
325 run (void *cls, char *const *args, const char *cfgfile,
326  const struct GNUNET_CONFIGURATION_Handle *cfg)
327 {
328  enum GNUNET_DNS_Flags flags;
329 
332  flags = 0;
333  if (inbound_only)
335  if (outbound_only)
337  handle =
338  GNUNET_DNS_connect (cfg,
339  flags,
341  NULL);
343 }
344 
345 
346 int
347 main (int argc, char *const *argv)
348 {
349  struct GNUNET_GETOPT_CommandLineOption options[] = {
350 
352  "inbound-only",
353  gettext_noop ("only monitor DNS queries"),
354  &inbound_only),
355 
357  "outbound-only",
358  gettext_noop ("only monitor DNS queries"),
359  &outbound_only),
360 
363  };
364 
365  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
366  return 2;
367  ret = (GNUNET_OK ==
368  GNUNET_PROGRAM_run (argc, argv, "gnunet-dns-monitor",
370  ("Monitor DNS queries."), options,
371  &run, NULL)) ? ret : 1;
372  GNUNET_free ((void*) argv);
373  return ret;
374 }
375 
376 
377 /* end of gnunet-dns-monitor.c */
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
static const char * get_class(uint16_t class)
Convert numeric DNS record class to a string.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
uint32_t retry
Time interval that should elapse before a failed refresh should be retried.
uint64_t rel_value_us
The actual value.
uint32_t refresh
Time interval before the zone should be refreshed.
#define GNUNET_TUN_DNS_CLASS_CHAOS
char * mname
The domainname of the name server that was the original or primary source of data for this zone...
Definition: w32nsp.c:83
#define GNUNET_DNSPARSER_TYPE_CNAME
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
static void display_query(const struct GNUNET_DNSPARSER_Query *query)
Output the given DNS query to stdout.
unsigned int return_code
See GNUNET_TUN_DNS_RETURN_CODE_ defines.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_verbose(unsigned int *level)
Define the &#39;-V&#39; verbosity option.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
uint16_t id
DNS ID (to match replies to requests).
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
Set this flag to see all requests just before they are returned to the network.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
unsigned int recursion_available
Set to 1 if recursion is available (server -> client)
#define GNUNET_DNSPARSER_TYPE_MX
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
unsigned int authoritative_answer
Set to 1 if this is an authoritative answer.
static int inbound_only
Option -i.
uint32_t serial
The version number of the original copy of the zone.
#define GNUNET_DNSPARSER_TYPE_PTR
static int outbound_only
Option -o.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
uint32_t minimum_ttl
The bit minimum TTL field that should be exported with any RR from this zone.
#define GNUNET_TUN_DNS_CLASS_HESIOD
unsigned int authenticated_data
Response has been cryptographically verified, RFC 4035.
unsigned int query_or_response
query:0, response:1
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:373
#define GNUNET_DNSPARSER_TYPE_SOA
char * name
Name of the record that the query is for (0-terminated).
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
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...
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:662
uint16_t port
TCP or UDP port of the service.
char * target
Hostname offering the service.
char * rname
A domainname which specifies the mailbox of the person responsible for this zone. ...
static char buf[2048]
unsigned int recursion_desired
Set to 1 if recursion is desired (client -> server)
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
unsigned int message_truncated
Set to 1 if message is truncated.
unsigned int opcode
See GNUNET_TUN_DNS_OPCODE_ defines.
A DNS response record.
uint32_t expire
Time value that specifies the upper limit on the time interval that can elapse before the zone is no ...
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
DNS handle.
Definition: dns_api.c:58
static int ret
Global return value (0 success).
size_t data_len
Number of bytes in data.
void * data
Binary record data.
static void display_record(const struct GNUNET_DNSPARSER_Record *record)
Output the given DNS record to stdout.
#define GNUNET_DNSPARSER_TYPE_TXT
int main(int argc, char *const *argv)
#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&#39;r...
Set this flag to see all requests first prior to resolution (for monitoring).
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:350
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
GNUNET_DNS_RequestHandler rh
Function to call to get replies.
Definition: dns_api.c:74
static void do_disconnect(void *cls)
Shutdown.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
Handle to identify an individual DNS request.
Definition: dns_api.c:34
#define GNUNET_DNSPARSER_TYPE_AAAA
configuration data
Definition: configuration.c:85
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:247
#define GNUNET_DNSPARSER_TYPE_NS
Easy-to-process, parsed version of a DNS packet.
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.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
int 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, parse options).
Definition: program.c:361
uint16_t priority
Preference for this entry (lower value is higher preference).
char * name
Name of the record that the query is for (0-terminated).
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:331
unsigned int num_queries
Number of queries in the packet.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
uint16_t weight
Relative weight for records with the same priority.
static const char * get_type(uint16_t type)
Convert numeric DNS record type to a string.
union GNUNET_DNSPARSER_Record::@27 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
static unsigned int verbosity
Selected level of verbosity.
#define GNUNET_DNSPARSER_TYPE_SRV
GNUNET_DNS_Flags
Flags that specify when to call the client&#39;s handler.
uint16_t preference
Preference for this entry (lower value is higher preference).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
#define GNUNET_DNSPARSER_TYPE_A
unsigned int checking_disabled
See RFC 4035.
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.
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69