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

I am trying to determine the network segment where my Macbook is located because I want to scan this segment for active hosts (basic IP scanner) 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 no idea how to get Netmask, so I'm kinda stuck. Moreover, I am quite new to Objective-C because I also do not have extensive knowledge of simple C. I watched CFHost, CFNetwork, NSHost and various Google hits, but haven’t found anything useful yet.

As a last resort, I could make a system call of the kind, I suppose, or read it from a file (which one?), But I want to avoid this, if possible.

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

Thanks!

+4
source share
3 answers

You will need to use the system configuration API. See System Programming Guide and System Configuration Reference

+3
source

So, to wrap this up, I finally got a look at exploring the system configuration API. As always, as soon as you know how it is not so difficult.

@ 0xced - Thanks for pointing me in the right direction. I would support your answer, but I do not have enough reputation to do this.

This is my solution for anyone who is curious or in the same situation. It includes digging into dynamic storage. See this for API information. You can view information stored in dynamic storage 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 main interface (e.g. en1):

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

Finally, I am building a line containing the interface in order to be able to request the correct key. Of course, it should look something like this: State / Network / Interface / en1 / IPv4, depending on the interface. With this, I can get an array with ip and netmask. On my Macbook, these arrays contain only one ip and netmask respectively. I suppose this might be different for other Macs, I should check this out. For my test, I just took the first (and only) element in the array, but some kind of size check should 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); 

It's easy to test, so it's a little rough around the edges. You will need to look for accounts, etc. This was written only to understand how this can be done.

+12
source
Martin gave a good answer. And its code in the ARC version is here:
 + (NSDictionary *)primaryIPv4AddressInfoFromSystemConfiguration { SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL); if (!storeRef) { return nil; } NSDictionary *IPv4Dictionary = nil; CFPropertyListRef global = SCDynamicStoreCopyValue(storeRef, CFSTR("State:/Network/Global/IPv4")); id primaryInterface = [(NSDictionary *)CFBridgingRelease(global) valueForKey:@"PrimaryInterface"]; if (primaryInterface) { NSString *interfaceState = @"State:/Network/Interface/"; interfaceState = [[interfaceState stringByAppendingString:(NSString *)primaryInterface] stringByAppendingString:@"/IPv4"]; CFPropertyListRef IPv4PropertyList = SCDynamicStoreCopyValue(storeRef, (__bridge CFStringRef)interfaceState); IPv4Dictionary = (NSDictionary *)CFBridgingRelease(IPv4PropertyList); } CFRelease(storeRef); return IPv4Dictionary; } + (NSDictionary *)primaryIPv6AddressInfoFromSystemConfiguration { SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL); if (!storeRef) { return nil; } NSDictionary *IPv6Dictionary = nil; CFPropertyListRef global = SCDynamicStoreCopyValue(storeRef, CFSTR("State:/Network/Global/IPv6")); id primaryInterface = [(NSDictionary *)CFBridgingRelease(global) valueForKey:@"PrimaryInterface"]; if (primaryInterface) { NSString *interfaceState = @"State:/Network/Interface/"; interfaceState = [[interfaceState stringByAppendingString:(NSString *)primaryInterface] stringByAppendingString:@"/IPv6"]; CFPropertyListRef IPv6PropertyList = SCDynamicStoreCopyValue(storeRef, (__bridge CFStringRef)interfaceState); IPv6Dictionary = (NSDictionary *)CFBridgingRelease(IPv6PropertyList); } CFRelease(storeRef); return IPv6Dictionary; } 
0
source

All Articles