Free Code: IPv6 addresses displayed properly
If you have network code in your programm, especially code that deals with IP addresses, then you might have been stumbled upon IPv6 addresses. If you don't check your sockaddr and use it, you will have a useless IPv4 address, thats just the first 4 bytes of the IPv6 address. If you're dealing with Mac OS X self assinged addresses you will get something like 254.128.2.48, which would be my current self assigned address for my aiport card. So what you have to do to handle that properly is to look at the
sa_family field of your
sockaddr struct, and handle IPv6 if you encounter it.
So here's my Category to NSString that facilitates ntop to return proper IPv4 and IPv6 address strings. Share and Enjoy!
#import "sys/socket.h"
#import "netinet/in.h"
#import "netinet6/in6.h"
#import "arpa/inet.h"
@interface NSString (NSStringNetworkingAdditions)
+ (NSString *)stringWithAddressData:(NSData *)aAddressData;
@end
@implementation NSString (NSStringNetworkingAdditions)
+ (NSString *)stringWithAddressData:(NSData *)aAddressData {
struct sockaddr *socketAddress=(struct sockaddr *)[aAddressData bytes];
// IPv6 Addresses are "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
// at max, which is 40 bytes (0-terminated)
// IPv4 Addresses are "255.255.255.255" at max which is smaller
char stringBuffer[40];
NSString *addressAsString=nil;
if (socketAddress->sa_family == AF_INET) {
if (inet_ntop(AF_INET,
&((struct in_addr)((struct sockaddr_in *)socketAddress)->sin_addr),
stringBuffer,40)) {
addressAsString=[NSString stringWithUTF8String:stringBuffer];
} else {
addressAsString=@"IPv4 un-ntopable";
}
int port = ((struct sockaddr_in *)socketAddress)->sin_port;
addressAsString=[addressAsString stringByAppendingFormat:@":%d",port];
} else if (socketAddress->sa_family == AF_INET6) {
if (inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)socketAddress)->sin6_addr),
stringBuffer,40)) {
addressAsString=[NSString stringWithUTF8String:stringBuffer];
} else {
addressAsString=@"IPv6 un-ntopable";
}
int port = ((struct sockaddr_in6 *)socketAddress)->sin6_port;
// Suggested IPv6 format (see http://www.faqs.org/rfcs/rfc2732.html)
addressAsString=[NSString stringWithFormat:@"[%@]:%d",addressAsString,port];
} else {
addressAsString=@"neither IPv6 nor IPv4";
}
return [[addressAsString copy] autorelease];
}
@end
P.S.: I already released this code more implicitly some while ago with my Rendezvous samplecode
RendezCon - but as category it's much cleaner.
P.P.S: In case you wondered: this is Cocoa Objective-C code :-)
15:05 - Samstag, 21. August 2004