Trouble with ACE and IPv6? Make Sure Your Config is Consistent

I just spent about 5 hours over the week debugging a stack corruption problem. The MSVC debugger was politely telling me the stack was corrupted in the area of an ACE_INET_Addr object instantiated on the stack. But all I did was create it then return from the method. So the problem had to be localized pretty well. Also, I was seeing the problem but none of the students in the class I was working this example for saw the problem. So it was somehow specific to my ACE build.

I stepped through the ACE_INET_Addr constructor and watched it clear the contents of the internal sockaddr to zeroes. Fine. I noted it was clearing 28 bytes and setting address family 23. “IPv6. Ok, ” I thought. But I knew the stack was being scribbled on outside the bounds of that ACE_INET_Addr object. I checked to see if ACE somehow had a bad definition of sockaddr_in6. After rummaging around ACE and Windows SDK headers I was pretty sure that wasn’t it. But there was definitely some confusion on the size of what needed to be cleared.

If you haven’t looked at the ACE_INET_Addr internals (and, really, why would you?), when ACE is built with IPv6 support (the ACE_HAS_IPV6 setting) the internal sockaddr is a union of socketaddr_in and sockaddr_in6 so both IPv4 and IPv6 can be supported. The debugger inside the ACE_INET_Addr constructor was showing me both v4 and v6 members of the union. But as I stepped out of the ACE_INET_Addr constructor back to the example application, the debugger changed to only showing the IPv4 part. Hmmm… why is that? The object back in the example is suddenly looking smaller (since the sockaddr_in6 structure is larger than the sockaddr_in structure, the union gets smaller when you leave out the sockaddr_in6). Ok, so now I know why the stack is getting smashed… I’m passing a IPv4-only ACE_INET_Addr object to a method that thinks it’s getting a IPv4-or-IPv6 object which is larger. But why?

I checked my $ACE_ROOT/ace/config.h since that’s where ACE config settings usually are. No ACE_HAS_IPV6 setting there. Did the ACE-supplied Windows configs add it in somewhere sneakily? Nope. I checked the ACE.vcproj file ACE was built with. Ah-ha… in the compile preprocessor settings there it is – ACE_HAS_IPV6.

AAAAARRRRRGGGGGGG!!!!! Now I remember where it came from. IPv6 support is turned on/off in the MPC-generated Visual Studio projects using an MPC feature setting, ipv6=1 (this is because some parts of ACE and tests aren’t included without the ipv6 feature). When I generated the ACE projects that setting was used, but when I generated the example program’s projects it wasn’t. So the uses of ACE_INET_Addr in the example had only the IPv4 support, but were passed to an ACE build that was expecting both IPv4 and IPv6 support – a larger object.

Solution? Regenerate the example’s projects with the same MPC feature file ACE’s projects were generated with. That made all the settings consistent between ACE and my example programs. No more stack scribbling.

15 Responses to “Trouble with ACE and IPv6? Make Sure Your Config is Consistent”

  1. Ken Sedgwick Says:

    Isn’t it a better solution to guarantee that all preprocessor settings which affect data object size be defined in $ACE_ROOT/ace/config.h instead of only being generated at compile time?

    This is the approach I’ve taken when packaging ACE+TAO rpm for linux; I attempt to set all such preprocessor settings explicitly in config.h to avoid this problem …


    • stevehuston Says:

      I completely agree, Ken! The ipv6 enabling switch in MPC got treated differently and I was on the losing side of the debate when it happened. In the MPC generation there’s no way to set a config.h macro. As long as the user projects also use MPC everything is ok, but if not, there could be trouble, as I re-learned…

  2. Steve Says:

    Can u please inform me how to use IPV6 In my ACE Server?

    • stevehuston Says:

      I recommend you look at ACE_wrappers/tests/SOCK_Send_Recv_Test_IPV6.cpp for hints on how to use IPv6 in ACE.

      • Steve Says:

        when i am trying to connect IPV6 server from the client its giving me error ACE_INETAddr:: ::1 : No such process

        can u please tell me why this error is coming..

  3. stevehuston Says:

    Steve… the blog is not a very effective way to answer detailed support questions. I recommend you fill out the PROBLEM-REPORT-FORM located in ACE_wrappers, include the code that’s causing the error, and either post it to ace-users or open a support contract with Riverace for resolution.

    • Steve Says:

      thanks stevehuston.
      but can u just please tell me how to enable ipv6? i have added #define ACE_HAS_IPV6 but the values returnd by ACE::ipv6_enabled() is still 0.

  4. Amey Says:

    Thanks in advance!
    I have added ACE_HAS_IPV6 to preprocessor list in vs2010.
    But when I call
    ACE_INET_Addr addr(port, host, AF_INET6);
    addr.get_ip_address(); //Here I get return value = 0 and ACE trace as “ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4”

    Debugging shows that inside ACE_INET_Addr::get_ip_address(), IN6_IS_ADDR_V4MAPPED and IN6_IS_ADDR_V4COMPAT both return false, any other preprocessor directives along with ACE_HAS_IPV6 do i need to set?

    Any help please?

    • stevehuston Says:

      Looks like the address is regular IPv6, not v4 compatible. The get_ip_address() method returns a 32-bit IPv4 address, so it can’t work with IPv6. If you really want the binary IP address, try get_addr()

  5. Amey Says:

    Thanks Steve,
    so for ipv4
    and for ipv6
    addr.get_addr(); //But get_addr() returns void*
    Is that correct?

  6. Amey Says:

    Hi steve,

    I could build ACE with ipv6 (ACE_HAS_IPV6) for 32 bit, but when I do it for 64 bit, my application code while building gets following errors:
    ace.6.1.0_versioned_vc10\ace/INET_Addr.inl(184): error C3861: ‘IN6_IS_ADDR_UNSPECIFIED’: identifier not found
    ace.6.1.0_versioned_vc10\ace/INET_Addr.inl(196): error C3861: ‘IN6_IS_ADDR_LOOPBACK’: identifier not found
    ace.6.1.0_versioned_vc10\ace/INET_Addr.inl(222): error C3861: ‘IN6_IS_ADDR_LINKLOCAL’: identifier not found
    ace.6.1.0_versioned_vc10\ace/INET_Addr.inl(232): error C3861: ‘IN6_IS_ADDR_V4MAPPED’: identifier not found
    ace.6.1.0_versioned_vc10\ace/INET_Addr.inl(242): error C3861: ‘IN6_IS_ADDR_V4COMPAT’: identifier not found

    How to fix this issue?


  7. stevehuston Says:

    For some reason the proper ipv6 headers aren’t being pulled in. You don’t see it during ACE build because inlines are on so the methods triggering the error aren’t compiled.

  8. Amey Says:

    Thats Ok, but what should I do, to get rid of above compilation errors?

    • stevehuston Says:

      I don’t have a good answer, since I don’t see that error in builds here. In general, I would suggest finding out which header files define those symbols, then look for why they aren’t being included.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

<span>%d</span> bloggers like this: