Verify that ipconfig was applied - c++

I am currently developing a tool that automatically connects and authenticates users to certain wireless hotspots under given circumstances.
To test if the device is behind a captive portal i send a http request via wininet and check if it gets redirected (yes i am aware of NCSI but it does not work correctly in this case).
If i do that directly after i get the callback for a successfull wlan connection i receive error 12007 (name not resolved) which i assume is because of the ipconfig not being fully applied at that point. If i put in a Sleep() for 2-3 seconds i dont receive the error (since i have one of the faster devices in our hardware-lineup it might vary on other target devices).
Is there a way i can programmatically check if the config has been fully applied to the interface?
Target-OS is Windows 7
Retrying like Jon suggests is not really a feasable Option in this case since I have to enable a Hotspot registration Mode in the Firewall which closes again after a certain number of network operations which is why I would like to avoid that.

Normally for a situation like this, if you error is catchable, you would retry for a certain amount of time then give up (timeout) with the most recent error. This is simpler and the same logic the OS would be implementing anyways
So, in this case I would:
For X(default 30) seconds at most {
test if I can get a dns resolution
delay 1 second
}

Quite possibly the easiest solution would be to do a DNS lookup, using a randomly generated name within a domain that you control. E.g. 79BF2DA7-EE45-4E11-89A4-45EEF2838003.guid.example.com. This should of course fail, but it has to fail by returning a negative response from the DNS server. And that DNS server has to be reachable to return a negative response.

Related

Windows API for DNS change notification

I am looking for a way to receive a notification whenever the configured DNS server address of a network interface changes, using native Windows APIs (C/C++). For both performance and reaction time reasons, I'd obviously want to avoid polling.
There is, for example, the NotifyIpInterfaceChange API in Iphlpapi.dll. In my tests, it reliably triggers a notification when the host's IP address, subnet mask, or default gateway changes, but not at all when only the DNS addresses change.
My only "solution" up to this point is using WMI event queries, but it actually polls in the background, so to avoid hogging down the system, the polling interval (WQL WITHIN clause) needs to be set to several seconds, which results in a long and annoying delay for my application. Also, for various reasons (which are not the topic of this discussion), I prefer to avoid WMI usage anyway, resorting to it only when there is no other way.
Actual credit for this answer should go to RbMm, but he's not posting the answer and seems to have gone MIA.
To receive DNS change notifications, the only non-polling solution seems to be using the RegNotifyChangeKeyValue WinApi to monitor for changes under the HKLM\SYSTEM\CurrentControlSet\Services\Tcpip[6]\Parameters\Interfaces key. Note that there's separate Tcpip and Tcpip6 keys for IPv4 and IPv6 respectively. Anyway, I've implemented and thoroughly tested the solution since the original suggestion and it works without problems.
A semi-related warning: RegNotifyChangeKeyValue has its non-intuitive peculiarities, and it is unlike most other notification APIs, so be sure to study its docs.

reporting end of seed or leeching to tracker Libtorrent

From what I know, when seeding or leeching torrent, your IP is on tracker and it remains there for some few hours or days How do I manually tell my the tracker using Libtorrent I am no longer going to be connected to the tracker and it should forget my IP as I am neither seeding nore leeching. Any code bits or advices would be appreciated, currently I am using Python binding provided by rasterbar but I am okay with C++ code too.
Trackers are just HTTP services (although poorly designed). See BitTorrent Tracker Protocol, in particular, the event query parameter. In Python, you can use urllib.
libtorrent automatically does this when stopping a torrent, or stopping the session. If it seems to fail, you might want to increase the tracker timeout when shutting down. This will add to the shutdown delay, but will give some more overloaded trackers some more time. See session_settings::stop_tracker_timeout. By default this is 5 seconds, but sometimes trackers take much longer than that to respond, up to 30 seconds.
Trackers typically time out peers in about an hour, and you need to re-announce every 30 minutes to stay alive.
If you're trying to just send the stopped event to trackers, using a separate bittorrent client (in this case, assuming whatever client you're using fails to send stopped events to the trackers), it might be a bit less reliable.
You're supposed to include the info-hash (i.e. the unique identifier for the torrent), your key which the client generates on startup, peer-id (which is also generated by the client) and transfer statistics, in the tracker request.
You can get away with omitting the statistics, but if you don't know the info-hash or the client key, and in some cases the peer-id, the tracker won't be able to figure out that your request actually refers to your client's tracker request, and it won't remove your IP.
In practice, for the most part you might be able to get it to work by just knowing the info-hash and tracker URL. You can get the info-hash by loading the .torrent file, grabbing the info-hash and tracker URLs out of it.

C/C++ detect network type

I need to write a win32 c/c++ application which will be able to determine whether the PC it's running on is connected to one of 2 networks. The first network is the company LAN (which has no internet connection) and the second network is a standalone switch with a single PC connected to it (the PC that the program is running on).
I'm pretty new to network programming but so far I have tried testing to see if a network drive which is held on our LAN can be mapped. This works fine if the PC is connected to the LAN, the drive mapping succeeds so so LAN detection is successful. However, if the PC is connected to the switch, this results in a VERY long timeout which is not a suitable as it will delay the program so much as to make it unusable.
Does anyone have any alternative suggestions?
I'm using c/c++ in VS 6.0
[Update]
Whilst trying a few different ideas and looking at some of the suggestions below I thought I should update with some additional information as many (if not all) of the suggestions I don't think will work.
(1) The aforementioned LAN has no external connections at all, it is completely isolated so no resolving of external DNS or pinging websites is possible.
(2) Hostname, MAC address, IP, Default Gateway, Subnet etc etc (basically everything you see in ipconfig -all) are all manually configured (not dynamic from the router) so checking any of these settings will return the same whether connected to the LAN or the switch.
(3) Due to point (2), any attempts to communicate with the switch seem to be unsuccessful, in fact almost all networking commands (ping, arp etc) seem to fail - I think due to the machine trying to connect to the LAN when it isn't there :-(
One thing I have found which works is pinging the default gateway IP which times out when connected to the switch. This is sort of ok as I can reduce the timeout of ping so it doesn't just hang for ages but it feels like a bit of a hack and I would certainly appreciate any better solutions.
Thanks
As far as TCP/IP is concerned there is no such thing as a LAN on WAN. There are a set of non-internet routable addresses like 192.168.x.x and 10.x.x.x but these are sometimes used by ISP short of IP addresses.
You best bet is to use Asynchronous APIs when making TCP/IP connections. WIN32 defines a whole buch of OVERLAPPED APIs for this purpose. This will prevent your application from grinding to a halt while waiting for a remote connection.
Alternatively put the socket stuff into another thread and then only notify the UI when the operation is done.
I would first try to differentiate between the two using information available locally--that is, from your computer. Does the output of ipconfig /all differ depending on which network you're connected to? If so, exploit that difference if you can.
Is it possible to get the MAC address of the standalone switch? Of the switch that controls the company LAN? That would be a sure way to tell. Unless somebody cloned the MAC address.
If you try using the existence or non-existence of some network service to determine which network you're connected to, you can never be sure. For example, if you failed to map that network drive, all you know is that the network drive isn't available. You can't say for certain that you're not connected to the company LAN. Same is true if you use ping. Lack of response from a particular machine means only that the machine didn't respond.
Various things you can look at for differentiation:
DNS domain name (GetComputerNameEx)
MAC address of gateway (ping it, then GetIpNetTable)
Routing table(do you have a gateway and default route on the company LAN)
WNet discovered network resources (WNetOpenEnum, WNetEnumResource)
Ability to resolve external hostnames (try a 5-10 names like www.google.com, www.microsoft.com and so on, if one resolves you should have internet)
You'll have to decide how many indicators are "enough" to decide you're on one or the other LAN though if tests fail. Then keep retrying until you have a definite result.
http://msdn.microsoft.com/en-us/library/aa366071%28v=VS.85%29.aspx has a lot of network related functions that you can experiment with to create further indicators.

WMI - Cannot connect to certain computers via IP address

I have a really odd issue with WMI that I'm running into on a few machines on our network.
I have a piece of software (.NET/C#) written that scans an IP range on a local network, and then uses WMI to query certain data about the machines (computer names, .NET framework versions, among other things). One issue I've run into recently is that a small subset of these machines will not respond to WMI connections made via their IP address- they simply throw an "RPC Server is Unavailable" exception as if WMI isn't running to begin with.
This occurs both with the C# application and with a vbscript application that attempts a simple query to return the computer's name:
if wscript.arguments.count >= 1 then
host = wscript.arguments(0)
end if
if host = "" or isnull(host) then host = "."
connectionStr = "winmgmts:{impersonationLevel=impersonate}!\\" & host & "\root\cimv2"
wscript.echo connectionStr
set objWMIService = GetObject(connectionStr)
set objCompName = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
for each x in objCompName
wscript.echo x.Name
next
This returns the following as results:
C:\>nslookup BROKENCOMPUTER
Address: 192.168.1.123
C:\>cscript testwmi.vbs 192.168.1.123
winmgmts:{impersonationLevel=impersonate}!\\192.168.1.123\root\cimv2
C:\testwmi.vbs(9, 1) Microsoft VBScript runtime error: The remote server machine does not exist or is unavailable: 'GetObject'
C:\>cscript testwmi.vbs BROKENCOMPUTER
winmgmts:{impersonationLevel=impersonate}!\\BROKENCOMPUTER\root\cimv2
BROKENCOMPUTER
I can still open a WMI connection if I refer to the computer by its host/computer name. I can also connect to other servers running on the machine via IP address (such as HTTP or RDP)- a request tp http://192.168.1.123 returns successfully.
To make things even weirder, the behavior isn't even consistent. Sometimes the connection to the IP will work correctly, and it happens in batches. To test this, I set up a script that repeatedly spammed a WMI request every 5 seconds to the computer in question and recorded the result (and trends of results). What I found was that all requests would fail or succeed for about a certain number of requests (180- a 15 minute interval) or a multiple of it. Example:
- Start script
- 35 successful requests in a row
- 180 failed requests in a row
- 180 successful requests
- 360 failed requests
- 180 successful requests
- 180 failed requests
- 900 successful requests
- etc etc
I then ran this script on two machines at the same time. What I found was the behavior between the two was similar (had several-minute-long-intervals of being able to connect and not being able to connect) but did not sync up between the two; there were periods where both could connect, periods where only one (or the other) could connect, and periods where neither could connect.
I know this is an incredibly weird and specific problem, and I don't really expect anyone to be able to insta-solve it, but I was wondering if anyone had any hints or direction? I've spoken to the network guys here and they're just as puzzled over the issue as I am.
I can add some perspective on this, in addition to the fine answer from MisterZimbu. Assuming Microsoft doesn't remove my comments on this article, see http://msdn.microsoft.com/en-us/library/windows/desktop/aa393720%28v=vs.85%29.aspx. Basically, Microsoft seems to be doing a reverse DNS lookup when IP addresses are passed into WMI. If your DNS isn't squeaky clean, you will get "unpredictable results", which is to say that you will be connecting to machines you didn't expect to connect to.
Adding the period to the IP address forces the reverse (or forward) lookup to fail, and then by some miracle, they actually use the IP address, and not the (potentially incorrect) hostname returned from DNS. It appears that appending a period to the IP address can be used in many contexts (UNC's, browser, etc.), but there are caveats and other failures you might encounter. Note that if you look at your DNS cache (ipconfig /displaydns) you will see the failed lookups when the period is appended, so it doesn't stop the OS from doing the lookup - it just ensures that the stale DNS entries won't be used.
Oddly enough, adding a "." to the end of the IP address when making the query corrects the issue. I assume this forces it to go through DNS resolution or something like that.
So connecting via
winmgmts:{impersonationLevel=impersonate}!\\192.168.1.123.\root\cimv2
seems to work correctly 100% of the time.
Still would be great to know what actually is the underlying cause of the issue though.

Is is possile to Hook file-download event of a program?

Please tell me is it possile to know when a program is trying to download a file ( like in Internet Download Manager ). I want to catch that event (hook it), get the download url, and then destroy the event.
Thanks in advance..
#Jerry Coffin:Sr, I forgot to tell you that this feature of IDM is not active by default. It is only turned on when you enable the "Use advance browser integration" option at "Download/Options" of IDM menu.
Like here :
http://files.myopera.com/UenX/files/Detect.jpg
+ Check the (1) options, OK, then reboot.
+ After reboot, the (2) option will appear, check it, OK, and now run your software. You should see some thing likes (3)
( this appear when I run the msgr9us.exe ( Yahoo! Messenger setup file) )
Give it a try..
For a specific program such as Internet Explorer, doing this is quite reasonable (IE includes hooks to invoke your code under the right circumstances). For most programs it's not possible though -- they simply don't generate any "event" for you to hook and "destroy".
To make a long story short, to get anywhere with this, you'll almost certainly need to handle the situation on a case-by-base basis, writing code specific to each application you want to deal with -- and know that any other application and even newer versions of the applications you've dealt with will probably break what you're trying to do.
Not really. Consider how a browser typically downloads a file: it opens a TCP socket connection to a remote server, either on port 23 or 80, and using the FTP protocol or HTTP protocol on that connection. These things you can detect, intercept and modify with high reliability. But there are other programs that use other mthods. for instance, P2P filesharing programs such as BitTorrent do not use HTTP or FTP, nor do they download a file from a single server.
So, while you don't need to understand every program, you must be able to detect and understand every file download protocol instead.
you could hook the network stream and filter for http download requests.
you'll need some library to capture network traffic (e.g. http://en.wikipedia.org/wiki/Pcap).
Then you'll have to parse the network packets for the appropriate HTTP messages (sorry, I can't give them to you, I don't know them). I don't know if you can actually prevent packets from being sent though.
Another (easier) way would be to implement a proxy server (or modify an existing one) to do what you want. Then you just have to connect the IE to your proxy using the proxy server settings. Check for example Privoxy, which already does some kind of filtering.