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 
69  switch (type)
70  {
71  case GNUNET_DNSPARSER_TYPE_A: return "A";
72 
73  case GNUNET_DNSPARSER_TYPE_NS: return "NS";
74 
75  case GNUNET_DNSPARSER_TYPE_CNAME: return "CNAME";
76 
77  case GNUNET_DNSPARSER_TYPE_SOA: return "SOA";
78 
79  case GNUNET_DNSPARSER_TYPE_PTR: return "PTR";
80 
81  case GNUNET_DNSPARSER_TYPE_MX: return "MX";
82 
83  case GNUNET_DNSPARSER_TYPE_TXT: return "TXT";
84 
85  case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA";
86 
87  case GNUNET_DNSPARSER_TYPE_SRV: return "SRV";
88  }
89  GNUNET_snprintf(buf, sizeof(buf), "%u", (unsigned int)type);
90  return buf;
91 }
92 
93 
100 static const char *
101 get_class(uint16_t class)
102 {
103  static char buf[6];
104 
105  switch (class)
106  {
107  case GNUNET_TUN_DNS_CLASS_INTERNET: return "IN";
108 
109  case GNUNET_TUN_DNS_CLASS_CHAOS: return "CHAOS";
110 
111  case GNUNET_TUN_DNS_CLASS_HESIOD: return "HESIOD";
112  }
113  GNUNET_snprintf(buf, sizeof(buf), "%u", (unsigned int)class);
114  return buf;
115 }
116 
117 
123 static void
125 {
126  fprintf(stdout,
127  "\t\t%s %s: %s\n",
129  get_type(query->type),
130  query->name);
131 }
132 
133 
139 static void
141 {
142  const char *format;
143  char buf[INET6_ADDRSTRLEN];
144  char *tmp;
145 
146  tmp = NULL;
147  switch (record->type)
148  {
150  if (record->data.raw.data_len != sizeof(struct in_addr))
151  format = "<invalid>";
152  else
153  format = inet_ntop(AF_INET, record->data.raw.data, buf, sizeof(buf));
154  break;
155 
157  if (record->data.raw.data_len != sizeof(struct in6_addr))
158  format = "<invalid>";
159  else
160  format = inet_ntop(AF_INET6, record->data.raw.data, buf, sizeof(buf));
161  break;
162 
166  format = record->data.hostname;
167  break;
168 
170  if (NULL == record->data.soa)
171  format = "<invalid>";
172  else
173  {
174  GNUNET_asprintf(&tmp,
175  "origin: %s, mail: %s, serial = %u, refresh = %u s, retry = %u s, expire = %u s, minimum = %u s",
176  record->data.soa->mname,
177  record->data.soa->rname,
178  (unsigned int)record->data.soa->serial,
179  (unsigned int)record->data.soa->refresh,
180  (unsigned int)record->data.soa->retry,
181  (unsigned int)record->data.soa->expire,
182  (unsigned int)record->data.soa->minimum_ttl);
183  format = tmp;
184  }
185  break;
186 
188  if (record->data.mx == NULL)
189  format = "<invalid>";
190  else
191  {
192  GNUNET_asprintf(&tmp,
193  "%u: %s",
194  record->data.mx->preference,
195  record->data.mx->mxhost);
196  format = tmp;
197  }
198  break;
199 
201  if (NULL == record->data.srv)
202  format = "<invalid>";
203  else
204  {
205  GNUNET_asprintf(&tmp,
206  "priority %u, weight = %s, port = %u, target = %s",
207  (unsigned int)record->data.srv->priority,
208  (unsigned int)record->data.srv->weight,
209  (unsigned int)record->data.srv->port,
210  record->data.srv->target);
211  format = tmp;
212  }
213  break;
214 
216  GNUNET_asprintf(&tmp,
217  "%.*s",
218  (unsigned int)record->data.raw.data_len,
219  record->data.raw.data);
220  format = tmp;
221  break;
222 
223  default:
224  format = "<payload>";
225  break;
226  }
227  fprintf(stdout,
228  "\t\t%s %s: %s = %s (%u s)\n",
229  get_class(record->dns_traffic_class),
230  get_type(record->type),
231  record->name,
232  format,
233  (unsigned int)(GNUNET_TIME_absolute_get_remaining(record->expiration_time).rel_value_us / 1000LL / 1000LL));
235 }
236 
237 
261 static void
262 display_request(void *cls,
264  size_t request_length,
265  const char *request)
266 {
267  static const char *return_codes[] =
268  {
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  {
276  "Query", "Inverse query", "Status", "<invalid>",
277  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
278  "<invalid>", "<invalid>", "<invalid>", "<invalid>",
279  "<invalid>", "<invalid>", "<invalid>", "<invalid>"
280  };
281  struct GNUNET_DNSPARSER_Packet *p;
282  unsigned int i;
283 
284  p = GNUNET_DNSPARSER_parse(request, request_length);
285  if (NULL == p)
286  {
287  fprintf(stderr, "Received malformed DNS packet!\n");
288  // FIXME: drop instead?
290  return;
291  }
292  fprintf(stdout,
293  "%s with ID: %5u Flags: %s%s%s%s%s%s, Return Code: %s, Opcode: %s\n",
294  p->flags.query_or_response ? "Response" : "Query",
295  p->id,
296  p->flags.recursion_desired ? "RD " : "",
297  p->flags.message_truncated ? "MT " : "",
298  p->flags.authoritative_answer ? "AA " : "",
299  p->flags.checking_disabled ? "CD " : "",
300  p->flags.authenticated_data ? "AD " : "",
301  p->flags.recursion_available ? "RA " : "",
302  return_codes[p->flags.return_code & 15],
303  op_codes[p->flags.opcode & 15]);
304  if (p->num_queries > 0)
305  fprintf(stdout,
306  "\tQueries:\n");
307  for (i = 0; i < p->num_queries; i++)
308  display_query(&p->queries[i]);
309 
310  if (p->num_answers > 0)
311  fprintf(stdout,
312  "\tAnswers:\n");
313  for (i = 0; i < p->num_answers; i++)
314  display_record(&p->answers[i]);
315  fprintf(stdout, "\n");
318 }
319 
320 
324 static void
325 do_disconnect(void *cls)
326 {
327  if (NULL != handle)
328  {
329  GNUNET_DNS_disconnect(handle);
330  handle = NULL;
331  }
332 }
333 
334 
343 static void
344 run(void *cls, char *const *args, const char *cfgfile,
345  const struct GNUNET_CONFIGURATION_Handle *cfg)
346 {
347  enum GNUNET_DNS_Flags flags;
348 
351  flags = 0;
352  if (inbound_only)
354  if (outbound_only)
356  handle =
357  GNUNET_DNS_connect(cfg,
358  flags,
360  NULL);
362 }
363 
364 
365 int
366 main(int argc, char *const *argv)
367 {
368  struct GNUNET_GETOPT_CommandLineOption options[] = {
370  "inbound-only",
371  gettext_noop("only monitor DNS queries"),
372  &inbound_only),
373 
375  "outbound-only",
376  gettext_noop("only monitor DNS queries"),
377  &outbound_only),
378 
381  };
382 
383  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
384  return 2;
385  ret = (GNUNET_OK ==
386  GNUNET_PROGRAM_run(argc, argv, "gnunet-dns-monitor",
388  ("Monitor DNS queries."), options,
389  &run, NULL)) ? ret : 1;
390  GNUNET_free((void*)argv);
391  return ret;
392 }
393 
394 
395 /* 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.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
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...
#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:1284
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:1439
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:853
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:75
#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:368
#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:656
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:55
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:345
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:69
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:83
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:242
#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_*.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
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:367
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