Hi Samuel,

Thank you for your feedback.

I should have addressed all the required changes.

Let me know what you think.

Cheers,

Gianluca

Il giorno gio 22 gen 2026 alle ore 00:53 Samuel Thibault
<[email protected]> ha scritto:
>
> Hello,
>
> Thanks for this, it's indeed useful and well-contained for a
> contribution.
>
> Samuel
>
> Gianluca Cannata, le mer. 21 janv. 2026 09:31:37 +0100, a ecrit:
> > Index: httpfs/http.c
> > ===================================================================
> > --- httpfs.orig/http.c
> > +++ httpfs/http.c
> > @@ -34,14 +34,59 @@
> >  #include <hurd/hurd_types.h>
> >  #include <hurd/netfs.h>
> >
> > -/* do a DNS lookup for NAME and store result in *ENT */
> > -error_t lookup_host (char *url, struct hostent **ent)
> > +/* do a DNS lookup for HOST and store result in *DEST */
> > +error_t lookup_host (const char *host, struct sockaddr_storage *dest, 
> > socklen_t *dest_len)
> >  {
> > -       if ( (*ent = gethostbyname(url)) == NULL )
> > -       {
> > -               fprintf(stderr,"wrong host name\n");
> > +       struct addrinfo hints;
> > +       struct addrinfo *res;
> > +       int s;
> > +
> > +       /* Buffer that holds a clean host, that is a host without square 
> > brackets in case of a IPv6 address */
> > +       char clean_host[256];
>
> Rather than hard-coding 256, you can use strlen(host)-1. Then you won't
> have an ENAMETOOLONG error.
>
> > +       const char *host_ptr = host;
>
> You don't need a separate host_ptr variable. When using clean_host, you
> can as well just do host = clean_host.
>
> > +       if (!host || !dest || !dest_len)
> >                 return EINVAL;
> > +
> > +       /* IPv6 syntax transformation: e.g. [2001:db8::1] -> 2001:db8::1
> > +        * because getaddrinfo does not accept square brackets, but URLs do.
> > +        */
> > +       if (host[0] == '[') {
> > +               const char *end = strchr (host, ']');
>
> If you have an opening bracket, the closing bracket should be the last
> character anyway, so you can as well directly check for ']' at the end,
> and return EINVAL otherwise.
>
> > +               if (end) {
> > +                       size_t host_len = end - host - 1;
> > +                       if (host_len >= sizeof (clean_host)) return 
> > ENAMETOOLONG;
> > +
> > +                       strncpy (clean_host, host + 1, host_len);
>
> Better use memcpy.
>
> > +                       clean_host[host_len] = '\0';
> > +                       host_ptr = clean_host;
> > +               }
> >         }
> > +
> > +       memset (&hints, 0, sizeof (struct addrinfo));
>
> better use sizeof(hints), which we then know for sure is correct.
>
> > +       hints.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
> > +       hints.ai_socktype = SOCK_STREAM; /* TCP */
> > +       /* AI_ADDRCONFIG: Asks for AAAA record only if the host has IPv6 
> > connectivity.
> > +        * AI_V4MAPPED: Maps IPv4 to IPv6 if necessary. */
> > +       hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
> > +
> > +       /* DNS lookup */
> > +       s = getaddrinfo (host_ptr, NULL, &hints, &res);
> > +       if (s != 0) {
> > +               if (debug_flag)
> > +                       fprintf (stderr, "DNS lookup failed for %s: %s\n", 
> > host_ptr, gai_strerror (s));
> > +
> > +               return ENOENT;
> > +       }
> > +
> > +       /* TODO: Shall we copy only the first result or iterate through 
> > possible multiple results */
>
> Ideally we'd try to connect to each result until one succeeds. But that
> will do for now.
>
> > +       if (res != NULL) {
> > +               memcpy (dest, res->ai_addr, res->ai_addrlen);
> > +               *dest_len = res->ai_addrlen;
> > +               dest->ss_family = res->ai_family;
>
> res->ai_addr.sa_family will already have filled dest->ss_family, no need
> to fill it again.
>
> > +       }
> > +
> > +       freeaddrinfo (res);
> >         return 0;
> >  }
> >
> > @@ -52,8 +97,8 @@ error_t open_connection(struct netnode *
> >          * head. *HEAD_LEN indicates the header length, for pruning upto 
> > that */
> >
> >         error_t err;
> > -       struct hostent *hptr;
> > -       struct sockaddr_in dest;
> > +       struct sockaddr_storage server_addr;
> > +       socklen_t addr_len;
> >         ssize_t written;
> >         size_t towrite;
> >         char buffer[4096];
> > @@ -63,49 +108,39 @@ error_t open_connection(struct netnode *
> >         char delimiters0[] = " ";
> >         char delimiters1[] = "\n";
> >
> > -       bzero(&dest,sizeof(dest));
> > -       dest.sin_family = AF_INET;
> > -       dest.sin_port = htons (port);
> > -
> > -       if ( !strcmp(ip_addr,"0.0.0.0") )
> > -       {
> > -               /* connection is not through a proxy server
> > -                * find IP addr. of remote server */
> > -               err = lookup_host (node->url, &hptr);
> > -               if (err)
> > -               {
> > -                       fprintf(stderr,"Could not find IP addr 
> > %s\n",node->url);
> > -                       return err;
> > -               }
> > -               dest.sin_addr = *(struct in_addr *)hptr->h_addr;
> > -       }
> > -       else
> > -       {
> > -               /* connection is through the proxy server
> > -                * need not find IP of remote server
> > -                * find IP of the proxy server */
> > -               if ( inet_aton(ip_addr,&dest.sin_addr) == 0 )
> > -               {
> > -                       fprintf(stderr,"Invalid IP for proxy\n");
> > -                       return -1;
> > -               }
> > +       /* 1. Target selection.
> > +        * If ip_addr (proxy global variable) is set, we use it.
> > +        * Otherwise we use the node URL.
> > +        */
> > +       const char *target_host = (strcmp (ip_addr, "0.0.0.0") != 0) ? 
> > ip_addr : node->url;
> > +
> > +       /* 2. Agnostic resolution (IPv4/IPv6) */
> > +       if ((err = lookup_host (target_host, &server_addr, &addr_len)) != 
> > 0) {
> > +               fprintf (stderr, "Cannot resolve host: %s\n", target_host);
> > +               return err;
> > +       }
> > +
> > +       /* 3. Set of the port. */
> > +       if (server_addr.ss_family == AF_INET) {
> > +               ((struct sockaddr_in *)&server_addr)->sin_port = htons 
> > (port);
> > +       } else if (server_addr.ss_family == AF_INET6) {
> > +               ((struct sockaddr_in6 *)&server_addr)->sin6_port = htons 
> > (port);
> >         }
> >
> >         if (debug_flag)
> > -               fprintf (stderr, "trying to open %s:%d/%s\n", node->url,
> > -                               port, node->conn_req);
> > +               fprintf (stderr, "Connecting to %s via %s:%d\n", node->url, 
> > target_host, port);
> >
> > -       *fd = socket (AF_INET, SOCK_STREAM, 0);
> > +       /* 4. First connection: HEAD request */
> > +       *fd = socket (server_addr.ss_family, SOCK_STREAM, 0);
>
> Ideally, you'd make lookup_host also take more parameters, to be filled
> by res->ai_socktype and res->ai_protocol, instead of hardcoding
> SOCK_STREAM and 0.
>
> >         if (*fd == -1)
> >         {
> > -               fprintf(stderr,"Socket creation error\n");
> > +               perror ("Socket creation error for HEAD request");
> >                 return errno;
> >         }
> >
> > -       err = connect (*fd, (struct sockaddr *)&dest, sizeof (dest));
> > -       if (err == -1)
> > -       {
> > -               fprintf(stderr,"Cannot connect to remote host\n");
> > +       if (connect (*fd, (struct sockaddr *)&server_addr, addr_len) == -1) 
> > {
> > +               perror ("Connection to remote host failed");
> > +               close (*fd);
> >                 return errno;
> >         }
> >
> > @@ -142,21 +177,20 @@ error_t open_connection(struct netnode *
> >
> >         close(*fd);
> >
> > +       /* 5. Second connection: GET request */
> >         /* Send the GET request for the url */
> > -       *fd = socket (AF_INET, SOCK_STREAM, 0);
> > +       *fd = socket (server_addr.ss_family, SOCK_STREAM, 0);
>
> Ditto
>
> >         if (*fd == -1)
> >         {
> > -               fprintf(stderr,"Socket creation error\n");
> > +               perror ("Socket creation error for GET request");
> >                 return errno;
> >         }
> >
> > -       err = connect (*fd, (struct sockaddr *)&dest, sizeof (dest));
> > -       if (err == -1)
> > -       {
> > -               fprintf(stderr,"Cannot connect to remote host\n");
> > +       if (connect (*fd, (struct sockaddr *)&server_addr, addr_len) == -1) 
> > {
> > +               perror ("Connection to remote host failed");
> > +               close (*fd);
> >                 return errno;
> >         }
> > -
> >         towrite = strlen (node->comm_buf);
> >
> >         /* guard against EINTR failures */
> > Index: httpfs/httpfs.h
> > ===================================================================
> > --- httpfs.orig/httpfs.h
> > +++ httpfs/httpfs.h
> > @@ -119,8 +119,8 @@ error_t parse(struct netnode *node);
> >   * string */
> >  void extract(char *string,char *parent);
> >
> > -/* do a DNS lookup for NAME and store result in *ENT */
> > -error_t lookup_host (char *url, struct hostent **ent);
> > +/* do a DNS lookup for HOST and store result in *DEST */
> > +error_t lookup_host (const char *url, struct sockaddr_storage *dest, 
> > socklen_t *dest_len);
> >
> >  /* store the remote socket in *FD and establish the connection and send the
> >   * http GET request */
>
Index: httpfs/http.c
===================================================================
--- httpfs.orig/http.c
+++ httpfs/http.c
@@ -35,15 +35,12 @@
 #include <hurd/netfs.h>
 
 /* do a DNS lookup for HOST and store result in *DEST */
-error_t lookup_host (const char *host, struct sockaddr_storage *dest, socklen_t *dest_len) 
+error_t lookup_host (const char *host, struct sockaddr_storage *dest, socklen_t *dest_len, int *socktype, int *protocol) 
 {
        struct addrinfo hints;
        struct addrinfo *res;
        int s;
-
-       /* Buffer that holds a clean host, that is a host without square brackets in case of a IPv6 address */
-       char clean_host[256];
-       const char *host_ptr = host;
+       char *allocated_host = NULL;
 
        if (!host || !dest || !dest_len)
                return EINVAL;
@@ -52,18 +49,25 @@ error_t lookup_host (const char *host, s
         * because getaddrinfo does not accept square brackets, but URLs do.
         */
        if (host[0] == '[') {
-               const char *end = strchr (host, ']');
-               if (end) {
-                       size_t host_len = end - host - 1;
-                       if (host_len >= sizeof (clean_host)) return ENAMETOOLONG;
-
-                       strncpy (clean_host, host + 1, host_len);
-                       clean_host[host_len] = '\0';
-                       host_ptr = clean_host;
-               }
+               size_t host_len = strlen (host);
+
+               /* If it starts with a [, it must also ends with a ] */
+               if (host[host_len - 1] != ']')
+                       return EINVAL;
+
+               /* We allocate only the necessary memory with a VLA (C99) */
+               size_t clean_len = host_len - 2;
+               char clean_host[clean_len + 1];
+
+               /* Copy the content between square brackets */
+               allocated_host = strndup (host + 1, host_len - 2);
+               if (!allocated_host)
+                       return ENOMEM;
+
+               host = allocated_host;
        }
 
-       memset (&hints, 0, sizeof (struct addrinfo));
+       memset (&hints, 0, sizeof (hints));
        hints.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
        hints.ai_socktype = SOCK_STREAM; /* TCP */
        /* AI_ADDRCONFIG: Asks for AAAA record only if the host has IPv6 connectivity.
@@ -71,19 +75,25 @@ error_t lookup_host (const char *host, s
        hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
 
        /* DNS lookup */
-       s = getaddrinfo (host_ptr, NULL, &hints, &res);
+       s = getaddrinfo (host, NULL, &hints, &res);
+
+       if (allocated_host)
+               free (allocated_host);
+
        if (s != 0) {
                if (debug_flag)
-                       fprintf (stderr, "DNS lookup failed for %s: %s\n", host_ptr, gai_strerror (s));
+                       fprintf (stderr, "DNS lookup failed for %s: %s\n", host, gai_strerror (s));
 
                return ENOENT;
        }
 
-       /* TODO: Shall we copy only the first result or iterate through possible multiple results */
+       /* TODO: Ideally we shoud loop through the result, but taking the first one is ok for now */
        if (res != NULL) {
                memcpy (dest, res->ai_addr, res->ai_addrlen);
                *dest_len = res->ai_addrlen;
-               dest->ss_family = res->ai_family;
+
+               if (socktype) *socktype = res->ai_socktype;
+               if (protocol) *protocol = res->ai_protocol;
        }
 
        freeaddrinfo (res);
@@ -99,6 +109,8 @@ error_t open_connection(struct netnode *
        error_t err;
        struct sockaddr_storage server_addr;
        socklen_t addr_len;
+       int sock_type = 0;
+       int protocol = 0;
        ssize_t written;
        size_t towrite;
        char buffer[4096];
@@ -115,7 +127,7 @@ error_t open_connection(struct netnode *
        const char *target_host = (strcmp (ip_addr, "0.0.0.0") != 0) ? ip_addr : node->url;
 
        /* 2. Agnostic resolution (IPv4/IPv6) */
-       if ((err = lookup_host (target_host, &server_addr, &addr_len)) != 0) {
+       if ((err = lookup_host (target_host, &server_addr, &addr_len, &sock_type, &protocol)) != 0) {
                fprintf (stderr, "Cannot resolve host: %s\n", target_host);
                return err;
        }
@@ -131,7 +143,7 @@ error_t open_connection(struct netnode *
                fprintf (stderr, "Connecting to %s via %s:%d\n", node->url, target_host, port);
 
        /* 4. First connection: HEAD request */
-       *fd = socket (server_addr.ss_family, SOCK_STREAM, 0);
+       *fd = socket (server_addr.ss_family, sock_type, protocol);
        if (*fd == -1)
        {
                perror ("Socket creation error for HEAD request");
@@ -179,7 +191,7 @@ error_t open_connection(struct netnode *
        
        /* 5. Second connection: GET request */
        /* Send the GET request for the url */
-       *fd = socket (server_addr.ss_family, SOCK_STREAM, 0);
+       *fd = socket (server_addr.ss_family, sock_type, protocol);
        if (*fd == -1)
        {
                perror ("Socket creation error for GET request");
Index: httpfs/httpfs.h
===================================================================
--- httpfs.orig/httpfs.h
+++ httpfs/httpfs.h
@@ -120,7 +120,7 @@ error_t parse(struct netnode *node);
 void extract(char *string,char *parent);
 
 /* do a DNS lookup for HOST and store result in *DEST */
-error_t lookup_host (const char *url, struct sockaddr_storage *dest, socklen_t *dest_len);
+error_t lookup_host (const char *url, struct sockaddr_storage *dest, socklen_t *dest_len, int *socktype, int *protocol);
 
 /* store the remote socket in *FD and establish the connection and send the 
  * http GET request */

Reply via email to