0

I am developing an app which shows content based on country, so I get the IP Address of the user, the problem is how to check if this IP is between two IPs. Example:

if I have this IP : myIP = 127.0.0.1

how can I check if it's between this range: IP1 = 2.88.0.0; IP2 = 2.91.255.255;

Thanks.

M.Alatrash
  • 1,270
  • 1
  • 12
  • 30

2 Answers2

2

127.0.0.1 is the address of the loopback device. You want the address of en0 or whatever, which is the device connected to the wifi/mobile network. (It's possible to enumerate all the device addresses using getifaddrs(); see this SO question).

For IPv4 address the value can be represented using an 32-bit unsigned int so the range change is as simple as:

BOOL inRange = ipAddress >= rangeStart && ipAddress <= endRange;

See this SO question.

EDIT The OP seems to be stuck on the conversion of an IP address represented using dot-notation within a string (i.e. "2.88.0.0") and the unsigned int that I refer to. For this I refer him to the inet_aton() function, which is used to perform that conversion. You will get many hits on the internet if you search for that function and how to use it.

EDIT 2 OK, I'll add a more complete answer as the OP is still having issues:

The key piece of information I think you are missing WRT using inet_aton() is byte order. There is a concept of network byte order, which is big-endian given the founders of the internet used Dec PDP 11's to develop on. Most computers these days are little endian. So you need to add htonl() into the mix, which is the function to convert from network to host byte order (where the l means long, which is in-fact 32-bit).

So:

#import <Foundation/Foundation.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>

@interface NetworkStuff : NSObject
- (uint32_t)convertIpAddress:(NSString *)ipAddress;
- (BOOL)ipAddress:(NSString *)ipAddress isBetweenIpAddress:(NSString *)rangeStart
     andIpAddress:(NSString *)rangeEnd;
@end

@implementation NetworkStuff
- (uint32_t)convertIpAddress:(NSString *)ipAddress {
    struct sockaddr_in sin;
    inet_aton([ipAddress UTF8String], &sin.sin_addr);
    return ntohl(sin.sin_addr.s_addr);
}

- (BOOL)ipAddress:(NSString *)ipAddress isBetweenIpAddress:(NSString *)rangeStart
     andIpAddress:(NSString *)rangeEnd {
    uint32_t ip = [self convertIpAddress:ipAddress];
    uint32_t start = [self convertIpAddress:rangeStart];
    uint32_t end = [self convertIpAddress:rangeEnd];
    return ip >= start && ip <= end;
}

@end

#define BOOLSTR(b) (b ? @"YES" : @"NO")

int main()
{  
    @autoreleasepool{
        NetworkStuff *networkStuff = [NetworkStuff new];
        NSLog(@"%@", BOOLSTR([networkStuff ipAddress:@"2.90.1.2" isBetweenIpAddress:@"2.88.0.0" andIpAddress:@"2.91.255.255"]));
        NSLog(@"%@", BOOLSTR([networkStuff ipAddress:@"2.92.1.2" isBetweenIpAddress:@"2.88.0.0" andIpAddress:@"2.91.255.255"]));
    }
    return 0;
}

$ clang -DDEBUG=1 -g -fobjc-arc -o iprange iprange.m -framework Foundation
$ ./iprange
2014-02-10 09:42:29.530 iprange[14693:707] YES
2014-02-10 09:42:29.532 iprange[14693:707] NO
Community
  • 1
  • 1
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • thanx for ur answer, but if i do this NSRange range = NSMakeRange(2.88.0.0, 2.91.255.255); it gives me a warning that the 2.88.0.0 is not int or double..etc – M.Alatrash Feb 09 '14 at 09:20
  • There might also be other things to consider: The Wifi address could be a "local" address if you are behind a router with NAT. The mobile address could be an IPv6 address ... – Martin R Feb 09 '14 at 09:28
  • @MKAlatrash: I cannot see any connection between trojanfoe's answer and NSMakeRange(). – Martin R Feb 09 '14 at 09:29
  • @MartinR exactly, his answer is about Reachability :o – M.Alatrash Feb 09 '14 at 09:30
  • @MKAlatrash: That is now what I meant! trojanfoe showed you exactly how to check if an IPv4 address is in a given range. So why do you try to use NSMakeRange() ? – Martin R Feb 09 '14 at 09:33
  • @MKAlatrash I have updated my answer with function you need to convert between dot-notation and the `unsigned int`. – trojanfoe Feb 09 '14 at 09:41
  • @trojanfoe Thanks a lot, I am working on it. I'll let you know if works :) – M.Alatrash Feb 09 '14 at 09:54
  • @trojanfoe the inet_aton() function helped, thanx :) but I have used another way to do it. see the answer – M.Alatrash Feb 10 '14 at 07:39
0

First i have convert the IP Address to number using the following method:

-(double)getIpAsNumberr:(NSString *)ip
{
    NSArray *ipParts = [ip componentsSeparatedByString:@"."];
    double result = 0;

    for (int i = 0; i < 4; i++)
    {
        result += [ipParts[i]doubleValue] * (pow(256, (3 - i)));
    }

    return result;
}

After Converting the IP Addresses I use the following method find if the IP Address is falling in some Range like being between 2.88.0.0 and 2.91.255.255 :

-(BOOL)isBetween:(NSString *)myIPAddress fromRange:(NSString *)from ToRange:(NSString *)to
{
    double myIpAsNumber = [self getIpAsNumberr:myIPAddress];
    double ipFromAsNumber = [self getIpAsNumberr:from];
    double ipToAsNumber = [self getIpAsNumberr:to];

    BOOL inRange = myIpAsNumber >= ipFromAsNumber && myIpAsNumber <= ipToAsNumber;

    return inRange;
}

That's it.

The following method I used to convert the IP Address to unsigned integer,(Didn't work for me, so I used the above one):

-(double)getIpAsUnSignedInteger:(NSString *)ip
{
    struct sockaddr_in antelope;
    char *some_addr;
    const char *ipUnsigned = [ip cStringUsingEncoding:NSStringEncodingConversionAllowLossy];

    inet_aton(ipUnsigned, &antelope.sin_addr); // store IP in antelope

    some_addr = inet_ntoa(antelope.sin_addr); // return the IP
    printf("%s\n", some_addr); // prints the IP Address

    // and this call is the same as the inet_aton() call, above:
    antelope.sin_addr.s_addr = inet_addr(ipUnsigned);

    NSString *ipAsNumber = [NSString stringWithFormat:@"%u",antelope.sin_addr.s_addr];
    NSLog(@"ssss == %@",ipAsNumber);

    return [ipAsNumber doubleValue];
}
M.Alatrash
  • 1,270
  • 1
  • 12
  • 30
  • Why `double`? An IPv4 address can be represented using an unsigned 32-bit integer. – trojanfoe Feb 10 '14 at 09:14
  • I tried to make it 32-bit integer, and it changed.. but when i tried to compare it didn't work.. I'll post the method which I used to convert it to 32-bit integer. – M.Alatrash Feb 10 '14 at 09:16
  • @trojanfoe see the Edit, which I added the method converting the IP Address to UnSigned Integer. – M.Alatrash Feb 10 '14 at 09:20
  • OK, I've added a more complete answer, as you appear to be thrashing around, getting nowhere. – trojanfoe Feb 10 '14 at 09:44
  • oh, thanx man @trojanfoe a lot for your response. I'll go up with ur solution it's better than mine – M.Alatrash Feb 10 '14 at 09:55