remove never working setuid helper code from the build-system.
[oweals/gnunet.git] / src / transport / plugin_transport_http_common.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2002-2013 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
21 /**
22  * @file transport/plugin_transport_http_common.c
23  * @brief functionality shared between http(s)client plugins
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_transport_plugin.h"
29 #include "plugin_transport_http_common.h"
30 #include "gnunet_resolver_service.h"
31
32 static void
33 http_clean_splitted (struct SplittedHTTPAddress *spa)
34 {
35   if (NULL != spa)
36   {
37     GNUNET_free_non_null (spa->protocol);
38     GNUNET_free_non_null (spa->host);
39     GNUNET_free_non_null (spa->path);
40     GNUNET_free_non_null (spa);
41   }
42 }
43
44
45 struct SplittedHTTPAddress *
46 http_split_address (const char *addr)
47 {
48   struct SplittedHTTPAddress *sp;
49   char *src = GNUNET_strdup (addr);
50   char *protocol_start = NULL;
51   char *host_start = NULL;
52   char *v6_end = NULL;
53   char *port_start = NULL;
54   char *path_start = NULL;
55
56   protocol_start = src;
57
58   sp = GNUNET_new (struct SplittedHTTPAddress);
59   /* Address string consists of protocol://host[:port]path*/
60
61   host_start = strstr (src, "://");
62   if (NULL == host_start)
63   {
64     GNUNET_free (src);
65     GNUNET_free (sp);
66     return NULL;
67   }
68   host_start[0] = '\0';
69   sp->protocol = GNUNET_strdup (protocol_start);
70
71   host_start += strlen ("://");
72   if (strlen (host_start) == 0)
73   {
74     GNUNET_free (src);
75     GNUNET_free (sp->protocol);
76     GNUNET_free (sp);
77     return NULL;
78   }
79
80   /* Find path start */
81   path_start = strchr (host_start, '/');
82   if (NULL != path_start)
83   {
84     sp->path = GNUNET_strdup (path_start);
85     path_start[0] = '\0';
86   }
87   else
88     sp->path = GNUNET_strdup ("");
89
90   if (strlen (host_start) < 1)
91   {
92     GNUNET_free (src);
93     GNUNET_free (sp->protocol);
94     GNUNET_free (sp->path);
95     GNUNET_free (sp);
96     return NULL;
97   }
98
99   if (NULL != (port_start = strrchr (host_start, ':')))
100   {
101     /* *We COULD have a port, but also an IPv6 address! */
102     if (NULL != (v6_end = strchr (host_start, ']')))
103     {
104       if (v6_end < port_start)
105       {
106         /* IPv6 address + port */
107         port_start[0] = '\0';
108         port_start++;
109         sp->port = atoi (port_start);
110         if ((0 == sp->port) || (65535 < sp->port))
111         {
112           GNUNET_free (src);
113           GNUNET_free (sp->protocol);
114           GNUNET_free (sp->path);
115           GNUNET_free (sp);
116           return NULL;
117         }
118       }
119       else
120       {
121         /* IPv6 address + no port */
122         if (0 == strcmp (sp->protocol, "https"))
123           sp->port = HTTPS_DEFAULT_PORT;
124         else if (0 == strcmp (sp->protocol, "http"))
125           sp->port = HTTP_DEFAULT_PORT;
126       }
127     }
128     else
129     {
130       /* No IPv6 address */
131       port_start[0] = '\0';
132       port_start++;
133       sp->port = atoi (port_start);
134       if ((0 == sp->port) || (65535 < sp->port))
135       {
136         GNUNET_free (src);
137         GNUNET_free (sp->protocol);
138         GNUNET_free (sp->path);
139         GNUNET_free (sp);
140         return NULL;
141       }
142     }
143   }
144   else
145   {
146     /* No ':' as port separator, default port for protocol */
147     if (0 == strcmp (sp->protocol, "https"))
148       sp->port = HTTPS_DEFAULT_PORT;
149     else if (0 == strcmp (sp->protocol, "http"))
150       sp->port = HTTP_DEFAULT_PORT;
151     else
152     {
153       GNUNET_break (0);
154       GNUNET_free (src);
155       GNUNET_free (sp->protocol);
156       GNUNET_free (sp->path);
157       GNUNET_free (sp);
158       return NULL;
159     }
160   }
161   if (strlen (host_start) > 0)
162     sp->host = GNUNET_strdup (host_start);
163   else
164   {
165     GNUNET_break (0);
166     GNUNET_free (src);
167     GNUNET_free (sp->protocol);
168     GNUNET_free (sp->path);
169     GNUNET_free (sp);
170     return NULL;
171   }
172   GNUNET_free (src);
173   return sp;
174 }
175
176 /**
177  * Closure for #append_port().
178  */
179 struct PrettyPrinterContext
180 {
181   /**
182    * DLL
183    */
184   struct PrettyPrinterContext *next;
185
186   /**
187    * DLL
188    */
189   struct PrettyPrinterContext *prev;
190
191   /**
192    * Resolver handle
193    */
194   struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
195
196   /**
197    * Function to call with the result.
198    */
199   GNUNET_TRANSPORT_AddressStringCallback asc;
200
201   /**
202    * Clsoure for @e asc.
203    */
204   void *asc_cls;
205
206   /**
207    * Timeout task
208    */
209   struct GNUNET_SCHEDULER_Task *timeout_task;
210
211   /**
212    * Splitted Address
213    */
214   struct SplittedHTTPAddress *saddr;
215
216   /**
217    * Plugin String
218    */
219   char *plugin;
220
221   /**
222    * Was conversion successful
223    */
224   int sucess;
225
226   /**
227    * Address options
228    */
229   uint32_t options;
230 };
231
232 /**
233  * Head of PPC list
234  */
235 static struct PrettyPrinterContext *dll_ppc_head;
236
237 /**
238  * Tail of PPC list
239  */
240 static struct PrettyPrinterContext *dll_ppc_tail;
241
242 /**
243  * Function called for a quick conversion of the binary address to
244  * a numeric address.  Note that the caller must not free the
245  * address and that the next call to this function is allowed
246  * to override the address again.
247  *
248  * @param plugin the name of the plugin
249  * @param saddr the splitted http address
250  * @param options address options
251  * @param dnsresult dns name to include in address
252  * @return string representing the same address or NULL on error
253  */
254 static const char *
255 http_common_plugin_dnsresult_to_address (const char *plugin,
256                                          const struct
257                                          SplittedHTTPAddress *saddr,
258                                          uint32_t options,
259                                          const char *dnsresult)
260 {
261   static char rbuf[1024];
262   char *res;
263
264   GNUNET_asprintf (&res, "%s.%u.%s://%s:%u%s", plugin, options, saddr->protocol,
265                    dnsresult, saddr->port, saddr->path);
266   if (strlen (res) + 1 < 500)
267   {
268     GNUNET_memcpy (rbuf, res, strlen (res) + 1);
269     GNUNET_free (res);
270     return rbuf;
271   }
272   GNUNET_break (0);
273   GNUNET_free (res);
274   return NULL;
275 }
276
277
278 static void
279 http_common_dns_reverse_lookup_cb (void *cls, const char *hostname)
280 {
281   struct PrettyPrinterContext *ppc = cls;
282
283   if (NULL != hostname)
284   {
285     ppc->asc (ppc->asc_cls,
286               http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr,
287                                                        ppc->options,
288                                                        hostname), GNUNET_OK);
289     ppc->sucess = GNUNET_YES;
290   }
291   else
292   {
293     ppc->asc (ppc->asc_cls, NULL,
294               (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
295
296     GNUNET_CONTAINER_DLL_remove (dll_ppc_head, dll_ppc_tail, ppc);
297     http_clean_splitted (ppc->saddr);
298     GNUNET_free (ppc->plugin);
299     GNUNET_free (ppc);
300   }
301 }
302
303
304 static int
305 http_common_dns_reverse_lookup (const struct sockaddr *sockaddr,
306                                 socklen_t sockaddr_len,
307                                 const char *type,
308                                 struct SplittedHTTPAddress *saddr,
309                                 uint32_t options,
310                                 struct GNUNET_TIME_Relative timeout,
311                                 GNUNET_TRANSPORT_AddressStringCallback asc,
312                                 void *asc_cls)
313 {
314   struct PrettyPrinterContext *ppc;
315
316   ppc = GNUNET_new (struct PrettyPrinterContext);
317   ppc->saddr = saddr;
318   ppc->asc = asc;
319   ppc->asc_cls = asc_cls;
320   ppc->plugin = GNUNET_strdup (type);
321   ppc->options = options;
322   ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sockaddr,
323                                                        sockaddr_len,
324                                                        GNUNET_YES,
325                                                        timeout,
326                                                        &
327                                                        http_common_dns_reverse_lookup_cb,
328                                                        ppc);
329   if (NULL == ppc->resolver_handle)
330   {
331     GNUNET_free (ppc->plugin);
332     GNUNET_free (ppc);
333     return GNUNET_SYSERR;
334   }
335   GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
336                                dll_ppc_tail,
337                                ppc);
338   return GNUNET_OK;
339 }
340
341
342 static void
343 http_common_dns_ip_lookup_cb (void *cls,
344                               const struct sockaddr *addr,
345                               socklen_t addrlen)
346 {
347   struct PrettyPrinterContext *ppc = cls;
348
349   if (NULL != addr)
350   {
351     ppc->asc (ppc->asc_cls,
352               http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr,
353                                                        ppc->options,
354                                                        GNUNET_a2s (addr,
355                                                                    addrlen)),
356               GNUNET_OK);
357     ppc->sucess = GNUNET_YES;
358     ppc->asc (ppc->asc_cls, GNUNET_a2s (addr, addrlen), GNUNET_OK);
359   }
360   else
361   {
362     ppc->asc (ppc->asc_cls, NULL,
363               (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
364
365     GNUNET_CONTAINER_DLL_remove (dll_ppc_head, dll_ppc_tail, ppc);
366     GNUNET_free (ppc->plugin);
367     http_clean_splitted (ppc->saddr);
368     GNUNET_free (ppc);
369   }
370 }
371
372
373 static int
374 http_common_dns_ip_lookup (const char *name,
375                            const char *type,
376                            struct SplittedHTTPAddress *saddr,
377                            uint32_t options,
378                            struct GNUNET_TIME_Relative timeout,
379                            GNUNET_TRANSPORT_AddressStringCallback asc,
380                            void *asc_cls)
381 {
382   struct PrettyPrinterContext *ppc;
383
384   ppc = GNUNET_new (struct PrettyPrinterContext);
385   ppc->sucess = GNUNET_NO;
386   ppc->saddr = saddr;
387   ppc->asc = asc;
388   ppc->asc_cls = asc_cls;
389   ppc->plugin = GNUNET_strdup (type);
390   ppc->options = options;
391   ppc->resolver_handle = GNUNET_RESOLVER_ip_get (name,
392                                                  AF_UNSPEC,
393                                                  timeout,
394                                                  &http_common_dns_ip_lookup_cb,
395                                                  ppc);
396   if (NULL == ppc->resolver_handle)
397   {
398     GNUNET_free (ppc->plugin);
399     GNUNET_free (ppc);
400     return GNUNET_SYSERR;
401   }
402   GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
403                                dll_ppc_tail,
404                                ppc);
405   return GNUNET_OK;
406 }
407
408
409 /**
410  * Convert the transports address to a nice, human-readable
411  * format.
412  *
413  * @param cls closure
414  * @param type name of the transport that generated the address
415  * @param addr one of the addresses of the host, NULL for the last address
416  *        the specific address format depends on the transport
417  * @param addrlen length of the @a addr
418  * @param numeric should (IP) addresses be displayed in numeric form?
419  * @param timeout after how long should we give up?
420  * @param asc function to call on each string
421  * @param asc_cls closure for @a asc
422  */
423 void
424 http_common_plugin_address_pretty_printer (void *cls, const char *type,
425                                            const void *addr,
426                                            size_t addrlen,
427                                            int numeric,
428                                            struct GNUNET_TIME_Relative timeout,
429                                            GNUNET_TRANSPORT_AddressStringCallback
430                                            asc,
431                                            void *asc_cls)
432 {
433   const struct HttpAddress *address = addr;
434   struct SplittedHTTPAddress *saddr;
435   struct sockaddr *sock_addr;
436   const char *ret;
437   char *addr_str;
438   int res;
439   int have_ip;
440
441   saddr = NULL;
442   sock_addr = NULL;
443   if ((addrlen < sizeof(struct HttpAddress)) ||
444       (addrlen != http_common_address_get_size (address)))
445   {
446     GNUNET_break (0);
447     goto handle_error;
448   }
449
450   addr_str = (char *) &address[1];
451   if (addr_str[ntohl (address->urlen) - 1] != '\0')
452   {
453     GNUNET_break (0);
454     goto handle_error;
455   }
456
457   saddr = http_split_address (addr_str);
458   if (NULL == saddr)
459   {
460     GNUNET_break (0);
461     goto handle_error;
462   }
463
464   sock_addr = http_common_socket_from_address (addr, addrlen, &res);
465   if (GNUNET_SYSERR == res)
466   {
467     /* Malformed address */
468     GNUNET_break (0);
469     goto handle_error;
470   }
471   else if (GNUNET_NO == res)
472   {
473     /* Could not convert to IP */
474     have_ip = GNUNET_NO;
475   }
476   else if (GNUNET_YES == res)
477   {
478     /* Converted to IP */
479     have_ip = GNUNET_YES;
480   }
481   else
482   {
483     /* Must not happen */
484     GNUNET_break (0);
485     goto handle_error;
486   }
487
488   if ((GNUNET_YES == numeric) &&
489       (GNUNET_YES == have_ip))
490   {
491     /* No lookup required */
492     ret = http_common_plugin_address_to_string (type, address, addrlen);
493     asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
494     asc (asc_cls, NULL, GNUNET_OK);
495     http_clean_splitted (saddr);
496     GNUNET_free_non_null (sock_addr);
497     return;
498   }
499   if ((GNUNET_YES == numeric) &&
500       (GNUNET_NO == have_ip))
501   {
502     /* Forward lookup */
503     if (GNUNET_SYSERR ==
504         http_common_dns_ip_lookup (saddr->host, type, saddr,
505                                    address->options, timeout,
506                                    asc, asc_cls))
507     {
508       GNUNET_break (0);
509       goto handle_error;
510     }
511     /* Wait for resolver callback */
512     GNUNET_free_non_null (sock_addr);
513     return;
514   }
515   if ((GNUNET_NO == numeric) &&
516       (GNUNET_YES == have_ip))
517   {
518     /* Reverse lookup */
519     if (GNUNET_SYSERR ==
520         http_common_dns_reverse_lookup (sock_addr,
521                                         (AF_INET == sock_addr->sa_family)
522                                         ? sizeof(struct sockaddr_in)
523                                         : sizeof(struct sockaddr_in6),
524                                         type,
525                                         saddr,
526                                         address->options, timeout,
527                                         asc, asc_cls))
528     {
529       GNUNET_break (0);
530       goto handle_error;
531     }
532     /* Wait for resolver callback */
533     GNUNET_free_non_null (sock_addr);
534     return;
535   }
536   if ((GNUNET_NO == numeric) &&
537       (GNUNET_NO == have_ip))
538   {
539     /* No lookup required */
540     ret = http_common_plugin_address_to_string (type, address, addrlen);
541     asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
542     asc (asc_cls, NULL, GNUNET_OK);
543     GNUNET_free_non_null (sock_addr);
544     http_clean_splitted (saddr);
545     return;
546   }
547   /* Error (argument supplied not GNUNET_YES or GNUNET_NO) */
548   GNUNET_break (0);
549   goto handle_error;
550
551 handle_error:
552   /* Report error */
553   asc (asc_cls, NULL, GNUNET_SYSERR);
554   asc (asc_cls, NULL, GNUNET_OK);
555   GNUNET_free_non_null (sock_addr);
556   if (NULL != saddr)
557     http_clean_splitted (saddr);
558 }
559
560
561 /**
562  * FIXME.
563  */
564 const char *
565 http_common_plugin_address_to_url (void *cls,
566                                    const void *addr,
567                                    size_t addrlen)
568 {
569   static char rbuf[1024];
570   const struct HttpAddress *address = addr;
571   const char *addr_str;
572
573   if (NULL == addr)
574   {
575     GNUNET_break (0);
576     return NULL;
577   }
578   if (0 == addrlen)
579   {
580     GNUNET_break (0);
581     return NULL;
582   }
583   if (addrlen != http_common_address_get_size (address))
584   {
585     GNUNET_break (0);
586     return NULL;
587   }
588   addr_str = (char *) &address[1];
589   if (addr_str[ntohl (address->urlen) - 1] != '\0')
590     return NULL;
591
592   GNUNET_memcpy (rbuf,
593                  &address[1],
594                  ntohl (address->urlen));
595   return rbuf;
596 }
597
598
599 /**
600  * Function called for a quick conversion of the binary address to
601  * a numeric address.  Note that the caller must not free the
602  * address and that the next call to this function is allowed
603  * to override the address again.
604  *
605  * @param plugin the name of the plugin
606  * @param addr binary address
607  * @param addrlen length of the address
608  * @return string representing the same address
609  */
610 const char *
611 http_common_plugin_address_to_string (const char *plugin,
612                                       const void *addr,
613                                       size_t addrlen)
614 {
615   static char rbuf[1024];
616   const struct HttpAddress *address = addr;
617   const char *addr_str;
618   char *res;
619
620   GNUNET_assert (NULL != plugin);
621   if (NULL == addr)
622     return NULL;
623   if (0 == addrlen)
624     return NULL;
625   if (addrlen != http_common_address_get_size (address))
626     return NULL;
627   addr_str = (char *) &address[1];
628   if (addr_str[ntohl (address->urlen) - 1] != '\0')
629     return NULL;
630   GNUNET_asprintf (&res, "%s.%u.%s", plugin, ntohl (address->options),
631                    &address[1]);
632   if (strlen (res) + 1 < 500)
633   {
634     GNUNET_memcpy (rbuf, res, strlen (res) + 1);
635     GNUNET_free (res);
636     return rbuf;
637   }
638   GNUNET_break (0);
639   GNUNET_free (res);
640   return NULL;
641 }
642
643 /**
644  * Function called to convert a string address to
645  * a binary address.
646  *
647  * @param cls closure ('struct Plugin*')
648  * @param addr string address
649  * @param addrlen length of the @a addr
650  * @param buf location to store the buffer
651  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
652  * @param added length of created address
653  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
654  */
655 int
656 http_common_plugin_string_to_address (void *cls,
657                                       const char *addr,
658                                       uint16_t addrlen,
659                                       void **buf,
660                                       size_t *added)
661 {
662   struct HttpAddress *a;
663   char *address;
664   char *plugin;
665   char *optionstr;
666   size_t urlen;
667   uint32_t options;
668
669   /* Format protocol.options.address:port */
670   address = NULL;
671   plugin = NULL;
672   optionstr = NULL;
673   if ((NULL == addr) || (addrlen == 0))
674   {
675     GNUNET_break (0);
676     return GNUNET_SYSERR;
677   }
678   if ('\0' != addr[addrlen - 1])
679   {
680     GNUNET_break (0);
681     return GNUNET_SYSERR;
682   }
683   if (strlen (addr) != addrlen - 1)
684   {
685     GNUNET_break (0);
686     return GNUNET_SYSERR;
687   }
688   plugin = GNUNET_strdup (addr);
689   optionstr = strchr (plugin, '.');
690   if (NULL == optionstr)
691   {
692     GNUNET_break (0);
693     GNUNET_free (plugin);
694     return GNUNET_SYSERR;
695   }
696   optionstr[0] = '\0';
697   optionstr++;
698   options = atol (optionstr);  /* 0 on conversion error, that's ok */
699   address = strchr (optionstr, '.');
700   if (NULL == address)
701   {
702     GNUNET_break (0);
703     GNUNET_free (plugin);
704     return GNUNET_SYSERR;
705   }
706   address[0] = '\0';
707   address++;
708   urlen = strlen (address) + 1;
709
710   a = GNUNET_malloc (sizeof(struct HttpAddress) + urlen);
711   a->options = htonl (options);
712   a->urlen = htonl (urlen);
713   GNUNET_memcpy (&a[1], address, urlen);
714
715   (*buf) = a;
716   (*added) = sizeof(struct HttpAddress) + urlen;
717   GNUNET_free (plugin);
718   return GNUNET_OK;
719 }
720
721
722 /**
723  * Create a HTTP address from a socketaddr
724  *
725  * @param protocol protocol
726  * @param addr sockaddr * address
727  * @param addrlen length of the address
728  * @return the HttpAddress
729  */
730 struct HttpAddress *
731 http_common_address_from_socket (const char *protocol,
732                                  const struct sockaddr *addr,
733                                  socklen_t addrlen)
734 {
735   struct HttpAddress *address = NULL;
736   char *res;
737   size_t len;
738
739   GNUNET_asprintf (&res,
740                    "%s://%s",
741                    protocol,
742                    GNUNET_a2s (addr,
743                                addrlen));
744   len = strlen (res) + 1;
745   address = GNUNET_malloc (sizeof(struct HttpAddress) + len);
746   address->options = htonl (HTTP_OPTIONS_NONE);
747   address->urlen = htonl (len);
748   GNUNET_memcpy (&address[1], res, len);
749   GNUNET_free (res);
750   return address;
751 }
752
753
754 /**
755  * Create a socketaddr from a HTTP address
756  *
757  * @param addr a `sockaddr *` address
758  * @param addrlen length of the @a addr
759  * @param res the result:
760  *   #GNUNET_SYSERR, invalid input,
761  *   #GNUNET_YES: could convert to ip,
762  *   #GNUNET_NO: valid input but could not convert to ip (hostname?)
763  * @return the string
764  */
765 struct sockaddr *
766 http_common_socket_from_address (const void *addr,
767                                  size_t addrlen,
768                                  int *res)
769 {
770   const struct HttpAddress *ha;
771   struct SplittedHTTPAddress *spa;
772   struct sockaddr_storage *s;
773   char *to_conv;
774   size_t urlen;
775
776   (*res) = GNUNET_SYSERR;
777   ha = (const struct HttpAddress *) addr;
778   if (NULL == addr)
779   {
780     GNUNET_break (0);
781     return NULL;
782   }
783   if (0 == addrlen)
784   {
785     GNUNET_break (0);
786     return NULL;
787   }
788   if (addrlen < sizeof(struct HttpAddress))
789   {
790     GNUNET_break (0);
791     return NULL;
792   }
793   urlen = ntohl (ha->urlen);
794   if (sizeof(struct HttpAddress) + urlen != addrlen)
795   {
796     /* This is a legacy addresses */
797     return NULL;
798   }
799   if (addrlen < sizeof(struct HttpAddress) + urlen)
800   {
801     /* This is a legacy addresses */
802     return NULL;
803   }
804   if (((char *) addr)[addrlen - 1] != '\0')
805   {
806     GNUNET_break (0);
807     return NULL;
808   }
809   spa = http_split_address ((const char *) &ha[1]);
810   if (NULL == spa)
811   {
812     (*res) = GNUNET_SYSERR;
813     return NULL;
814   }
815
816   s = GNUNET_new (struct sockaddr_storage);
817   GNUNET_asprintf (&to_conv, "%s:%u", spa->host, spa->port);
818   if (GNUNET_SYSERR
819       == GNUNET_STRINGS_to_address_ip (to_conv, strlen (to_conv), s))
820   {
821     /* could be a hostname */
822     GNUNET_free (s);
823     (*res) = GNUNET_NO;
824     s = NULL;
825   }
826   else if ((AF_INET != s->ss_family) && (AF_INET6 != s->ss_family))
827   {
828     GNUNET_free (s);
829     (*res) = GNUNET_SYSERR;
830     s = NULL;
831   }
832   else
833   {
834     (*res) = GNUNET_YES;
835   }
836   http_clean_splitted (spa);
837   GNUNET_free (to_conv);
838   return (struct sockaddr *) s;
839 }
840
841
842 /**
843  * Get the length of an address
844  *
845  * @param addr address
846  * @return the size
847  */
848 size_t
849 http_common_address_get_size (const struct HttpAddress *addr)
850 {
851   return sizeof(struct HttpAddress) + ntohl (addr->urlen);
852 }
853
854
855 /**
856  * Compare addr1 to addr2
857  *
858  * @param addr1 address1
859  * @param addrlen1 address 1 length
860  * @param addr2 address2
861  * @param addrlen2 address 2 length
862  * @return #GNUNET_YES if equal, #GNUNET_NO if not, #GNUNET_SYSERR on error
863  */
864 size_t
865 http_common_cmp_addresses (const void *addr1,
866                            size_t addrlen1,
867                            const void *addr2,
868                            size_t addrlen2)
869 {
870   const char *a1 = addr1;
871   const char *a2 = addr2;
872   const struct HttpAddress *ha1;
873   const struct HttpAddress *ha2;
874
875   ha1 = (const struct HttpAddress *) a1;
876   ha2 = (const struct HttpAddress *) a2;
877
878   if (NULL == a1)
879     return GNUNET_SYSERR;
880   if (0 == addrlen1)
881     return GNUNET_SYSERR;
882   if (a1[addrlen1 - 1] != '\0')
883     return GNUNET_SYSERR;
884
885   if (NULL == a2)
886     return GNUNET_SYSERR;
887   if (0 == addrlen2)
888     return GNUNET_SYSERR;
889   if (a2[addrlen2 - 1] != '\0')
890     return GNUNET_SYSERR;
891
892   if (addrlen1 != addrlen2)
893     return GNUNET_NO;
894   if (ha1->urlen != ha2->urlen)
895     return GNUNET_NO;
896
897   if (0 == strcmp ((const char *) &ha1[1], (const char *) &ha2[1]))
898     return GNUNET_YES;
899   return GNUNET_NO;
900 }
901
902
903 /**
904  * Function obtain the network type for an address.
905  *
906  * @param env the environment
907  * @param address the address
908  * @return the network type
909  */
910 enum GNUNET_NetworkType
911 http_common_get_network_for_address (struct
912                                      GNUNET_TRANSPORT_PluginEnvironment *env,
913                                      const struct GNUNET_HELLO_Address *address)
914 {
915   struct sockaddr *sa;
916   enum GNUNET_NetworkType net_type;
917   size_t salen = 0;
918   int res;
919
920   net_type = GNUNET_NT_UNSPECIFIED;
921   sa = http_common_socket_from_address (address->address,
922                                         address->address_length,
923                                         &res);
924   if (GNUNET_SYSERR == res)
925     return net_type;
926   if (GNUNET_YES == res)
927   {
928     GNUNET_assert (NULL != sa);
929     if (AF_INET == sa->sa_family)
930     {
931       salen = sizeof(struct sockaddr_in);
932     }
933     else if (AF_INET6 == sa->sa_family)
934     {
935       salen = sizeof(struct sockaddr_in6);
936     }
937     net_type = env->get_address_type (env->cls,
938                                       sa,
939                                       salen);
940     GNUNET_free (sa);
941   }
942   return net_type;
943 }
944
945
946
947 /* end of plugin_transport_http_common.c */