GNUnet  0.11.x
vpn_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012, 2016 Christian Grothoff
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 
26 #include "platform.h"
27 #include "gnunet_vpn_service.h"
28 #include "vpn.h"
29 
30 
35 {
40 
45 
50 
55 
60 
65 
69  uint64_t request_id_gen;
70 };
71 
72 
77 {
82 
87 
92 
97  const void *addr;
98 
103 
107  void *cb_cls;
108 
113 
117  struct GNUNET_HashCode serv;
118 
122  struct GNUNET_TIME_Absolute expiration_time;
123 
127  uint64_t request_id;
128 
133 
137  int addr_af;
138 
142  uint8_t protocol;
143 };
144 
145 
151 static void
152 reconnect (struct GNUNET_VPN_Handle *vh);
153 
154 
163 static int
164 check_use_ip (void *cls,
165  const struct RedirectToIpResponseMessage *rm)
166 {
167  size_t alen;
168  int af;
169 
170  af = (int) ntohl (rm->result_af);
171  switch (af)
172  {
173  case AF_UNSPEC:
174  alen = 0;
175  break;
176 
177  case AF_INET:
178  alen = sizeof(struct in_addr);
179  break;
180 
181  case AF_INET6:
182  alen = sizeof(struct in6_addr);
183  break;
184 
185  default:
186  GNUNET_break (0);
187  return GNUNET_SYSERR;
188  }
189  if ((ntohs (rm->header.size) != alen + sizeof(*rm)) ||
190  (0 == rm->request_id))
191  {
192  GNUNET_break (0);
193  return GNUNET_SYSERR;
194  }
195  return GNUNET_OK;
196 }
197 
198 
206 static void
207 handle_use_ip (void *cls,
208  const struct RedirectToIpResponseMessage *rm)
209 {
210  struct GNUNET_VPN_Handle *vh = cls;
212  int af;
213 
214  af = (int) ntohl (rm->result_af);
215  for (rr = vh->rr_head; NULL != rr; rr = rr->next)
216  {
217  if (rr->request_id == rm->request_id)
218  {
220  vh->rr_tail,
221  rr);
222  rr->cb (rr->cb_cls,
223  af,
224  (af == AF_UNSPEC) ? NULL : &rm[1]);
225  GNUNET_free (rr);
226  break;
227  }
228  }
229 }
230 
231 
237 static void
239 {
240  struct GNUNET_VPN_Handle *vh = rr->vh;
241  struct RedirectToIpRequestMessage *rip;
243  struct GNUNET_MQ_Envelope *env;
244  size_t alen;
245 
246  if (NULL == vh->mq)
247  return;
248  if (NULL == rr->addr)
249  {
250  env = GNUNET_MQ_msg (rs,
252  rs->reserved = htonl (0);
254  rs->protocol = htonl (rr->protocol);
255  rs->result_af = htonl (rr->result_af);
256  rs->target = rr->peer;
257  rs->service_descriptor = rr->serv;
258  rs->request_id = rr->request_id = ++vh->request_id_gen;
259  }
260  else
261  {
262  switch (rr->addr_af)
263  {
264  case AF_INET:
265  alen = sizeof(struct in_addr);
266  break;
267 
268  case AF_INET6:
269  alen = sizeof(struct in6_addr);
270  break;
271 
272  default:
273  GNUNET_assert (0);
274  return;
275  }
276  env = GNUNET_MQ_msg_extra (rip,
277  alen,
279  rip->reserved = htonl (0);
281  rip->result_af = htonl (rr->result_af);
282  rip->addr_af = htonl (rr->addr_af);
283  rip->request_id = rr->request_id = ++vh->request_id_gen;
284  GNUNET_memcpy (&rip[1],
285  rr->addr,
286  alen);
287  }
288  GNUNET_MQ_send (vh->mq,
289  env);
290 }
291 
292 
301 static void
302 mq_error_handler (void *cls,
303  enum GNUNET_MQ_Error error)
304 {
305  struct GNUNET_VPN_Handle *vh = cls;
306 
307  reconnect (vh);
308 }
309 
310 
316 static void
317 connect_task (void *cls)
318 {
319  struct GNUNET_VPN_Handle *vh = cls;
320  struct GNUNET_MQ_MessageHandler handlers[] = {
321  GNUNET_MQ_hd_var_size (use_ip,
324  cls),
326  };
328 
329  vh->rt = NULL;
330  vh->mq = GNUNET_CLIENT_connect (vh->cfg,
331  "vpn",
332  handlers,
334  vh);
335  if (NULL == vh->mq)
336  return;
337  for (rr = vh->rr_head; NULL != rr; rr = rr->next)
338  send_request (rr);
339 }
340 
341 
347 static void
349 {
351 
352  GNUNET_MQ_destroy (vh->mq);
353  vh->mq = NULL;
354  vh->request_id_gen = 0;
355  for (rr = vh->rr_head; NULL != rr; rr = rr->next)
356  rr->request_id = 0;
360  vh->backoff, 2),
364  &connect_task,
365  vh);
366 }
367 
368 
374 void
376 {
377  struct GNUNET_VPN_Handle *vh;
378 
379  vh = rr->vh;
381  vh->rr_tail,
382  rr);
383  GNUNET_free (rr);
384 }
385 
386 
411  int result_af,
412  uint8_t protocol,
413  const struct GNUNET_PeerIdentity *peer,
414  const struct GNUNET_HashCode *serv,
417  void *cb_cls)
418 {
420 
422  rr->vh = vh;
423  rr->cb = cb;
424  rr->cb_cls = cb_cls;
425  rr->peer = *peer;
426  rr->serv = *serv;
428  rr->result_af = result_af;
429  rr->protocol = protocol;
431  vh->rr_tail,
432  rr);
433  send_request (rr);
434  return rr;
435 }
436 
437 
462  int result_af,
463  int addr_af,
464  const void *addr,
467  void *cb_cls)
468 {
470  size_t alen;
471 
472  switch (addr_af)
473  {
474  case AF_INET:
475  alen = sizeof(struct in_addr);
476  break;
477 
478  case AF_INET6:
479  alen = sizeof(struct in6_addr);
480  break;
481 
482  default:
483  GNUNET_break (0);
484  return NULL;
485  }
486  rr = GNUNET_malloc (sizeof(struct GNUNET_VPN_RedirectionRequest) + alen);
487  rr->vh = vh;
488  rr->addr = &rr[1];
489  rr->cb = cb;
490  rr->cb_cls = cb_cls;
491  rr->expiration_time = expiration_time;
492  rr->result_af = result_af;
493  rr->addr_af = addr_af;
494  GNUNET_memcpy (&rr[1],
495  addr,
496  alen);
498  vh->rr_tail,
499  rr);
500  send_request (rr);
501  return rr;
502 }
503 
504 
511 struct GNUNET_VPN_Handle *
513 {
514  struct GNUNET_VPN_Handle *vh
515  = GNUNET_new (struct GNUNET_VPN_Handle);
516 
517  vh->cfg = cfg;
518  connect_task (vh);
519  if (NULL == vh->mq)
520  {
521  GNUNET_free (vh);
522  return NULL;
523  }
524  return vh;
525 }
526 
527 
533 void
535 {
536  GNUNET_assert (NULL == vh->rr_head);
537  if (NULL != vh->mq)
538  {
539  GNUNET_MQ_destroy (vh->mq);
540  vh->mq = NULL;
541  }
542  if (NULL != vh->rt)
543  {
545  vh->rt = NULL;
546  }
547  GNUNET_free (vh);
548 }
549 
550 
551 /* end of vpn_api.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct GNUNET_HashCode service_descriptor
Service descriptor identifying the service.
Definition: vpn.h:115
Response from the VPN service to a VPN client informing about the IP that was assigned for the reques...
Definition: vpn.h:129
struct GNUNET_SCHEDULER_Task * rt
Identifier of a reconnect task.
Definition: vpn_api.c:59
int result_af
Desired address family for the result.
Definition: vpn_api.c:132
uint64_t request_id_gen
ID of the last request that was submitted to the service.
Definition: vpn_api.c:69
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
static int check_use_ip(void *cls, const struct RedirectToIpResponseMessage *rm)
Check a GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP message from the VPN service.
Definition: vpn_api.c:164
struct GNUNET_PeerIdentity target
Target peer offering the service.
Definition: vpn.h:110
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE
Client asks VPN service to setup an IP to redirect traffic to some peer offering a service...
struct GNUNET_VPN_RedirectionRequest * next
Element in DLL.
Definition: vpn_api.c:81
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition: time.c:287
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_PeerIdentity peer
For service redirection, identity of the peer offering the service.
Definition: vpn_api.c:112
static void connect_task(void *cls)
Connect to the VPN service and start again to transmit our requests.
Definition: vpn_api.c:317
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
static void handle_use_ip(void *cls, const struct RedirectToIpResponseMessage *rm)
Handle a GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP message from the VPN service.
Definition: vpn_api.c:207
uint64_t request_id
Unique ID to match the response to a request.
Definition: vpn.h:145
int32_t result_af
Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo)
Definition: vpn.h:105
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int32_t protocol
Desired protocol (IPPROTO_UDP or IPPROTO_TCP)
Definition: vpn.h:100
uint64_t request_id
non-zero if this request has been sent to the service.
Definition: vpn_api.c:127
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void(* GNUNET_VPN_AllocationCallback)(void *cls, int af, const void *address)
Callback invoked from the VPN service once a redirection is available.
struct GNUNET_MQ_Handle * mq
Connection to VPN service.
Definition: vpn_api.c:44
Message send by the VPN client to the VPN service requesting the setup of a redirection from some IP ...
Definition: vpn.h:38
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_TIME_Absolute expiration_time
At what time should the created service mapping expire?
Definition: vpn_api.c:122
Opaque VPN handle.
Definition: vpn_api.c:34
IPC messages between VPN library and VPN service.
uint32_t reserved
Always zero.
Definition: vpn.h:48
struct GNUNET_TIME_Relative backoff
How long do we wait until we try to reconnect?
Definition: vpn_api.c:64
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1253
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP
VPN service responds to client with an IP to use for the requested redirection.
GNUNET_VPN_AllocationCallback cb
Function to call with the designated IP address.
Definition: vpn_api.c:102
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP
Client asks VPN service to setup an IP to redirect traffic via an exit node to some global IP address...
int32_t result_af
Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo)
Definition: vpn.h:58
void GNUNET_VPN_disconnect(struct GNUNET_VPN_Handle *vh)
Disconnect from the VPN service.
Definition: vpn_api.c:534
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:442
A 512-bit hashcode.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
Message handler for a specific message type.
void GNUNET_VPN_cancel_request(struct GNUNET_VPN_RedirectionRequest *rr)
Cancel redirection request with the service.
Definition: vpn_api.c:375
struct GNUNET_VPN_RedirectionRequest * rr_tail
Tail of list of active redirection requests.
Definition: vpn_api.c:54
struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_peer(struct GNUNET_VPN_Handle *vh, int result_af, uint8_t protocol, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HashCode *serv, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls)
Tell the VPN that a forwarding to a particular peer offering a particular service is requested...
Definition: vpn_api.c:410
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP.
Definition: vpn.h:134
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int32_t result_af
Address family of the allocated address that follows; will match "result_af" from the request...
Definition: vpn.h:140
Opaque redirection request handle.
Definition: vpn_api.c:76
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
uint32_t reserved
Always zero.
Definition: vpn.h:90
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
struct GNUNET_TIME_AbsoluteNBO expiration_time
How long should the redirection be maintained at most?
Definition: vpn.h:95
uint64_t request_id
Unique ID to match a future response to this request.
Definition: vpn.h:121
Handle to a message queue.
Definition: mq.c:85
struct GNUNET_VPN_Handle * GNUNET_VPN_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the VPN service.
Definition: vpn_api.c:512
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:85
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: vpn_api.c:302
int32_t addr_af
Address family used for the destination address (AF_INET or AF_INET6, in nbo)
Definition: vpn.h:63
static void reconnect(struct GNUNET_VPN_Handle *vh)
Disconnect from the service (communication error) and reconnect later.
Definition: vpn_api.c:348
struct GNUNET_TIME_AbsoluteNBO expiration_time
How long should the redirection be maintained at most?
Definition: vpn.h:53
uint8_t protocol
For service redirection, IPPROT_UDP or IPPROTO_TCP.
Definition: vpn_api.c:142
Entry in list of pending tasks.
Definition: scheduler.c:134
void * cb_cls
Closure for cb.
Definition: vpn_api.c:107
struct GNUNET_VPN_RedirectionRequest * rr_head
Head of list of active redirection requests.
Definition: vpn_api.c:49
struct GNUNET_VPN_RedirectionRequest * prev
Element in DLL.
Definition: vpn_api.c:86
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we use.
Definition: vpn_api.c:39
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
int addr_af
Address family of addr.
Definition: vpn_api.c:137
uint64_t request_id
Unique ID to match a future response to this request.
Definition: vpn.h:69
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:501
struct GNUNET_HashCode serv
For service redirection, service descriptor.
Definition: vpn_api.c:117
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static void send_request(struct GNUNET_VPN_RedirectionRequest *rr)
Add a request to our request queue and transmit it.
Definition: vpn_api.c:238
#define GNUNET_malloc(size)
Wrapper around malloc.
Message send by the VPN client to the VPN service requesting the setup of a redirection from some IP ...
Definition: vpn.h:80
const void * addr
Target IP address for the redirection, or NULL for redirection to service.
Definition: vpn_api.c:97
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_VPN_Handle * vh
Pointer to the VPN struct.
Definition: vpn_api.c:91
Time for relative time used by GNUnet, in microseconds.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_ip(struct GNUNET_VPN_Handle *vh, int result_af, int addr_af, const void *addr, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls)
Tell the VPN that forwarding to the Internet via some exit node is requested.
Definition: vpn_api.c:461