Re: bug in addrlist_match (with IPv6 addresses)

Christof Meerwald <[email protected]> Wed, 6 Aug 2003 23:20:19 +0200
Newsgroups gmane.network.xinetd
Message-ID <[email protected]>
On Thu, Jun 19, 2003 at 06:54:30PM -0700, Steve G wrote:
> -  uint32_t *tmp_addr = (unsigned *)&addr->sa_data[3];
> +  uint32_t *tmp_addr =
> &SAIN6(addr)->sin6_addr.s6_addr32[3];
> 
> This should be applied, the rest doesn't need to be.

This one isn't included in xinetd 2.3.12 (you reverted the change a few days
later).

But your code isn't correct. Have a look at the sockaddr and sockaddr_in6
definitions (from glibc 2.2.x, Debian woody):

/* Structure describing a generic socket address.  */
struct sockaddr
  {
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length. */
    char sa_data[14];           /* Address data.  */
  };


struct sockaddr_in6
  {
    __SOCKADDR_COMMON (sin6_);
    in_port_t sin6_port;        /* Transport layer port # */
    uint32_t sin6_flowinfo;     /* IPv6 flow information */
    struct in6_addr sin6_addr;  /* IPv6 address */
    uint32_t sin6_scope_id;     /* IPv6 scope-id */
  };


So, "(unsigned *)&addr->sa_data[3]" definitely won't contain the mapped IPv4
address, instead it will contain 24 bits of the sin6_flowinfo field and 8
bits of sin6_addr (and will probably segfault on some RISC architectures
because of a misaligned memory access).


Hmm, in case my fix just wasn't portable enough, this one might be better
(untested):

  uint32_t *tmp_addr = (uint32_t *) &SAIN6(addr)->sin6_addr.s6_addr[12];

(see
http://www.opengroup.org/onlinepubs/007904975/basedefs/netinet/in.h.html:
"The <netinet/in.h> header shall define the in6_addr structure that contains
at least the following member: uint8_t s6_addr[16]")


bye, Christof

-- 
http://cmeerw.org                                 JID: [email protected]
mailto cmeerw at web.de