PDA

View Full Version : C/C++ Get IP for interface programmaticly




hiddenpremise
Jul 4, 2009, 10:20 PM
I am trying to accomplish something so very simple, and yet I can't seem to figure it out. What I need: a NSString containing the IP address given to a particular interface. Most importantly, I want to accomplish this programmaticly, not through some sort of shell script. I have searched for several days, and no one else seems to have had this problem.... which means it is probably so simple no one had to ask...

I am rather unskilled in C. My approach so far has been this
char hostname[30];
gethostname(hostname, 30);
hostent * record = gethostbyname(hostname);
in_addr * address=(in_addr * )record->h_addr;
std::string ipstring = inet_ntoa(* address);
NSString *addressstr = [NSString stringWithCString:ipstring.c_str() encoding:NSUTF8StringEncoding];

Unfortunately, this does not give me a specific interface and it does not give me anything but my bonjour ip. My gethostname() returns iWhit.local. I end up with something like 10.211.55.2 instead of 192.168.2.1

In a shell script I would use

ifconfig en1 | grep -E "inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})" | awk '{print $2}'

but I don't want to use a shell script if at all possible... Plus I haven't been able to figure out how to get the output from
system("my shell script");
into a string..

Any help is much appreciated :)
Thanks,
Whit



jpyc7
Jul 4, 2009, 11:24 PM
Maybe try the getifaddrs function? The man page says it will return a list of interfaces and information about those interfaces. I don't know how/if you know which interface you are interested in consistently.

If you were to look for source code for the "ifconfig" utility, I suspect it uses the getifaddrs function.

If you aren't familiar with using man, basically just type "man getifaddrs" in a Terminal window.

Here is a link on Apple's website too:
http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/getifaddrs.3.html

jw2002
Jul 5, 2009, 12:00 AM
Take a look at ifmib and sysctl (3).

idelovski
Jul 5, 2009, 08:21 AM
This should work on both the Mac & iPhone:

-(NSString *)getIPAddress
{
char baseHostName[256], fullHostName[256];
struct hostent *host;
struct in_addr **hList;

gethostname (baseHostName, 255);
if (!strstr(baseHostName, ".local"))
sprintf (fullHostName, "%s.local", baseHostName);
else
strcpy (fullHostName, baseHostName);

host = gethostbyname (fullHostName);

if (!host)
return (@"");

hList = (struct in_addr **)host->h_addr_list;
return ([NSString stringWithCString:inet_ntoa(*hList[0])]);
}

hiddenpremise
Jul 5, 2009, 03:24 PM
This should work on both the Mac & iPhone:
This only gives me the bonjour address which is something like 10.52.22.1 instead of the 192.168.2.1 that I am looking for

Maybe try the getifaddrs function?

Thanks mate, I've got this semi-working now.
struct ifaddrs * addrs, * ifloop;
char buf[64];
struct sockaddr_in *s4;
const char * en0 = "en0";
getifaddrs(&addrs);
for (ifloop = addrs; ifloop != NULL; ifloop = ifloop->ifa_next)
{
s4 = (struct sockaddr_in *)(ifloop->ifa_addr);
inet_ntop(ifloop->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf)) == NULL;
const char * ifname = ifloop->ifa_name;
if (strncmp(ifname, en0, 2) == 1)
{
printf("%s: %s\n", ifloop->ifa_name, buf);
}
}
Problem is strncmp(ifname, en0, 2) doesn't give me en0, it gives me en1 and fw0. It is the most bizzare thing. Am I missing something basic about string comparisons?

Guiyon
Jul 5, 2009, 03:59 PM
'10.211.55.2' is not a bonjour address, it is a valid local IP address! All link-local IP addresses (self-configured, zeroconf, etc.) are in the 169.254.0.0/16 range. Any IP in the 10.0.0.0/8, 192.168.0.0/16 or 172.16.0.0/12 ranges is designated for private use and either manually assigned or assigned by a DHCP server. if you have not manually configured anything and you don't have a 169.254.0.0/16 address then there is a DHCP server on your network somewhere handing out addresses in that range.

Edit: Looked at your code. First of all, you're leaking memory from the getifaddrs() call. Second, that strncmp function isn't doing what you think it's doing (and your 'n' value is off by one); you might want to check the manpage on it (hint: what does it return?)

hiddenpremise
Jul 6, 2009, 11:28 AM
Thanks for the replys all

Edit: Looked at your code. First of all, you're leaking memory from the getifaddrs() call. Second, that strncmp function isn't doing what you think it's doing (and your 'n' value is off by one); you might want to check the manpage on it (hint: what does it return?)

I am blind as to how getifaddrs() is leaking memory, sorry I'm piss poor with C. How would I fix that or could you point me to a good article on C memory management? Thanks for the pointer on strncmp, i actually just converted to NSStrings and used obj-c's isEqualToString: function.

Guiyon
Jul 6, 2009, 11:42 AM
I am blind as to how getifaddrs() is leaking memory

Check out the manpage for getifaddrs, specifically the last sentence in the "Description" section. As for C's memory management, it can be summed up in one short sentence: If you allocate it, you need to free it. Generally, unless their documentation states otherwise, anything which returns a pointer or takes a double-indirect pointer as an argument is probably allocating something.

jpyc7
Jul 6, 2009, 11:44 AM
Thanks for the replys all


I am blind as to how getifaddrs() is leaking memory, sorry I'm piss poor with C. How would I fix that or could you point me to a good article on C memory management? Thanks for the pointer on strncmp, i actually just converted to NSStrings and used obj-c's isEqualToString: function.

From the manpage (toward the end of Description section):
"The data returned by getifaddrs() is dynamically allocated and should be freed using freeifaddrs() when no longer needed."

So just call freeifaddrs(addrs) when done.

bliblablo
Oct 2, 2009, 05:20 AM
Does anybody got a solution to get the IP Address if you are on a 3G network and connected to a router via VPN (PPTP).
In the VPN menu i can see my ip address given from my router (192.168.1.100) but when i try to get it programmatically i can't get anything...
getifaddrs(...) does not seem to work :(

Thanks for your help