views:

146

answers:

5

Hello,

Probably the weirdest bug I've encountered so far.

I need to connect to some 3rd-party application running under Windows XP Embedded. Network connectivity present and works: I'm able to connect to the expected port using PuTTY running on Windows XP SP3 and perform some telnet-like operations. Now, my application is a very simple C (VC++ 2008) program:

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsaData = { 0 };
    if (SOCKET_ERROR == WSAStartup(MAKEWORD(2, 0), &wsaData))
        return Error("Failed to initialize sockets.");

    SOCKET client = INVALID_SOCKET;

    const char *pserver = "172.22.1.3";

    client = socket(AF_INET, SOCK_STREAM, 0);

    if (INVALID_SOCKET != client)
    {
        sockaddr_in s = { 0 };
        s.sin_family = AF_INET;
        s.sin_port = htons(4799);
        hostent *e = gethostbyname(pserver);
        memmove(&s.sin_addr, e->h_addr, e->h_length);

        std::cout << "Connecting to: " << pserver << std::endl;

        if (SOCKET_ERROR != connect(client, (sockaddr*)&s, sizeof(s)))
        {
            std::cout << "Successfully connected." << std::endl;
        }
        else
            std::cout << "Can't connect: " << WSAGetLastError() << std::endl;
    }

    getchar();

    if (INVALID_SOCKET != client)
        closesocket(client);

    return 0;
}

Every time I compile and run this program I'm getting WSAETIMEDOUT error. Puzzled, I started digging deeper and produced two Wireshark dumps on the receiver side - one with PuTTY and another one with my application, being ran from the same PC and connecting to the same equipment (first SYN packets below).

PuTTY:

No.     Time        Source                Destination           Protocol Info
      1 0.000000    172.22.1.61           172.22.1.3            TCP      atc-lm > 4799 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=0 TSV=0 TSER=0

Frame 1 (78 bytes on wire, 78 bytes captured)
Ethernet II, Src: Dell_b8:4a:31 (00:26:b9:b8:4a:31), Dst: EEPD_96:04:48 (00:e0:33:96:04:48)
Internet Protocol, Src: 172.22.1.61 (172.22.1.61), Dst: 172.22.1.3 (172.22.1.3)
Transmission Control Protocol, Src Port: atc-lm (1170), Dst Port: 4799 (4799), Seq: 0, Len: 0

0000  00 e0 33 96 04 48 00 26 b9 b8 4a 31 08 00 45 00   ..3..H.&..J1..E.
0010  00 40 04 a1 40 00 80 06 9b aa ac 16 01 3d ac 16   .@..@........=..
0020  01 03 04 92 12 bf 9a 99 fc ec 00 00 00 00 b0 02   ................
0030  ff ff 2c bd 00 00 02 04 05 b4 01 03 03 00 01 01   ..,.............
0040  08 0a 00 00 00 00 00 00 00 00 01 01 04 02         ..............

My application:

No.     Time        Source                Destination           Protocol Info
      1 0.000000    Dell_b8:4a:31         EEPD_96:04:48         FC       [Malformed Packet]

Frame 1 (78 bytes on wire, 78 bytes captured)
Ethernet II, Src: Dell_b8:4a:31 (00:26:b9:b8:4a:31), Dst: EEPD_96:04:48 (00:e0:33:96:04:48)
MDS Header(Unknown(0)/Unknown(0))
[Malformed Packet: FC]

0000  00 e0 33 96 04 48 00 26 b9 b8 4a 31 00 00 00 00   ..3..H.&..J1....
0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0020  00 00 00 00 00 00 00 00 6d 8b 00 00 00 00 b0 02   ........m.......
0030  ff ff 90 73 00 00 02 04 05 b4 01 03 03 00 01 01   ...s............
0040  08 0a 00 00 00 00 00 00 00 00 01 01 04 02         ..............

Basically, the whole IP payload is being wiped with 0x00 instead of valid bytes.

Now comes the weirdest part. I wrote a similar program for .NET 3.5:

static void Main(string[] args)
{
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified);
    socket.Connect("172.22.1.3", 4799);

    Console.WriteLine("Connected");

    Console.ReadLine();
    socket.Disconnect(true);
}

Same Windows XP SP3 PC, same network connection - my .NET application simply connects to the remote application! Moreover, my original C application works just fine from another laptop under Windows 7 x64. After daylong headbanding I have two Windows XP SP3 laptops using which my C application doesn't connect to remote client, and one Windows XP SP3 and one Windows 7 x64 laptops where my C application works without any issues.

My first guess was network drivers, but PuTTY and .NET applications just work on the same laptop!

Had anyone exerienced something similar and could advise me?

Thanks.

A: 

Since you are connecting to an IP address, do not use gethostbyname() (especially since you are not checking it for an error reply). Use inet_addr() instead:

sockaddr_in s = { 0 }; 
s.sin_family = AF_INET; 
s.sin_port = htons(4799); 
s.sin_addr.s_addr = inet_addr(pserver); // <-- here
Remy Lebeau - TeamB
Unfortunately, that didn't work either. As well as getaddrinfo().
Converting dotted quads is a known and supported feature of gethostbyname(). It's just more efficient to call inet_addr() when you know you have a dotted quad.
Warren Young
My intention was to remove the call to memmove(), in case it is corrupting memory using a bad pointer or byte length.
Remy Lebeau - TeamB
Tried again today with inet_addr() - it makes no difference, connection doesn't happen. I even copy-pasted the whole sample from connect() page on MSDN at no avail - same behavior.
A: 

I had some what similar problem; instead of WSAETIMEDOUT, it was returning me WSAEADDRINUSE. setsockopt() solved that problem.

I would also suggest you to update socket(..., 0) call with socket(..., IPPROTO_TCP).

vrrathod
A: 

1st - Don't trust defaults in API - like make sure that you force TCP as a protocol and that you set socket options that you actually need. It's easy to remember that you are not statically linking all your code so you can always face different versions and degrees of updates applied. Forcing all options and defaults helps to reduce weird and undocumented side-effects of uncountable QFE-s.

2nd - Looks like you are building {x86,x64} Check any possible diffs between your x86 and x64 builds. Make sure that you build absolutely clean both sides (meaning explicitly deleting everything in sight - so called mixed builds can always happen when building multi platform.

3rd - Does Wireshark actually notice traffic from your app or is it just a network noise it gets? The reason I ask is that if there's no real traffic then is can be group policy and/or firewall - PUTTY most probably makes explicit API calls to open a port on built in firewall.

That exhaust my ideas at this point. Oh and do you have x64 XP to try? Just out of curiosity.

ZXX
A: 

Definitely explicitly specify IPPROTO_TCP in your socket call, don't let the API choose for you. Until you've tried that it's not worth looking at anything else.

bshields
+1  A: 

This doesn't look right to me:

memmove(&s.sin_addr, e->h_addr, e->h_length);
                     ^^^^^^^^^-- here

Don't have access to the VC docs, but shouldn't it be &e->h_addr?

Just a W.A.G. Since your version's IP block is zeroed out, stands to reason the memmove is reading from the wrong spot and copying a block of unused-but-zeroed memory.

Marc B
Also shouldn't it be memcpy, not memmove
grieve