gethostbyaddr() has error 11001 - winsock

I'm writing simple program to communicate between smart devices and I receive 11001 when calling gethostbyaddr(). Both devices show they are connected to the same network, but from msdn document 11001 error is Host not found. No such host is known. Does anybody have any suggestion, thanks? My code is below.
void InitializeSocket()
{
WORD socketVersion;
WSADATA wsaData;
SOCKADDR_IN serverInfo;
int returnVal;
LPHOSTENT remotHost;
socketVersion = MAKEWORD(2,2);
WSAStartup(socketVersion, &wsaData);
in_addr iaHost;
//iaHost.s_addr = inet_addr("120.15.22.14");
iaHost.S_un.S_un_b.s_b1 = 120;
iaHost.S_un.S_un_b.s_b2 = 15;
iaHost.S_un.S_un_b.s_b3 = 22;
iaHost.S_un.S_un_b.s_b4 = 14;
remotHost = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr),
AF_INET);
if(iaHost.s_addr == INADDR_NONE)
{
MessageBox(NULL, TEXT("inet_addr has invalid address"),
TEXT("inet_addr"), MB_OK);
WSACleanup();
closesocket(theSocket);
return;
}
if(!remotHost)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(theSocket == INVALID_SOCKET)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*remotHost->h_addr_list);
serverInfo.sin_port = htons(8888);
//Connect to the server
returnVal = connect(theSocket, (LPSOCKADDR)&serverInfo,
sizeof(struct sockaddr));
if(returnVal == SOCKET_ERROR)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
}

Error 11001 is a generic DNS lookup error so I have only one question. Does the 120.15.22.14 address actually exist in DNS?
You can find this out by typing
nslookup 120.15.22.14
from the command line.
If you get an error, it's because DNS doesn't know anything about those addresses, so a gethostbyaddr() will not be able to give you any information.
Update:
Answering your points:
I just type nslookup 120.15.22.14, but it returns back as cant find 120.15.22.14. Non-existent domain.
Since nslookup 120.15.22.14 returns an error, there is no entry in DNS for that IP address. That's your problem.
I look at my device settings for the DNS and it sets to 120.20.32.10 which is different 120.15.22.14 so does it mean I haven't configured the DNS?
If 120.20.32.10 is what's in DNS for your device, and 120.15.22.14 is the actual address, then DNS is wrong. Plain and simple. Fix DNS.
will it produce the same result if I use gethostbyname() instead of gethostbyaddr()?
If you want to turn a DNS name into an IP address, use gethostbyname(). To turn an IP address into a DNS name, use gethostbyaddr().
For connecting to a remote host, you would normally use the gethostbyname() call since the IP address of the host could change at any time. Provided DNS always accurately represents the IP address of that host, that's the preferred way.

I just type nslookup 120.15.22.14, but it returns back as cant find 120.15.22.14. Non-existent domain.
I look at my device settings for the DNS and it sets to 120.20.32.10 which is different 120.15.22.14 so does it mean I haven't configured the DNS?

Related

Esp8266 webserver restart after IP changed

I'm trying to access a webserver after I've changed IP addresses on my ESP8266 arduino sketch, but it's not responding (but a ping is).
The sketch starts in WIFI_AP mode (for device testing purposes), but if a network is discovered after an asynchronous WiFi scan, the call back code disconnects the WiFi and then creates a connection in WIFI_AP_STA mode (acting as a secondary network access point).
ESP8266WebServer webServer(80);
void myWifiScanCompleted( int networksFound ) {
IPAddress ip(192,168,1,2); // fixed IP address of this access point
IPAddress gateway(192,168,1,254);
IPAddress subnet(255,255,255,0);
int count;
int quality;
networkConnection = NET_CONNECT_NONE; // initialise as not found
for(count = 0; count < networksFound; count++) {
quality = getRSSIasQuality( WiFi.RSSI(count) );
if(strcmp(WiFi.SSID(count).c_str(), ap_ssid ) == 0) {
debug_print("found network %s (%d\%)", ap_ssid, quality);
networkConnection = NET_CONNECT_FOUND;
break;
} else {
debug_print("ignoring network %s (%d\%)", WiFi.SSID(count).c_str(), quality);
}
}
if(networkConnection == NET_CONNECT_FOUND) { // found network = try to connect
// reset any existing connection
webServer.stop();
WiFi.disconnect();
delay(100);
WiFi.mode(WIFI_AP_STA); // need both modes to join the network to get IP address, and then create access point
WiFi.begin(ap_ssid, ap_password);
count = 0;
while (WiFi.status() != WL_CONNECTED) {
toggle_led(); // Blink the LED
if(++count > (15 * 10)) {
debug_print("error connecting to network %s", ap_ssid);
networkConnection = NET_CONNECT_NONE;
break; // failed to connect
}
delay(100);
}
if(networkConnection != NET_CONNECT_NONE) {
networkConnection = NET_CONNECT_CONNECTED; // we've successfully connected to the network, now set up the access point
ip = WiFi.localIP();
gateway = (uint32_t)0;
kev_softAPConfig(ip, gateway, subnet, false); // no DHCP server
if(! kev_softAP(ap_ssid, ap_password, MY_WIFI_CHANNEL, MY_WIFI_HIDDEN, MY_WIFI_MAX_CONNECTIONS)) {
debug_print("create %s softAP failed - performing network reset", ap_ssid);
WiFi.disconnect();
networkConnection = NET_CONNECT_NONE;
} else {
// access point started = restart server
webServer.begin(); // start web server on the new IP address
debug_print("create %s softAP OK", ap_ssid);
}
}
}
}
The functions kev_softAPConfig() and kev_softAP() are modified versions of the API that do NOT start the dhcp service (which already exists on the network).
I've proved these functions work, I've just changed the order of things so that I can provide device testing features.
Has anyone achieved this, or am I a pioneer? :-)
I found that I had to use a different IP range for the access point from the WiFi.localIP() allocated to the station by the network DHCP server, which meant having to write some proxy code to communicate across networks.

connect to remote server using sockets unix

In unix, I want to make a client program connect to a server running on different machine. For this, I need to enter the ip address of server through keyboard and then pass that ip address in the connect() system call of client. I tried reading as a string, and passing it.But it didnt work. Is there any specific way to pass the ip address?
Assuming IPv4, the function you're looking for is inet_addr, which converts the string representation of an IPv4 address to a numerical value which can be passed into various socket functions:
int get_connection(const char *ip, int port)
{
int sock;
struct sockaddr_in sin;
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_port = htons(port);
if ((sock=socket(AF_INET,SOCK_STREAM,0))==-1) {
perror("Error creating socket");
return -1;
}
if (connect(sock,(struct sockaddr *)&sin,sizeof(sin))==-1) {
perror("Couldn't connect");
close(sock);
return -1;
}
return sock;
}

Can't listen on multiple sockets when using BINDTODEVICE?

I have two network links to the Internet, and I have two default routes set up:
Destination Gateway Genmask Flags Metric Ref Use Iface
default gateway0 0.0.0.0 UG 0 0 eth0
default gateway1 0.0.0.0 UG 0 0 eth1
...
I created two sockets with BINDTODEVICE, so that I can send data out either eth0 or eth1. I am also trying to listen on both sockets using recvfrom (UDP data only), but I can only successfully read data from whichever interface is listed first in the routes. eth0 works, for example, but I get nothing from the socket bound to eth1.
Running wireshark on either interface shows data coming in successfully - that is, I can see data being sent from the Internet to either eth0's or eth1's IP in Wireshark (so NAT is not a problem with either), but my program just blocks on recvfrom without getting any data.
I have tried using bind on the sockets to make them listen on their respective interface's IP, and also tried not using bind to have them listen on 0.0.0.0 (each on a different port), but I still have the same problem.
How can I make sure both sockets get the data they're supposed to?
Edit: sample code:
int createDeviceBoundUDPSocket(uint32_t sip, uint16_t sport, const char* bind_dev) {
printf("bind_dev = %s", bind_dev);
int s = socket(AF_INET, SOCK_DGRAM, 0);
int result;
struct sockaddr_in my_ip_addr;
if (s < 0) {
perror("socket");
return s;
}
memset(&my_ip_addr, 0, sizeof(my_ip_addr));
my_ip_addr.sin_family = AF_INET;
my_ip_addr.sin_addr.s_addr = htonl(sip);
my_ip_addr.sin_port = htons(sport);
// commenting this section out doesn't seem to make a difference
// listening on 0.0.0.0 or the interface's IP both have the same problem
result = bind(s, (struct sockaddr*)(&my_ip_addr), sizeof(my_ip_addr));
if (result < 0) {
perror("Error in bind");
return result;
}
if (bind_dev) {
// Bind to specific device.
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
bind_dev, strlen(bind_dev) + 1)) {
perror("Error binding to device");
return -1;
}
}
return s;
}
The solution, as hinted by the Linux Advanced Routing and Traffic Control guide, is to turn off reverse path filtering. Not sure which of the three interfaces needed to have it turned off, but doing
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
made it work.

ios - Determine if a certain address with a certain port is reachable

I want to know if my server is online via my ios application. Here's what I'm doing:
Boolean result;
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFDataRef)(serverIPAddress)); //serverIPAdress = "10.10.10.100:5010"
if(hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
}
if (!result) { //This means that the host was unreachable
return ;
}
My server is online and I can access it later on in the code(meaning that my connection to the server works perfectly fine). However, I want to be able to detect if my server, on a certain port, is reachable.
Also, if I remove the ":5010" from the ip address, it detects that my server is online (it doesn't go in the "!result" condition) and detects that my server is offline if I put "10.10.10.253" which corresponds to no ip address on my network.
How can I manage to determine if my server is online or not ?
I've looked at this question : Reachability with Address - Server AND Port - iOS 5 but it doesn't work since it always return that it is reachable no matter what ip address I enter
Thanks in advance
One approach could be to open a socket connection to a specific port to see if you get any response back. If not, then the destination is unreachable. For example
#include <arpa/inet.h> //for PF_INET, SOCK_STREAM, IPPROTO_TCP etc
CFRunLoopSourceRef gSocketSource;
void ConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
UInt8 buffer[1024];
bzero(buffer, sizeof(buffer));
CFSocketNativeHandle sock = CFSocketGetNative(socket); // The native socket, used recv()
//check here for correct connect output from server
recv(sock, buffer, sizeof(buffer), 0);
printf("Output: %s\n", buffer);
if (gSocketSource)
{
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
if (CFRunLoopContainsSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode))
{
CFRunLoopRemoveSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode);
}
CFRelease(gSocketSource);
}
if (socket) //close socket
{
if (CFSocketIsValid(socket))
{
CFSocketInvalidate(socket);
}
CFRelease(socket);
}
}
void ConnectSocket()
{
//socket
CFSocketContext context = {0, NULL, NULL, NULL, NULL};
CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack , (CFSocketCallBack)ConnectCallBack, &context);
//address
struct sockaddr_in socketAddress;
memset(&socketAddress, 0, sizeof(socketAddress));
socketAddress.sin_len = sizeof(socketAddress);
socketAddress.sin_family = AF_INET;
socketAddress.sin_port = htons(5010);
socketAddress.sin_addr.s_addr = inet_addr("10.10.10.253");
gSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, theSocket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), gSocketSource, kCFRunLoopDefaultMode);
CFDataRef socketData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&socketAddress, sizeof(socketAddress));
CFSocketError status = CFSocketConnectToAddress(theSocket, socketData, 30); //30 second timeout
//check status here
CFRelease(socketData);
}
Basically, if the server is unreachable at that port, you will most likely get a kCFSocketTimeout for CFSocketError status. If you are looking to parse a specific response back from the server to determine if the server is ready or not, the ConnectCallBack function will be called upon successful socket connection.
This is just a simple example, make sure not to block the UI by calling socket connections on the main thread such as recv()

Reachability with Address - Server AND Port - iOS 5

I am trying to check whether a server is online or offline: I face the problem that it has a port when connecting to it
My code at the moment:
struct sockaddr_in address;
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_port = htons(25667);
address.sin_addr.s_addr = inet_addr("fr7.mooshroom.net");
Reachability *reachability = [Reachability reachabilityWithAddress:&address];
Please let me know what im doing wrong. And please dont link me to other questions, I have searched and none of them have what I'm looking for.
Basically the inet_addr() function does not do domain name resolution for you. You need to pass it an IP address (for example 127.0.0.1).
To resolve a DNS name into an IP address you need to look at the standard gethostbyname() functions.
To clarify:
struct hostent *host = gethostbyname("fr7.mooshroom.net");
if (host) {
struct in_addr in;
NSLog(#"HOST: %s" , host->h_name);
while (*host->h_addr_list)
{
bcopy(*host->h_addr_list++, (char *) &in, sizeof(in));
NSLog(#"IP: %s", inet_ntoa(in));
}
}
Now, having said all that, are you sure this is going to do what you want? Documentation for SCNetworkReachabilityRef suggests not:
http://developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/SCNetworkReachabilityRef/Reference/reference.html
"A remote host is considered reachable when a data packet, sent by an
application into the network stack, can leave the local device.
Reachability does not guarantee that the data packet will actually be
received by the host."
I have fixed it now, i needed to put the line:
const char *serverIPChar = [serverIP cStringUsingEncoding:NSASCIIStringEncoding];
and replace the "fr7.mooshroom.net" inside the inet_addr to serverIPChar. Thanks anyway