Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine netmask of active interface in Objective-C on a Mac?

I'm trying to determine the network segment my Macbook is in, because I then want to scan this segment for active hosts (basic IP scanner) by using the CFHost class. Therefore I need the IP and Netmask of my active interface. This is how I get the IP:

NSString *ipAddr = [[[NSHost currentHost] addresses] objectAtIndex:0];

But I have absolutely no idea how to get the Netmask, so I'm kind of stuck. Especially because I'm fairly new at Objective-C and because I also do not have extensive knowledge of plain C. I've looked at CFHost, CFNetwork, NSHost and various Google hits, but have found nothing useful, so far.

As a last resort I could do a system call of sorts, I suppose, or read it from a file (which one?), but I want to avoid that, if possible.

So, how do I get the matching netmask to the ip obtained through NSHost? Any suggestions would be greatly appreciated.

Thanks!

like image 250
Martin Avatar asked Dec 03 '22 07:12

Martin


1 Answers

So, to wrap this up, I did finally get around to investigating the System Configuration API. As always, once you know how it's not that difficult.

@0xced - Thanks for pointing me in the right direction. I'd upvote your answer, but I do not have enough reputation to do so.

This is my solution, for anyone who is curious or in the same situation. It involves digging in the dynamic store. See this for infos on the API. You can look at the information the dynamic store holds by using the scutil command line utility (see x-man-page://8/scutil ).

Here are my steps. First, you need a session:

SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL);

Then, I try to get the primary interface (en1, for example):

CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Global/IPv4"));
NSString *primaryInterface = [(__bridge NSDictionary *)global valueForKey:@"PrimaryInterface"];

Last, I build a string containing the interface to be able to query the right key. It should look something like State:/Network/Interface/en1/IPv4, depending on the interface, of course. With that I am able to get an array with the ip and the netmask. On my Macbook these arrays hold only one ip and netmask, respectively. I suppose it is possible this could be different for other Macs, I will have to verify that. For my test I simply took the first (and only) element in the array, but some sort of checking for size would have to be implemented there.

NSString *interfaceState = [NSString stringWithFormat:@"State:/Network/Interface/%@/IPv4", primaryInterface];

CFPropertyListRef ipv4 = SCDynamicStoreCopyValue (storeRef, (CFStringRef)interfaceState);
CFRelease(storeRef);

NSString *ip = [(__bridge NSDictionary *)ipv4 valueForKey:@"Addresses"][0];
NSString *netmask = [(__bridge NSDictionary *)ipv4 valueForKey:@"SubnetMasks"][0];
CFRelease(ipv4);

This is just for testing, so it is a little rough around the edges. You will have to look for retain counts and the like. It was only written to get an idea of how it could be done.

like image 83
Martin Avatar answered Dec 25 '22 04:12

Martin