iOS - Get device's DNS server address on IPv6 only network - ios

I am trying to get device's DNS server address while connected to IPv6 only network on iOS. The following code works well for when connected to IPv4 network but doesn't work on IPv6 network. Code taken from this answer.
res_ninit(&_res);
res_state res = &_res;
for (int i=0; i < res->nscount; i++) {
sa_family_t family = res->nsaddr_list[i].sin_family;
if (family == AF_INET) {
NSLog(#"IPv4");
char str[INET_ADDRSTRLEN]; // String representation of address
inet_ntop(AF_INET, & (res->nsaddr_list[i].sin_addr.s_addr), str, INET_ADDRSTRLEN);
} else if (family == AF_INET6) {
NSLog(#"IPv6");
char address[INET6_ADDRSTRLEN]; // String representation of address
inet_ntop(AF_INET6, &(res->nsaddr_list [i].sin_addr.s_addr), address, INET6_ADDRSTRLEN);
} else {
NSLog(#"Unspecified");
}
}
On IPv6 network, sin_family is always AF_UNSPEC. Any suggestions/alternatives?

Try using res._u._ext.nsaddrs for IPv6.
See https://chromium.googlesource.com/chromium/src/+/master/net/dns/dns_config_service_posix.cc#437

Related

Find the device(IP camera) IP address present in LAN network using iOS device?

I am working on project, which has find the camera IP-address which is connect in LAN network, i am using LAN search for iOS to find the camera, it works but some times camera has self assigned to (169.254.164.XXX) default IP address. LAN search can’t find it. How can i find the all camera which is present in LAN network, even though camera in default network?
This will returns local IP Address:
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == 2) {
// Check if interface is end which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}

Resolve NetBIOS name on iOS

Is there any way on iOS to resolve NetBIOS name using IP address?
One could resolve NetBIOS name on a Mac using terminal command:
smbutil -v status -ae
The smbutil is opensourced so you can find it here:
http://www.apple.com/opensource/ -> http://opensource.apple.com//source/smb/
And the same on GitHub:
https://github.com/unofficial-opensource-apple/smb
But the util extensively uses private and Mac OS-specific frameworks so Xcode couldn't even compile the source for iOS.
I think you just need to do a reverse DNS lookup, gethostbyaddr, because it looks like DNS, gethostbyname, is the only thing being used to go from NetBios name to IP.
Looking at the source from Apple, the smbutil application in the 'status' mode first calls 'nb_resolvehost' which just uses 'gethostbyname' to get the IP address from NetBios name. 'gethostbyname' uses DNS under the hood:
nb_resolvehost_in(const char *name, struct sockaddr **dest)
{
struct hostent* h;
struct sockaddr_in *sinp;
int len;
h = gethostbyname(name);
if (!h) {
warnx("can't get server address `%s': ", name);
herror(NULL);
return ENETDOWN;
}
if (h->h_addrtype != AF_INET) {
warnx("address for `%s' is not in the AF_INET family", name);
return EAFNOSUPPORT;
}
if (h->h_length != 4) {
warnx("address for `%s' has invalid length", name);
return EAFNOSUPPORT;
}
len = sizeof(struct sockaddr_in);
sinp = malloc(len);
if (sinp == NULL)
return ENOMEM;
bzero(sinp, len);
sinp->sin_len = len;
sinp->sin_family = h->h_addrtype;
memcpy(&sinp->sin_addr.s_addr, h->h_addr, 4);
sinp->sin_port = htons(SMB_TCP_PORT);
*dest = (struct sockaddr*)sinp;
return 0;
}
After this call the 'smbutil status' then sends some sort of SMB query using the function 'nbns_getnodestatus' to the previously given IP address on the SMB port. From this query the command gets Workgroup and Servername (not sure which server this is referring to).

how to resolve the hostname of a device in my LAN from its ip address on this LAN?

I have to resolve the hostname of a device in my LAN from its ip address on this LAN.
I have some code that works for external ip address but not the internally connected devices .
Below i have attached the code .
if you have any idea to get hostname of remote machine from it's IP in iOS/OSX, it'll make my day.
int error;
struct addrinfo *results = NULL;
error = getaddrinfo("173.194.34.24", NULL, NULL, &results);
if (error != 0)
{
NSLog (#"Could not get any info for the address");
}
for (struct addrinfo *r = results; r; r = r->ai_next)
{
char hostname[NI_MAXHOST] = {0};
error = getnameinfo(r->ai_addr, r->ai_addrlen, hostname, sizeof hostname, NULL, 0 , 0);
if (error != 0)
{
continue; // try next one
}
else
{
NSLog (#"Found hostname: %s", hostname);
break;
}
}
freeaddrinfo(results);
or with NSHost
NSLog(#"%# \n%#",[NSHost currentHost],[[NSHost hostWithAddress:#"172.17.241.61"] names]);
Only way to make a DNS lookup directly to a specific DNS is to implement the protocol yourself or use some library.
https://serverfault.com/questions/173187/what-does-a-dns-request-look-like
https://www.ietf.org/rfc/rfc1035.txt
https://github.com/adeboer/rfc1035lib

Is it possible in some way to convert IPV6 address to IPV4 address or else retrieve the IPV4 address always?

We are developing an iOS application for ipad that uses bonjour for conneting with other devices and couchbaseListener for replications with peer databases.
We have observed that whenever [nsnetservice addresses] returns IPV6 address ,replication is not suuccesful.
We get the IPV4 address only when bluetooth is switched on randomly i.e 1 out of 5 times. In addition, [NSNetService addresses] returns only one address from the array. Is it possible in some way to convert IPV6 address to IPV4 address or else retrieve the IPV4 address always?
Please find the code used for converting to Ip address below.
char addressBuffer[INET6_ADDRSTRLEN];
for (NSData *data in self.addresses)
{
memset(addressBuffer, 0, INET6_ADDRSTRLEN);
typedef union {
struct sockaddr sa;
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
} ip_socket_address;
ip_socket_address *socketAddress = (ip_socket_address *)[data bytes];
if (socketAddress && (socketAddress->sa.sa_family == AF_INET || socketAddress->sa.sa_family == AF_INET6))
{
const char *addressStr = inet_ntop(
socketAddress->sa.sa_family,
(socketAddress->sa.sa_family == AF_INET ? (void *)&(socketAddress->ipv4.sin_addr) : (void *)&(socketAddress->ipv6.sin6_addr)),
addressBuffer,
sizeof(addressBuffer));
int port = ntohs(socketAddress->sa.sa_family == AF_INET ? socketAddress->ipv4.sin_port : socketAddress->ipv6.sin6_port);
if (addressStr && port)
{
NSLog(#"Found service at %s:%d", addressStr, port);
}
}
}
The IPv6 address itself contains the IPv4 address encoded in hexadecimal (after the ::)
Let's say you have the following IPv6 address: 2608::c0a8:1 (compact form)
This translates to the following IPv4 address: 192 (c0) . 168 (a8) . 0 (00 omitted) . 1 (01)
It may depend of the IPv6 address format but that's essentially the way to do.
If you aren't sure, you can try this converter: http://v6decode.com/#address=2608%3A%3Ac0a8%3A1

how can i get programmaticaly in Objective-C the name of local domain Knowing the ip adress?

Hi have many iPad in 2 differents local networks and I want to know programatically in Objective-C the local domain based in the IP address in each iPad.
for example I have an iPad in local domain "project.local". In this domain we have many IP address as 192.168.12.50. The IOS device get automaticaly their ip address.
Now I want to get programmaticaly in objective-C the domain name "projet.local" knowing the ip address??
Try this (similar to dreamlax's answer https://stackoverflow.com/a/3575383/1758762):
struct addrinfo *results = NULL;
char hostname[NI_MAXHOST] = {0};
if ( getaddrinfo("192.168.12.50", NULL, NULL, &results) != 0 )
return;
for (struct addrinfo *r = results; r; r = r->ai_next)
{
if (getnameinfo(r->ai_addr, r->ai_addrlen, hostname, sizeof hostname, NULL, 0 , 0) != 0)
continue; // try next one
else
{
NSLog (#"Found hostname: %s", hostname);
break;
}
}
freeaddrinfo(results);

Resources