-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[oweals/gnunet.git] / src / nat / nat_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2007-2017 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
19 /**
20  * @author Christian Grothoff
21  * @author Milan Bouchet-Valat
22  *
23  * @file nat/nat_api.c
24  * Service for handling UPnP and NAT-PMP port forwarding
25  * and external IP address retrieval
26  */
27 #include "platform.h"
28 #include "gnunet_nat_service.h"
29 #include "nat.h"
30 #include "nat_stun.h"
31
32
33 /**
34  * Entry in DLL of addresses of this peer.
35  */
36 struct AddrEntry
37 {
38
39   /**
40    * DLL.
41    */
42   struct AddrEntry *next;
43
44   /**
45    * DLL.
46    */
47   struct AddrEntry *prev;
48
49   /**
50    * Address class of the address.
51    */
52   enum GNUNET_NAT_AddressClass ac;
53
54   /**
55    * Number of bytes that follow.
56    */
57   socklen_t addrlen;
58 };
59
60
61 /**
62  * Handle for active NAT registrations.
63  */
64 struct GNUNET_NAT_Handle
65 {
66
67   /**
68    * Configuration we use.
69    */
70   const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72   /**
73    * Message queue for communicating with the NAT service.
74    */
75   struct GNUNET_MQ_Handle *mq;
76
77   /**
78    * Our registration message.
79    */
80   struct GNUNET_MessageHeader *reg;
81
82   /**
83    * Head of address DLL.
84    */
85   struct AddrEntry *ae_head;
86
87   /**
88    * Tail of address DLL.
89    */
90   struct AddrEntry *ae_tail;
91
92   /**
93    * Function to call when our addresses change.
94    */
95   GNUNET_NAT_AddressCallback address_callback;
96
97   /**
98    * Function to call when another peer requests connection reversal.
99    */
100   GNUNET_NAT_ReversalCallback reversal_callback;
101
102   /**
103    * Closure for the various callbacks.
104    */
105   void *callback_cls;
106
107   /**
108    * Task scheduled to reconnect to the service.
109    */
110   struct GNUNET_SCHEDULER_Task *reconnect_task;
111
112   /**
113    * How long to wait until we reconnect.
114    */
115   struct GNUNET_TIME_Relative reconnect_delay;
116 };
117
118
119 /**
120  * Task to connect to the NAT service.
121  *
122  * @param cls our `struct GNUNET_NAT_Handle *`
123  */
124 static void
125 do_connect (void *cls);
126
127
128 /**
129  * Task to connect to the NAT service.
130  *
131  * @param nh handle to reconnect
132  */
133 static void
134 reconnect (struct GNUNET_NAT_Handle *nh)
135 {
136   struct AddrEntry *ae;
137
138   if (NULL != nh->mq)
139   {
140     GNUNET_MQ_destroy (nh->mq);
141     nh->mq = NULL;
142   }
143   while (NULL != (ae = nh->ae_head))
144   {
145     GNUNET_CONTAINER_DLL_remove (nh->ae_head,
146                                  nh->ae_tail,
147                                  ae);
148     nh->address_callback (nh->callback_cls,
149                           GNUNET_NO,
150                           ae->ac,
151                           (const struct sockaddr *) &ae[1],
152                           ae->addrlen);
153     GNUNET_free (ae);
154   }
155   nh->reconnect_delay
156     = GNUNET_TIME_STD_BACKOFF (nh->reconnect_delay);
157   nh->reconnect_task
158     = GNUNET_SCHEDULER_add_delayed (nh->reconnect_delay,
159                                     &do_connect,
160                                     nh);
161 }
162
163
164 /**
165  * Check connection reversal request.
166  *
167  * @param cls our `struct GNUNET_NAT_Handle`
168  * @param crm the message
169  * @return #GNUNET_OK if @a crm is well-formed
170  */
171 static int
172 check_connection_reversal_request (void *cls,
173                                    const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
174 {
175   if (ntohs (crm->header.size) !=
176       sizeof (*crm) +
177       sizeof (struct sockaddr_in) )
178   {
179     GNUNET_break (0);
180     return GNUNET_SYSERR;
181   }
182   return GNUNET_OK;
183 }
184
185
186 /**
187  * Handle connection reversal request.
188  *
189  * @param cls our `struct GNUNET_NAT_Handle`
190  * @param crm the message
191  */
192 static void
193 handle_connection_reversal_request (void *cls,
194                                     const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
195 {
196   struct GNUNET_NAT_Handle *nh = cls;
197
198   nh->reversal_callback (nh->callback_cls,
199                          (const struct sockaddr *) &crm[1],
200                          sizeof (struct sockaddr_in));
201 }
202
203
204 /**
205  * Check address change notification.
206  *
207  * @param cls our `struct GNUNET_NAT_Handle`
208  * @param acn the message
209  * @return #GNUNET_OK if @a crm is well-formed
210  */
211 static int
212 check_address_change_notification (void *cls,
213                                    const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
214 {
215   size_t alen = ntohs (acn->header.size) - sizeof (*acn);
216
217   switch (alen)
218   {
219   case sizeof (struct sockaddr_in):
220     {
221       const struct sockaddr_in *s4
222         = (const struct sockaddr_in *) &acn[1];
223       if (AF_INET != s4->sin_family)
224       {
225         GNUNET_break (0);
226         return GNUNET_SYSERR;
227       }
228     }
229     break;
230   case sizeof (struct sockaddr_in6):
231     {
232       const struct sockaddr_in6 *s6
233         = (const struct sockaddr_in6 *) &acn[1];
234       if (AF_INET6 != s6->sin6_family)
235       {
236         GNUNET_break (0);
237         return GNUNET_SYSERR;
238       }
239     }
240     break;
241   default:
242     GNUNET_break (0);
243     return GNUNET_SYSERR;
244   }
245   return GNUNET_OK;
246 }
247
248
249 /**
250  * Handle connection reversal request.
251  *
252  * @param cls our `struct GNUNET_NAT_Handle`
253  * @param acn the message
254  */
255 static void
256 handle_address_change_notification (void *cls,
257                                     const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
258 {
259   struct GNUNET_NAT_Handle *nh = cls;
260   size_t alen = ntohs (acn->header.size) - sizeof (*acn);
261   const struct sockaddr *sa = (const struct sockaddr *) &acn[1];
262   enum GNUNET_NAT_AddressClass ac;
263   struct AddrEntry *ae;
264
265   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266               "Received address change notification\n");
267   ac = (enum GNUNET_NAT_AddressClass) ntohl (acn->addr_class);
268   if (GNUNET_YES == ntohl (acn->add_remove))
269   {
270     ae = GNUNET_malloc (sizeof (*ae) + alen);
271     ae->ac = ac;
272     ae->addrlen = alen;
273     GNUNET_memcpy (&ae[1],
274                    sa,
275                    alen);
276     GNUNET_CONTAINER_DLL_insert (nh->ae_head,
277                                  nh->ae_tail,
278                                  ae);
279   }
280   else
281   {
282     for (ae = nh->ae_head; NULL != ae; ae = ae->next)
283       if ( (ae->addrlen == alen) &&
284            (0 == memcmp (&ae[1],
285                          sa,
286                          alen)) )
287         break;
288     if (NULL == ae)
289     {
290       GNUNET_break (0);
291       reconnect (nh);
292       return;
293     }
294     GNUNET_CONTAINER_DLL_remove (nh->ae_head,
295                                  nh->ae_tail,
296                                  ae);
297     GNUNET_free (ae);
298   }
299   nh->address_callback (nh->callback_cls,
300                         ntohl (acn->add_remove),
301                         ac,
302                         sa,
303                         alen);
304 }
305
306
307 /**
308  * Handle queue errors by reconnecting to NAT.
309  *
310  * @param cls the `struct GNUNET_NAT_Handle *`
311  * @param error details about the error
312  */
313 static void
314 mq_error_handler (void *cls,
315                   enum GNUNET_MQ_Error error)
316 {
317   struct GNUNET_NAT_Handle *nh = cls;
318
319   reconnect (nh);
320 }
321
322
323 /**
324  * Task to connect to the NAT service.
325  *
326  * @param cls our `struct GNUNET_NAT_Handle *`
327  */
328 static void
329 do_connect (void *cls)
330 {
331   struct GNUNET_NAT_Handle *nh = cls;
332   struct GNUNET_MQ_MessageHandler handlers[] = {
333     GNUNET_MQ_hd_var_size (connection_reversal_request,
334                            GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED,
335                            struct GNUNET_NAT_ConnectionReversalRequestedMessage,
336                            nh),
337     GNUNET_MQ_hd_var_size (address_change_notification,
338                            GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE,
339                            struct GNUNET_NAT_AddressChangeNotificationMessage,
340                            nh),
341     GNUNET_MQ_handler_end ()
342   };
343   struct GNUNET_MQ_Envelope *env;
344
345   nh->reconnect_task = NULL;
346   nh->mq = GNUNET_CLIENT_connect (nh->cfg,
347                                   "nat",
348                                   handlers,
349                                   &mq_error_handler,
350                                   nh);
351   if (NULL == nh->mq)
352   {
353     reconnect (nh);
354     return;
355   }
356   env = GNUNET_MQ_msg_copy (nh->reg);
357   GNUNET_MQ_send (nh->mq,
358                   env);
359 }
360
361
362 /**
363  * Attempt to enable port redirection and detect public IP address
364  * contacting UPnP or NAT-PMP routers on the local network. Use @a
365  * addr to specify to which of the local host's addresses should the
366  * external port be mapped. The port is taken from the corresponding
367  * sockaddr_in[6] field.  The NAT module should call the given @a
368  * address_callback for any 'plausible' external address.
369  *
370  * @param cfg configuration to use
371  * @param config_section name of the configuration section for optionsx
372  * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
373  * @param num_addrs number of addresses in @a addrs
374  * @param addrs list of local addresses packets should be redirected to
375  * @param addrlens actual lengths of the addresses in @a addrs
376  * @param address_callback function to call everytime the public IP address changes
377  * @param reversal_callback function to call if someone wants connection reversal from us,
378  *        NULL if connection reversal is not supported
379  * @param callback_cls closure for callbacks
380  * @return NULL on error, otherwise handle that can be used to unregister
381  */
382 struct GNUNET_NAT_Handle *
383 GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
384                      const char *config_section,
385                      uint8_t proto,
386                      unsigned int num_addrs,
387                      const struct sockaddr **addrs,
388                      const socklen_t *addrlens,
389                      GNUNET_NAT_AddressCallback address_callback,
390                      GNUNET_NAT_ReversalCallback reversal_callback,
391                      void *callback_cls)
392 {
393   struct GNUNET_NAT_Handle *nh;
394   struct GNUNET_NAT_RegisterMessage *rm;
395   size_t len;
396   size_t str_len;
397   char *off;
398
399   len = 0;
400   for (unsigned int i=0;i<num_addrs;i++)
401     len += addrlens[i];
402   str_len = strlen (config_section) + 1;
403   len += str_len;
404   if ( (len > GNUNET_MAX_MESSAGE_SIZE - sizeof (*rm)) ||
405        (num_addrs > UINT16_MAX) )
406   {
407     GNUNET_break (0);
408     return NULL;
409   }
410   rm = GNUNET_malloc (sizeof (*rm) + len);
411   rm->header.size = htons (sizeof (*rm) + len);
412   rm->header.type = htons (GNUNET_MESSAGE_TYPE_NAT_REGISTER);
413   rm->flags = GNUNET_NAT_RF_NONE;
414   if (NULL != address_callback)
415     rm->flags |= GNUNET_NAT_RF_ADDRESSES;
416   if (NULL != reversal_callback)
417     rm->flags |= GNUNET_NAT_RF_REVERSAL;
418   rm->proto = proto;
419   rm->str_len = htons (str_len);
420   rm->num_addrs = htons ((uint16_t) num_addrs);
421   off = (char *) &rm[1];
422   for (unsigned int i=0;i<num_addrs;i++)
423   {
424     switch (addrs[i]->sa_family)
425     {
426     case AF_INET:
427       if (sizeof (struct sockaddr_in) != addrlens[i])
428       {
429         GNUNET_break (0);
430         GNUNET_free (rm);
431         return NULL;
432       }
433       break;
434     case AF_INET6:
435       if (sizeof (struct sockaddr_in6) != addrlens[i])
436       {
437         GNUNET_break (0);
438         GNUNET_free (rm);
439         return NULL;
440       }
441       break;
442 #if AF_UNIX
443     case AF_UNIX:
444       if (sizeof (struct sockaddr_un) != addrlens[i])
445       {
446         GNUNET_break (0);
447         GNUNET_free (rm);
448         return NULL;
449       }
450       break;
451 #endif
452     default:
453       GNUNET_break (0);
454       GNUNET_free (rm);
455       return NULL;
456     }
457     GNUNET_memcpy (off,
458                    addrs[i],
459                    addrlens[i]);
460     off += addrlens[i];
461   }
462   GNUNET_memcpy (off,
463                  config_section,
464                  str_len);
465
466   nh = GNUNET_new (struct GNUNET_NAT_Handle);
467   nh->reg = &rm->header;
468   nh->cfg = cfg;
469   nh->address_callback = address_callback;
470   nh->reversal_callback = reversal_callback;
471   nh->callback_cls = callback_cls;
472   do_connect (nh);
473   return nh;
474 }
475
476
477 /**
478  * Check if an incoming message is a STUN message.
479  *
480  * @param data the packet
481  * @param len the length of the packet in @a data
482  * @return #GNUNET_YES if @a data is a STUN packet,
483  *         #GNUNET_NO if the packet is invalid (not a stun packet)
484  */
485 static int
486 test_stun_packet (const void *data,
487                   size_t len)
488 {
489   const struct stun_header *hdr;
490   const struct stun_attr *attr;
491   uint32_t advertised_message_size;
492   uint32_t message_magic_cookie;
493
494   /* On entry, 'len' is the length of the UDP payload. After the
495    * initial checks it becomes the size of unprocessed options,
496    * while 'data' is advanced accordingly.
497    */
498   if (len < sizeof(struct stun_header))
499   {
500     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
501                 "STUN packet too short (only %d, wanting at least %d)\n",
502                 (int) len,
503                 (int) sizeof (struct stun_header));
504     return GNUNET_NO;
505   }
506   hdr = (const struct stun_header *) data;
507   /* Skip header as it is already in hdr */
508   len -= sizeof (struct stun_header);
509   data += sizeof (struct stun_header);
510
511   /* len as advertised in the message */
512   advertised_message_size = ntohs (hdr->msglen);
513
514   message_magic_cookie = ntohl (hdr->magic);
515   /* Compare if the cookie match */
516   if (STUN_MAGIC_COOKIE != message_magic_cookie)
517   {
518     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519                 "Invalid magic cookie for STUN\n");
520     return GNUNET_NO;
521   }
522
523   if (advertised_message_size > len)
524   {
525     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
526                 "Scrambled STUN packet length (got %d, expecting %d)\n",
527                 advertised_message_size,
528                 (int)len);
529     return GNUNET_NO;
530   }
531   len = advertised_message_size;
532   while (len > 0)
533   {
534     if (len < sizeof (struct stun_attr))
535     {
536       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
537                   "Attribute too short in STUN packet (got %d, expecting %d)\n",
538                   (int) len,
539                   (int) sizeof(struct stun_attr));
540       return GNUNET_NO;
541     }
542     attr = (const struct stun_attr *) data;
543
544     /* compute total attribute length */
545     advertised_message_size = ntohs (attr->len) + sizeof(struct stun_attr);
546
547     /* Check if we still have space in our buffer */
548     if (advertised_message_size > len)
549     {
550       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
551                   "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n",
552                   advertised_message_size,
553                   (int) len);
554       return GNUNET_NO;
555     }
556     data += advertised_message_size;
557     len -= advertised_message_size;
558   }
559   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
560               "STUN Packet, msg %04x, length: %d\n",
561               ntohs (hdr->msgtype),
562               advertised_message_size);
563   return GNUNET_OK;
564 }
565
566
567 /**
568  * Handle an incoming STUN message.  This function is useful as
569  * some GNUnet service may be listening on a UDP port and might
570  * thus receive STUN messages while trying to receive other data.
571  * In this case, this function can be used to process replies
572  * to STUN requests.
573  *
574  * The function does some basic sanity checks on packet size and
575  * content, try to extract a bit of information.
576  *
577  * At the moment this only processes BIND requests, and returns the
578  * externally visible address of the request to the rest of the
579  * NAT logic.
580  *
581  * @param nh handle to the NAT service
582  * @param sender_addr address from which we got @a data
583  * @param sender_addr_len number of bytes in @a sender_addr
584  * @param data the packet
585  * @param data_size number of bytes in @a data
586  * @return #GNUNET_OK on success
587  *         #GNUNET_NO if the packet is not a STUN packet
588  *         #GNUNET_SYSERR on internal error handling the packet
589  */
590 int
591 GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
592                                const struct sockaddr *sender_addr,
593                                size_t sender_addr_len,
594                                const void *data,
595                                size_t data_size)
596 {
597   struct GNUNET_MQ_Envelope *env;
598   struct GNUNET_NAT_HandleStunMessage *hsn;
599   char *buf;
600
601   if (GNUNET_YES !=
602       test_stun_packet (data,
603                         data_size))
604     return GNUNET_NO;
605   if (NULL == nh->mq)
606     return GNUNET_SYSERR;
607   env = GNUNET_MQ_msg_extra (hsn,
608                              data_size + sender_addr_len,
609                              GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN);
610   hsn->sender_addr_size = htons ((uint16_t) sender_addr_len);
611   hsn->payload_size = htons ((uint16_t) data_size);
612   buf = (char *) &hsn[1];
613   GNUNET_memcpy (buf,
614                  sender_addr,
615                  sender_addr_len);
616   buf += sender_addr_len;
617   GNUNET_memcpy (buf,
618                  data,
619                  data_size);
620   GNUNET_MQ_send (nh->mq,
621                   env);
622   return GNUNET_OK;
623 }
624
625
626 /**
627  * Test if the given address is (currently) a plausible IP address for
628  * this peer.  Mostly a convenience function so that clients do not
629  * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
630  * has returned so far.
631  *
632  * @param nh the handle returned by register
633  * @param addr IP address to test (IPv4 or IPv6)
634  * @param addrlen number of bytes in @a addr
635  * @return #GNUNET_YES if the address is plausible,
636  *         #GNUNET_NO if the address is not plausible,
637  *         #GNUNET_SYSERR if the address is malformed
638  */
639 int
640 GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh,
641                          const void *addr,
642                          socklen_t addrlen)
643 {
644   struct AddrEntry *ae;
645
646   if ( (addrlen != sizeof (struct sockaddr_in)) &&
647        (addrlen != sizeof (struct sockaddr_in6)) )
648   {
649     GNUNET_break (0);
650     return GNUNET_SYSERR;
651   }
652   for (ae = nh->ae_head; NULL != ae; ae = ae->next)
653     if ( (addrlen == ae->addrlen) &&
654          (0 == memcmp (addr,
655                        &ae[1],
656                        addrlen)) )
657       return GNUNET_YES;
658   return GNUNET_NO;
659 }
660
661
662 /**
663  * We learned about a peer (possibly behind NAT) so run the
664  * gnunet-nat-client to send dummy ICMP responses to cause
665  * that peer to connect to us (connection reversal).
666  *
667  * @param nh handle (used for configuration)
668  * @param local_sa our local address of the peer (IPv4-only)
669  * @param remote_sa the remote address of the peer (IPv4-only)
670  * @return #GNUNET_SYSERR on error,
671  *         #GNUNET_NO if connection reversal is unavailable,
672  *         #GNUNET_OK otherwise (presumably in progress)
673  */
674 int
675 GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
676                              const struct sockaddr_in *local_sa,
677                              const struct sockaddr_in *remote_sa)
678 {
679   struct GNUNET_MQ_Envelope *env;
680   struct GNUNET_NAT_RequestConnectionReversalMessage *req;
681   char *buf;
682
683   if (NULL == nh->mq)
684     return GNUNET_SYSERR;
685   GNUNET_break (AF_INET == local_sa->sin_family);
686   GNUNET_break (AF_INET == remote_sa->sin_family);
687   env = GNUNET_MQ_msg_extra (req,
688                              2 * sizeof (struct sockaddr_in),
689                              GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL);
690   req->local_addr_size = htons (sizeof (struct sockaddr_in));
691   req->remote_addr_size = htons (sizeof (struct sockaddr_in));
692   buf = (char *) &req[1];
693   GNUNET_memcpy (buf,
694                  local_sa,
695                  sizeof (struct sockaddr_in));
696   buf += sizeof (struct sockaddr_in);
697   GNUNET_memcpy (buf,
698                  remote_sa,
699                  sizeof (struct sockaddr_in));
700   GNUNET_MQ_send (nh->mq,
701                   env);
702   return GNUNET_OK;
703 }
704
705
706 /**
707  * Stop port redirection and public IP address detection for the given
708  * handle.  This frees the handle, after having sent the needed
709  * commands to close open ports.
710  *
711  * @param nh the handle to stop
712  */
713 void
714 GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh)
715 {
716   if (NULL != nh->mq)
717   {
718     GNUNET_MQ_destroy (nh->mq);
719     nh->mq = NULL;
720   }
721   if (NULL != nh->reconnect_task)
722   {
723     GNUNET_SCHEDULER_cancel (nh->reconnect_task);
724     nh->reconnect_task = NULL;
725   }
726   GNUNET_free (nh->reg);
727   GNUNET_free (nh);
728 }
729
730
731 /* end of nat_api.c */