On Wed, 8 Oct 2003, Hrvoje Niksic wrote:

> Mauro Tortonesi <[EMAIL PROTECTED]> writes:
>
> > so, i am asking you: what do you think of these changes?
>
> Overall they look very good!  Judging from the patch, a large piece of
> the work part seems to be in an unexpected place: the FTP code.

yes, i have added support for LPRT and LPSV, and refactored existing code.
i still have to work on the code, but the main problem remains probably
the duplication of ftp_port and ftp_pasv, which have two different
versions (one for the IPv6-enabled case and the other for IPv4-only
case).


> Here are some remarks I got looking at the patch.
>
> It inadvertently undoes the latest fnmatch move.

sorry. i am working on an old wget cvs release. i will get up-to-date with
the latest cvs changes ASAP.


> I still don't understand the choice to use sockaddr and
> sockaddr_storage in a application code.
> They result in needless casts and (to me) uncomprehensible code.

well, using sockaddr_storage is the right way (TM) to write IPv6 enabled
code ;-)

quoting RFC3493 section 3.10:


   One simple addition to the sockets API that can help application
   writers is the "struct sockaddr_storage".  This data structure can
   simplify writing code that is portable across multiple address
   families and platforms.  This data structure is designed with the
   following goals.

   - Large enough to accommodate all supported protocol-specific address
      structures.

   - Aligned at an appropriate boundary so that pointers to it can be
      cast as pointers to protocol specific address structures and used
      to access the fields of those structures without alignment
      problems.

   The sockaddr_storage structure contains field ss_family which is of
   type sa_family_t.  When a sockaddr_storage structure is cast to a
   sockaddr structure, the ss_family field of the sockaddr_storage
   structure maps onto the sa_family field of the sockaddr structure.
   When a sockaddr_storage structure is cast as a protocol specific
   address structure, the ss_family field maps onto a field of that
   structure that is of type sa_family_t and that identifies the
   protocol's address family.


using a union like:

struct wget_sockaddr {
        struct sockaddr;
        struct sockaddr_in;
        struct sockaddr_in6;
};

is not an elegant solution, and is probably not safe because of compiler
alignments. see the chapter about struct sockaddr_storage in:

http://www.kame.net/newsletter/19980604


> For example, this cast: (unsigned char *)(&addr->addr_v4.s_addr) would
> not be necessary if the address were defined as unsigned char[4].

in_addr is the correct structure to store ipv4 addresses. using in_addr
instead of unsigned char[4] makes much easier to copy or compare ipv4
addresses. moreover, you don't have to care about the integer size in
64-bits architectures.


> I don't understand the new PASSIVE flag to lookup_host.

well, that's a problem. to get a socket address suitable for bind(2), you
must call getaddrinfo with the AI_PASSIVE flag set. for instance, if you
call:

getaddrinfo(NULL, "ftp", &hints, &res)

with the AI_PASSIVE flag, you get the :: port 21 and 0.0.0.0 port 21
socket addresses, while calling getaddrinfo without the AI_PASSIVE flag
returns the ::1 port 21 and 127.0.0.1 port 21 addresses.

the passive flag for lookup_host is a very unelegant hack, but i haven't
found a way to get rid of it, yet. any suggestion?


> In lookup_host, the comment says that you don't need to call
> getaddrinfo_with_timeout, but then you call getaddrinfo_with_timeout.
> An oversight?
>
> You removed this code:
>
> -      /* ADDR is defined to be in network byte order, which is what
> -      this returns, so we can just copy it to STORE_IP.  However,
> -      on big endian 64-bit architectures the value will be stored
> -      in the *last*, not first four bytes.  OFFSET makes sure that
> -      we copy the correct four bytes.  */
> -      int offset = 0;
> -#ifdef WORDS_BIGENDIAN
> -      offset = sizeof (unsigned long) - sizeof (ip4_address);
> -#endif
>
> But the reason the code is there is that inet_aton is not present on
> all architectures, whereas inet_addr is.  So I used only inet_addr in
> the IPv4 case, and inet_addr stupidly returned `long', which requires
> some contortions to copy into a uchar[4] on 64-bit machines.  (I see
> that inet_addr returns `in_addr_t' these days.)
>
> If you intend to use inet_aton without checking, there should be a
> fallback implementation in cmpt.c.

are there __REALLY__ systems which do not support inet_aton? their ISVs
should be ashamed of themselves...

however, yours seemed to me an ugly hack, so i have temporarily removed
it. as you say, it would be probably better to provide a fallback
implementation of inet_aton in cmpt.c.


> I note that you elided TYPE from ip_address if ENABLE_IPV6 is not
> defined.  That (I think) results in code duplication in some places,
> because the code effectively has to handle the IPv4 case twice:
>
> #ifdef ENABLE_IPV6
> switch (addr->type)
>   {
>     case IPv6:
>     ... IPv6 handling ...
>     break;
>     case IPv4:
>     ... IPv4 handling ...
>     break;
>   }
> #else
>   ... IPv4 handling because TYPE is not present without ENABLE_IPV6 ...
> #endif
>
> If it would make your life easier to add TYPE in !ENABLE_IPV6 case, so
> you can write it more compactly, by all means do it.  By "more
> compactly" I mean something code like this:
>
> switch (addr->type)
>   {
> #ifdef ENABLE_IPV6
>     case IPv6:
>     ... IPv6 handling ...
>     break;
> #endif
>     case IPv4:
>     ... IPv4 handling ...
>     break;
>   }

that's a question i was going to ask you. i supposed you were against
adding the type member to ip_address in the IPv4-only case, so i had to
made all those "#ifdef ENABLE_IPV6" switches.

i'll change my code and add the type member to ip_address. i think that
it's the best solution.


P.S. please notice that by caching the string representation of IP
     addresses instead of their network representation, the code
     could become much more elegant and simple.



-- 
Aequam memento rebus in arduis servare mentem...

Mauro Tortonesi                 [EMAIL PROTECTED]
                                [EMAIL PROTECTED]
                                [EMAIL PROTECTED]
Deep Space 6 - IPv6 with Linux  http://www.deepspace6.net
Ferrara Linux User Group        http://www.ferrara.linux.it


Reply via email to