C/C++ Get IP for interface programmaticly

Discussion in 'Mac Programming' started by hiddenpremise, Jul 4, 2009.

  1. macrumors regular

    hiddenpremise

    Joined:
    Jul 25, 2008
    Location:
    Somewhere between my imagination and reality
    #1
    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
    Code:
    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
    Code:
    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
    Code:
    system("my shell script");
    into a string..

    Any help is much appreciated :)
    Thanks,
    Whit
     
  2. macrumors 6502

    Joined:
    Mar 8, 2009
    Location:
    Denver, CO
    #2
    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
     
  3. macrumors 6502

    Joined:
    Feb 23, 2008
    #3
    Take a look at ifmib and sysctl (3).
     
  4. macrumors regular

    Joined:
    Sep 11, 2008
    #4
    This should work on both the Mac & iPhone:

    Code:
    -(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])]);
    }
     
  5. thread starter macrumors regular

    hiddenpremise

    Joined:
    Jul 25, 2008
    Location:
    Somewhere between my imagination and reality
    #5
    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

    Thanks mate, I've got this semi-working now.
    Code:
    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?
     
  6. macrumors 6502a

    Joined:
    Mar 19, 2008
    Location:
    North Shore, MA
    #6
    '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?)
     
  7. thread starter macrumors regular

    hiddenpremise

    Joined:
    Jul 25, 2008
    Location:
    Somewhere between my imagination and reality
    #7
    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.
     
  8. macrumors 6502a

    Joined:
    Mar 19, 2008
    Location:
    North Shore, MA
    #8
    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.
     
  9. macrumors 6502

    Joined:
    Mar 8, 2009
    Location:
    Denver, CO
    #9
    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.
     
  10. macrumors newbie

    Joined:
    Oct 20, 2008
    #10
    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
     

Share This Page