GNUnet  0.10.x
gnunet-dns-redirector.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 char *n4;
41 
45 static char *n6;
46 
50 static int ret;
51 
55 static unsigned int verbosity;
56 
57 
63 static void
65 {
66  char buf[INET6_ADDRSTRLEN];
67 
68  switch (record->type)
69  {
71  if (record->data.raw.data_len != sizeof(struct in_addr))
72  return;
73  if (NULL != n4)
74  {
75  if (verbosity > 1)
76  fprintf(stderr,
77  "Changing A record from `%s' to `%s'\n",
78  inet_ntop(AF_INET, record->data.raw.data, buf, sizeof(buf)),
79  n4);
80  GNUNET_assert(1 == inet_pton(AF_INET, n4, record->data.raw.data));
81  }
82  break;
83 
85  if (record->data.raw.data_len != sizeof(struct in6_addr))
86  return;
87  if (NULL != n6)
88  {
89  if (verbosity > 1)
90  fprintf(stderr,
91  "Changing AAAA record from `%s' to `%s'\n",
92  inet_ntop(AF_INET6, record->data.raw.data, buf, sizeof(buf)),
93  n6);
94  GNUNET_assert(1 == inet_pton(AF_INET6, n6, record->data.raw.data));
95  }
96  break;
97 
104  break;
105 
106  default:
107  break;
108  }
109 }
110 
111 
135 static void
136 modify_request(void *cls,
138  size_t request_length,
139  const char *request)
140 {
141  struct GNUNET_DNSPARSER_Packet *p;
142  unsigned int i;
143  char *buf;
144  size_t len;
145  int ret;
146 
147  p = GNUNET_DNSPARSER_parse(request, request_length);
148  if (NULL == p)
149  {
150  fprintf(stderr, "Received malformed DNS packet, leaving it untouched\n");
152  return;
153  }
154  for (i = 0; i < p->num_answers; i++)
155  modify_record(&p->answers[i]);
156  buf = NULL;
157  ret = GNUNET_DNSPARSER_pack(p, 1024, &buf, &len);
159  if (GNUNET_OK != ret)
160  {
161  if (GNUNET_NO == ret)
162  fprintf(stderr,
163  "Modified DNS response did not fit, keeping old response\n");
164  else
165  GNUNET_break(0); /* our modifications should have been sane! */
167  }
168  else
169  {
170  if (verbosity > 0)
171  fprintf(stdout,
172  "Injecting modified DNS response\n");
173  GNUNET_DNS_request_answer(rh, len, buf);
174  }
176 }
177 
178 
182 static void
183 do_disconnect(void *cls)
184 {
185  if (NULL != handle)
186  {
187  GNUNET_DNS_disconnect(handle);
188  handle = NULL;
189  }
190 }
191 
192 
201 static void
202 run(void *cls, char *const *args, const char *cfgfile,
203  const struct GNUNET_CONFIGURATION_Handle *cfg)
204 {
205  struct in_addr i4;
206  struct in6_addr i6;
207 
208  if ((n4 != NULL) &&
209  (1 != inet_pton(AF_INET, n4, &i4)))
210  {
211  fprintf(stderr,
212  "`%s' is nto a valid IPv4 address!\n",
213  n4);
214  return;
215  }
216  if ((n6 != NULL) &&
217  (1 != inet_pton(AF_INET6, n6, &i6)))
218  {
219  fprintf(stderr,
220  "`%s' is nto a valid IPv6 address!\n",
221  n6);
222  return;
223  }
224 
225  handle =
226  GNUNET_DNS_connect(cfg,
229  NULL);
231 }
232 
233 
234 int
235 main(int argc, char *const *argv)
236 {
237  struct GNUNET_GETOPT_CommandLineOption options[] = {
239  "ipv4",
240  "IPV4",
241  gettext_noop("set A records"),
242  &n4),
243 
245  "ipv4",
246  "IPV6",
247  gettext_noop("set AAAA records"),
248  &n6),
249 
252  };
253 
254  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
255  return 2;
256 
257  ret = (GNUNET_OK ==
258  GNUNET_PROGRAM_run(argc, argv, "gnunet-dns-redirector",
260  ("Change DNS replies to point elsewhere."), options,
261  &run, NULL)) ? ret : 1;
262  GNUNET_free((void*)argv);
263  return ret;
264 }
265 
266 
267 /* end of gnunet-dns-redirector.c */
static struct GNUNET_DNS_Handle * handle
Handle to DNS service.
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 struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
#define GNUNET_DNSPARSER_TYPE_CNAME
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
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
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1256
This client wants to be called on the results of a DNS resolution (either resolved by PRE-RESOLUTION ...
static char * n6
New target for AAAA records.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:853
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
#define GNUNET_DNSPARSER_TYPE_MX
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
int main(int argc, char *const *argv)
#define GNUNET_DNSPARSER_TYPE_PTR
static char * n4
New target for A records.
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:368
#define GNUNET_DNSPARSER_TYPE_SOA
static void do_disconnect(void *cls)
Shutdown.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
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
static int ret
Global return value (0 success).
static char buf[2048]
A DNS response record.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
DNS handle.
Definition: dns_api.c:55
size_t data_len
Number of bytes in data.
void * data
Binary record data.
#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:345
GNUNET_DNS_RequestHandler rh
Function to call to get replies.
Definition: dns_api.c:69
void GNUNET_DNS_request_answer(struct GNUNET_DNS_RequestHandle *rh, uint16_t reply_length, const char *reply)
If a GNUNET_DNS_RequestHandler calls this function, the request is supposed to be answered with the d...
Definition: dns_api.c:301
static void modify_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 void modify_record(const struct GNUNET_DNSPARSER_Record *record)
Modify the given DNS record.
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.
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
union GNUNET_DNSPARSER_Record::@27 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
static unsigned int verbosity
Selected level of verbosity.
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
#define gettext_noop(String)
Definition: gettext.h:69