Winsock error 10049 with no apparent reason

Hey all,

So, it’s been a while since I last updated. I assume I am experiencing the way too common “early enthusiasm leads to early laziness” syndrome.

Without further a do – a lovely issue I had to face.

On certain machines – all Vista SP1 machines, we thought – certain outgoing TCP connections to well known HTTP servers (www.google.com, www.facebook.com, www.microsoft.com etc) simply failed.

The failure returned a last error code 10049 (0x2741) which means “The requested address is not valid in its context”. This usually happens when someone tries to use a non-existent local IP address as the socket address, or when someone tries to connect to an invalid remote computer.

I wrote a test program and reproduced the behavior. I discovered that, oddly, using ADDR_ANY works perfectly – but binding to a specific interface doesn’t work.

The test program seemed to work everywhere, including Vista SP2 machines. I found no mention of this behavior anywhere on-line. I disabled the Windows Firewall and the on-board ESET NOD32 3.0 Business anti-virus, and double checked that everything was turned off. It still failed. I was stumped.

I posted on alt.programming.winsock asking about this:



Hello all,

I have been witnessing some very strange behavior of Winsock on
Windows Vista SP1, and would like to share my findings to see if
anyone could help me figure out the answer to what’s wrong.

I’ve been running a simple program which tests the behavior of Winsock
when it comes to binding a UDP socket, binding a TCP socket and
binding and then connecting a TCP socket with a wildcard interface and
a specific interface.

On my Windows XP SP3, running as an administrator, I get the following
results:

—————————————————————————————-

Testing bind() UDP with 0.0.0.0:0…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() UDP with 192.168.2.110:0…
+++ Success!!!
Testing bind() UDP with 192.168.2.110:1024…
+++ Success!!!
Testing bind() UDP with 192.168.2.110:32033…
+++ Success!!!
Testing bind() UDP with 192.168.2.110:55301…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:0…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() TCP with 192.168.2.110:0…
+++ Success!!!
Testing bind() TCP with 192.168.2.110:1024…
+++ Success!!!
Testing bind() TCP with 192.168.2.110:32033…
+++ Success!!!
Testing bind() TCP with 192.168.2.110:55301…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:0…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() AND connect() TCP with 192.168.2.110:0…
+++ Success!!!
Testing bind() AND connect() TCP with 192.168.2.110:1024…
+++ Success!!!
Testing bind() AND connect() TCP with 192.168.2.110:32033…
+++ Success!!!
Testing bind() AND connect() TCP with 192.168.2.110:55301…
+++ Success!!!
Press any key to continue . . .

—————————————————————————————-

The same results appear in Windows Vista SP2, being run as an
Administrator and as a standard user. Windows firewall is disabled, or
an exception is added, in all cases.

Windows Vista SP1, with firewall disabled, eSET NOD32 antivirus
disabled and no other special software I can think of gives me this
result, however:

—————————————————————————————-

Testing bind() UDP with 0.0.0.0:0…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() UDP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() UDP with 192.168.2.24:0…
+++ Success!!!
Testing bind() UDP with 192.168.2.24:1024…
+++ Success!!!
Testing bind() UDP with 192.168.2.24:32033…
+++ Success!!!
Testing bind() UDP with 192.168.2.24:55301…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:0…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() TCP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() TCP with 192.168.2.24:0…
+++ Success!!!
Testing bind() TCP with 192.168.2.24:1024…
+++ Success!!!
Testing bind() TCP with 192.168.2.24:32033…
+++ Success!!!
Testing bind() TCP with 192.168.2.24:55301…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:0…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:1024…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:32033…
+++ Success!!!
Testing bind() AND connect() TCP with 0.0.0.0:55301…
+++ Success!!!
Testing bind() AND connect() TCP with 192.168.2.24:0…
— connect() failed: 10049 (The requested address is not valid in its
context.).
Testing bind() AND connect() TCP with 192.168.2.24:1024…
— connect() failed: 10049 (The requested address is not valid in its
context.).
Testing bind() AND connect() TCP with 192.168.2.24:32033…
— connect() failed: 10049 (The requested address is not valid in its
context.).
Testing bind() AND connect() TCP with 192.168.2.24:55301…
— connect() failed: 10049 (The requested address is not valid in its
context.).

—————————————————————————————-

I can’t seem to understand why this happens only on Windows Vista SP1,
with a specific *CORRECT* interface.

The program code is attached after this post.

Does anyone have any clue as to what is causing this?

Thanks,

Alon


I wrote an ICMP ping client and discovered that ping worked properly on all machines – including Vista SP1. Strange – is this something to do with specific ports?

I received a response in the newsgroups – something about Vista SP1’s anti-malware logic. I was so confused at this point that I actually started looking this up, but naturally – I found nothing.

Then I discovered that a clean Vista SP1 does not exhibit this issue at all – it worked properly.

I started searching for TCP/IP stack hooks, or for NDIS filter drivers – I was looking everywhere for answer, really.

I found nothing!

My final move was to recheck the firewall and anti-virus. I was amazed to discover that shutting down the ESET NOD32 anti-virus and disabling all active protection doesn’t disable the HTTP filtering module.

This module, which basically blocks all outgoing connections from or to ports 80, 3128 and 8080 from all non-approved “browser” applications, was the cause of all my problems!

I discovered this issue in only one other place on-line, at yoics.

ESET themselves explain this on their own page, but they don’t say anything about what behavior a programmer should expect to see if their HTTP filter is active.

Basically – you can can create a socket, you can bind(), but if you try and connect to an address with port 80/3128/8080 using a socket bound to a specific interface – Winsock error 10049 is thrown. This is as if the address is invalid. Confusing!

Right now I’m looking at anti-virus/firewall detection possibilities – including WMI. This might help us notify our users as to what actions they must take to unblock our application with their anti-virus “flavor”.

I hope this post will help others, somewhere, somehow.

"If" conditional does not work properly

While debugging, I noticed that an “if” conditional displayed some pretty strange behavior.

I had code similar to this:

if (SomeFunctionReturningBoolean() == true)
{
// do something…
print “1”;
}
else
{
// do something else.
print “2”;
}

Strangely, even though SomeFunctionReturningBoolean() returned true (as the debugger helpfully noted) – the “else” clause was executed, rather than the “if” clause.

I started investigating this.

First, I suspected a mismatch between the code and the executable. I rebuilt from scratch, but no dice. I manually cleaned all of the intermediate files, nope – same strange behavior.

I then changed the code to the following:

bool fResult = SomeFunctionReturningBoolean();

if (fResult == true)
{
// do something…
print “1”;
}
else
{
// do something else.
print “2”;
}

fResult clearly held “true”, but “2” was still printed.

Next, I changed the code to:

bool fResult = SomeFunctionReturningBoolean();

if (fResult == true)
{
// do something…
print “1”;
}

if (fResult == false)
{
// do something else.
print “2”;
}

Neither “1” nor “2” were printed. Strangely, this seemed to work:

bool fResult = SomeFunctionReturningBoolean();

if (fResult)
{
// do something…
print “1”;
}
else
{
// do something else.
print “2”;
}

it printed “1”. I started wondering whether the function was indeed returning true. I changed to disassembly mode, and to my surprise – I noticed that the function was returning 0x6E, and that the equality check was:

cmp eax, 1

Going deeper into the code, I discovered that a function used by SomeFunctionReturningBoolean() as a basis for its return coded simply did not return any value. The programmer was annoyed by some of the warnings returned by an external include file, and disabled all of the warnings using a pragma – so the “Not all code paths return a value” warning simply did not appear when I compiled the code.

The Visual Studio 2008 debugger treats a bool variable with a value of 0 as false, and it displays “false” as its value in any variable windows. If the bool variable contains anything but 0 – the value displayed is “true”. This is generally correct, since non-zero values are handled as “true” by most conditional assembly instructions. However, a comparison instruction like

if (variable == true)

is compiled to

cmp eax, 1

which does not check for “true”-ness, but rather for equality with 1 – which is the value that “true” signifies in the current Microsoft C++ world.

So – the actual source code compared the bool to a specific value – 1, and since 0x6E is not equal to 1 – the check failed and we executed the “else” clause.

So, what did we learn from this issue?

  1. Never disable all of the warnings using a pragma – disable specific warnings, otherwise you’ll lose important warnings that might appear.
  2. The VS2008 debugger displays “true”/”false” values in the variables window based on a check of “true”-ness, not an equality to the “true” value.
  3. The “Go to assembly” can be very, very useful at times. You should familiarize yourself with it.