Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > getting multiple IP addresses

getting multiple IP addresses
Thread Tools
stupidFish23
Forum Regular
Join Date: Jan 2002
Location: Hungary
Status: Offline
Reply With Quote
May 27, 2002, 05:41 AM
 
Hi!

I have already posted this at omnigroup's cocoa dev mailing list, but can!t seem to get an answer for what I am looking for. I want to get all IP address of my mac. Now I tried [[NSHost currentHost] addresses], but it only returns one IP address, the one of my cable modem's DHCP connection, but not the one for my AirPort IP. How can I get the Airport IP? On my iBook, which has only one IP, namely the one for AirPort connection with my desktop G4, [[NSHost currentHost] addresses] returns 127.0.0.1, which is the machine's internal server IP assress.

Any ideas?

<img border="0" alt="[Skeptical]" title="" src="graemlins/bugeye.gif" />

Thanks...
nothing is when everything is alright
[email protected] ICQ: 153647416
     
lindberg
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
May 27, 2002, 11:12 PM
 
NSHost will give you the addresses given in DNS (or NetInfo) to the local hostname -- typically just one, and if the hostname is "localhost", then you'll get 127.0.0.1 .

To get the addresses for each local interface, that's an entirely different kettle of fish, and it has nothing to do with DNS. You basically have to walk the interface list, getting the interface address for each interface.
The code to do it is in the ifconfig command (see the Darwin CVS repository), and it basically uses sysctl(3) to get the interface
information (found in routing table messages).

If you have no experience in the depths of BSD networking code, this may not be for you. For what it's worth however, here is some code to do it. This just gets AF_INET addresses; if you want AF_INET6 (IPv6, coming in MacOS X 10.2 I think) you'll have to alter the code. I doubt you'll care
about that for quite a while to come though.

The code is mostly paraphrased from the code to the ifconfig command. Copy this into a "ifenum.m" file, and compile with "cc ifenum.m -o ifenum -framework Foundation".

</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">#import &lt;Foundation/NSDictionary.h&gt;
#import &lt;Foundation/NSString.h&gt;

#include &lt;sys/param.h&gt;
#include &lt;sys/sysctl.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;net/route.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;net/if.h&gt;
#include &lt;net/if_dl.h&gt;
#include &lt;stdlib.h&gt;

/*
* The rt_addrinfo struct has an array of sockaddr pointers, with each slot
* being a possible type of address (interface, broadcast, netmask, etc.). Since
* there are 8 slots, a lot of these are empty. The sysctl() call comes back
* with a &quot;packed&quot; array, with the sockaddr structures all back to back, and the
* rti_addrs field a mask specifying which ones are there. This function expands
* it into the full rt_addrinfo struct. Stolen directly from ifconfig, as I have
* no desire to figure out the actual bits here.
*/
#define ROUNDUP(a) \
((a) &gt; 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)-&gt;sa_len))

static void rt_expand_addrs(void *cp, void *cplim, struct rt_addrinfo *rtinfo)
{
struct sockaddr *sa;
int i;

memset(rtinfo-&gt;rti_info, 0, sizeof(rtinfo-&gt;rti_info));
for (i = 0; (i &lt; RTAX_MAX) &amp;&amp; (cp &lt; cplim); i++) {
if ((rtinfo-&gt;rti_addrs &amp; (1 &lt;&lt; i)) == 0)
continue;
rtinfo-&gt;rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}

NSDictionary *HostAddresses()
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *interfaceName;

int mib[6];
char *buffer, *end;
size_t buffsize = 0;

/*
* The sysctl() setup to get the interface list out of the routing table. We
* expect an RTM_IFINFO message followed by zero or more RTM_NEWADDR
* messages for each interface. struct if_msghdr is the basic structure,
* with other message types defining additional fields in specific structures.
*/
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;

/* A dummy sysctl to get the memory size needed, malloc, then the real call */
if (sysctl(mib, 6, NULL, &amp;buffsize, NULL, 0) &lt; 0)
return nil;
if ((buffer = (char*)malloc(buffsize)) == NULL)
return nil;
if (sysctl(mib, 6, buffer, &amp;buffsize, NULL, 0) &lt; 0)
return nil;

end = buffer + buffsize;

while (buffer &lt; end)
{
struct if_msghdr *if_header = (struct if_msghdr *)buffer;
int if_flags = 0;

/* The interface info route message; should be first */
if (if_header-&gt;ifm_type == RTM_IFINFO)
{
struct sockaddr_dl *sdl;

if_flags = if_header-&gt;ifm_flags; //flags for this interface
sdl = (struct sockaddr_dl *)(if_header+1); // sockaddr_dl is extra field; has the name
interfaceName = [NSString stringWithCString:sdl-&gt;sdl_data length:sdl-&gt;sdl_nlen];
}
else if (if_header-&gt;ifm_type == RTM_NEWADDR)
{
struct ifa_msghdr *ifam;
struct rt_addrinfo info;

/* this message is a ifa_msghdr structure */
ifam = (struct ifa_msghdr *)if_header;

/* the packed address array (data follows ifam header) into an rt_addrinfo structure. */
info.rti_addrs = ifam-&gt;ifam_addrs;
rt_expand_addrs((char *)(ifam+1), ifam-&gt;ifam_msglen+(char*)ifam, &amp;info);

// make sure we have the right family
if (info.rti_info[RTAX_IFA]-&gt;sa_family == AF_INET)
{
NSString *address;
struct sockaddr_in *sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
unsigned char *addr = (unsigned char *)&amp;sin-&gt;sin_addr;

address = [NSString stringWithFormat:@&quot;%d.%d.%d.%d&quot;, addr[0], addr[1], addr[2], addr[3]];
if (interfaceName != nil) //should always be set, but...
[dict setObject:address forKey:interfaceName];

// if (if_flags &amp; IFF_POINTTOPOINT), then info.rtf_info[RTAX_BRD] is the dest address. Do we care?
}
// AF_INET6 has a different sockaddr type...
}
else
{
#if DEBUG
printf(&quot;Unexpected route message type: %d\n&quot;, if_header-&gt;ifm_type);
#endif
}

buffer += if_header-&gt;ifm_msglen; //increment the buffer to the next message
}

return dict;
}



#import &lt;Foundation/Foundation.h&gt;
int main()
{
id pool = [[NSAutoreleasePool alloc] init];
NSDictionary *addresses = HostAddresses();
NSEnumerator *ifEnum = [addresses keyEnumerator];
NSString *iface;

while (iface = [ifEnum nextObject])
{
printf(&quot;%s: %s\n&quot;, [iface cString], [[addresses objectForKey:iface] cString]);
}

[pool release];
exit(0);
return 0;
}</pre><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">
     
stupidFish23  (op)
Forum Regular
Join Date: Jan 2002
Location: Hungary
Status: Offline
Reply With Quote
May 28, 2002, 12:31 AM
 
WoW!

Now that's some serious code! Thanks! I'll check it out and see how far I can get. Thanks again.

Ben <img border="0" title="" alt="[Wink]" src="wink.gif" />
nothing is when everything is alright
[email protected] ICQ: 153647416
     
Angus_D
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
May 28, 2002, 04:08 PM
 
You might also like to check out the SystemConfiguration framework.
     
   
 
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Top
Privacy Policy
All times are GMT -4. The time now is 06:54 PM.
All contents of these forums © 1995-2017 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.8 © 2000-2017, Jelsoft Enterprises Ltd.,