how to check for ip address that falls inside a range.

Discussion in 'Perl Misc' started by mike, Jan 30, 2004.

  1. mike

    mike Guest

    hi

    i need to verify if an ip-address falls inside a range for example,
    say 10.1.1.1 to 10.1.2.255.
    So if a user keys in 10.1.2.2, it should fall inside this range and
    then the program can do something.

    How can i go about declaring the range, and how can i check the ip
    whether it falls inside the range. ?
    thanks.
    mike, Jan 30, 2004
    #1
    1. Advertising

  2. In article <>,
    mike <> wrote:
    :i need to verify if an ip-address falls inside a range for example,
    :say 10.1.1.1 to 10.1.2.255.
    :So if a user keys in 10.1.2.2, it should fall inside this range and
    :then the program can do something.

    :How can i go about declaring the range, and how can i check the ip
    :whether it falls inside the range. ?

    for each of the three IP addresses, split the IP address on '\.',
    say into @ipd; then
    $iaddr = pack('C4', $ipd[0], $ipd[1], $ipd[2], $ipd[3]);
    gives the binary equivilent of the IP. Once you have all three,
    it's just a matter of testing that the test ip is numerically
    between the other two values.
    --
    "No one has the right to destroy another person's belief by
    demanding empirical evidence." -- Ann Landers
    Walter Roberson, Jan 30, 2004
    #2
    1. Advertising

  3. mike wrote:
    > i need to verify if an ip-address falls inside a range for example,
    > say 10.1.1.1 to 10.1.2.255.


    One idea:

    my $test = '10.1.2.2';
    my $lower = '10.1.1.1';
    my $higher = '10.1.2.255';

    sub iptest {
    my @ip = @_;
    for ( @ip ) {
    $_ = join '', map { sprintf '%03s', $_ } split /\./, $_;
    }
    $ip[0] >= $ip[1] and $ip[0] <= $ip[2] ? 1 : 0;
    }

    if ( iptest($test, $lower, $higher) ) {
    print "$test falls inside the range $lower to $higher.\n";
    }

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Jan 30, 2004
    #3
  4. mike

    Ben Morrow Guest

    -cnrc.gc.ca (Walter Roberson) wrote:
    > In article <>,
    > mike <> wrote:
    > :i need to verify if an ip-address falls inside a range for example,
    > :say 10.1.1.1 to 10.1.2.255.
    > :So if a user keys in 10.1.2.2, it should fall inside this range and
    > :then the program can do something.
    >
    > :How can i go about declaring the range, and how can i check the ip
    > :whether it falls inside the range. ?
    >
    > for each of the three IP addresses, split the IP address on '\.',
    > say into @ipd;


    Or, better, use Regexp::Common.

    Ben

    --
    And if you wanna make sense / Whatcha looking at me for? (Fiona Apple)
    * *
    Ben Morrow, Jan 30, 2004
    #4
  5. mike

    Tony Curtis Guest

    >> On 29 Jan 2004 18:43:28 -0800,
    >> (mike) said:


    > hi i need to verify if an ip-address falls inside a range
    > for example, say 10.1.1.1 to 10.1.2.255. So if a user keys
    > in 10.1.2.2, it should fall inside this range and then the
    > program can do something.


    > How can i go about declaring the range, and how can i check
    > the ip whether it falls inside the range. ? thanks.


    http://search.cpan.org/

    Take a look at NetAddr::IP and Net::IP::Match, one or both
    might do what you want.

    hth
    t
    Tony Curtis, Jan 30, 2004
    #5
  6. mike

    Kien Ha Guest

    mike wrote:
    > hi
    >
    > i need to verify if an ip-address falls inside a range for example,
    > say 10.1.1.1 to 10.1.2.255.
    > So if a user keys in 10.1.2.2, it should fall inside this range and
    > then the program can do something.
    >
    > How can i go about declaring the range, and how can i check the ip
    > whether it falls inside the range. ?
    > thanks.



    #!/usr/bin/perl
    use strict;
    use warnings;
    use IO::Socket qw(inet_aton);


    my @ip_range = qw{ 10.1.1.1 10.1.2.255 };
    my ($lower, $upper) = map { inet_aton($_) } @ip_range;


    for ( qw{ 10.1.2.2 10.1.2.10 10.1.3.222 } ) {
    my $packed_ip = inet_aton($_);
    if ( $packed_ip lt $lower or $packed_ip gt $upper ) {
    print "$_ is out of expected range ",
    "$ip_range[0] .. $ip_range[1].\n";
    next;
    }


    print "$_ is in range.\n";
    }


    --
    Kien
    Kien Ha, Jan 30, 2004
    #6
  7. mike

    mike Guest

    Kien Ha <> wrote in message news:<RCkSb.6281$>...
    > mike wrote:
    > > hi
    > >
    > > i need to verify if an ip-address falls inside a range for example,
    > > say 10.1.1.1 to 10.1.2.255.
    > > So if a user keys in 10.1.2.2, it should fall inside this range and
    > > then the program can do something.
    > >
    > > How can i go about declaring the range, and how can i check the ip
    > > whether it falls inside the range. ?
    > > thanks.

    >
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    > use IO::Socket qw(inet_aton);
    >
    >
    > my @ip_range = qw{ 10.1.1.1 10.1.2.255 };
    > my ($lower, $upper) = map { inet_aton($_) } @ip_range;
    >
    >
    > for ( qw{ 10.1.2.2 10.1.2.10 10.1.3.222 } ) {
    > my $packed_ip = inet_aton($_);
    > if ( $packed_ip lt $lower or $packed_ip gt $upper ) {
    > print "$_ is out of expected range ",
    > "$ip_range[0] .. $ip_range[1].\n";
    > next;
    > }
    >
    >
    > print "$_ is in range.\n";
    > }





    Thanks for all the tips...appreciate that..
    mike, Jan 30, 2004
    #7
  8. In article <RCkSb.6281$>,
    Kien Ha <> wrote:
    :mike wrote:
    :> i need to verify if an ip-address falls inside a range for example,

    :use IO::Socket qw(inet_aton);

    Looking at perldoc, it appears to me that should be Socket instead
    of IO::Socket .


    : my $packed_ip = inet_aton($_);
    : if ( $packed_ip lt $lower or $packed_ip gt $upper ) {

    I realized a potential flaw in my pack 'C4' version:
    I was using network byte order and numeric comparisions, which
    would fail on small-endian or machines with other unusual binary
    storage orders. I see that your version avoids that by doing
    string comparisons instead of numeric comparisons. Think I'll
    go edit some of my code now... ;-)
    --
    We don't need no side effect-ing
    We don't need no scope control
    No global variables for execution
    Hey! Did you leave those args alone? -- decvax!utzoo!utcsrgv!roderick
    Walter Roberson, Jan 31, 2004
    #8
  9. In article <bvfbsl$3g6$>,
    Walter Roberson <-cnrc.gc.ca> wrote:
    |In article <RCkSb.6281$>,
    |Kien Ha <> wrote:

    |: my $packed_ip = inet_aton($_);
    |: if ( $packed_ip lt $lower or $packed_ip gt $upper ) {

    |I realized a potential flaw in my pack 'C4' version:
    |I was using network byte order and numeric comparisions, which
    |would fail on small-endian or machines with other unusual binary
    |storage orders. I see that your version avoids that by doing
    |string comparisons instead of numeric comparisons.

    Ah, and I just found a theoretical flaw in the inet_aton version.
    The documentation for inet_aton says that it returns an
    opaque string, and that one should not assume that it is 32 bits
    (e.g., because of IPv6.) Theoretically, then, the results of
    inet_aton are not always going to be linear for lt / gt purposes,
    even if the inputs are consistantly dotted quads.
    --
    Oh, yeah, an African swallow maybe, but not a European swallow.
    That's my point.
    Walter Roberson, Jan 31, 2004
    #9
  10. Walter Roberson wrote:
    > Ah, and I just found a theoretical flaw in the inet_aton version.
    > The documentation for inet_aton says that it returns an opaque
    > string, and that one should not assume that it is 32 bits (e.g.,
    > because of IPv6.) Theoretically, then, the results of inet_aton are
    > not always going to be linear for lt / gt purposes, even if the
    > inputs are consistantly dotted quads.


    So why not keep it simple, then?

    http://groups.google.se/groups?selm=bvck8u$kijvq$-berlin.de

    ;-)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Jan 31, 2004
    #10
  11. In article <bvfdgl$rqqgc$-berlin.de>,
    Gunnar Hjalmarsson <> wrote:
    :Walter Roberson wrote:
    :> Ah, and I just found a theoretical flaw in the inet_aton version.

    :So why not keep it simple, then?

    :http://groups.google.se/groups?selm=bvck8u$kijvq$-berlin.de

    sprintf '%03s' of each quad leads to string comparisons that are
    longer than they need be. Not important for a single such test, but
    if you are doing many such tests, it could add up. More efficient
    string tests can be had by pack()ing each octet as a character.
    Looking over some old code last night, I find I have

    pack 'C*', split /\./ $_

    The question then would be whether conversions from the textual
    multi-character octets into binary characters are more efficient
    than the sprintf '%03s'. The %03s requires an internal string to
    binary conversion as it is (the '3' into the number 3 internally)
    and sprintf has a lot of overhead. Possibly more efficient than
    either of these would be some manipulations involving substr
    and a leading '000' concatenated on...
    --
    Entropy is the logarithm of probability -- Boltzmann
    Walter Roberson, Jan 31, 2004
    #11
  12. mike

    Ben Morrow Guest

    -cnrc.gc.ca (Walter Roberson) wrote:
    > In article <bvfdgl$rqqgc$-berlin.de>,
    > Gunnar Hjalmarsson <> wrote:
    > :Walter Roberson wrote:
    > :> Ah, and I just found a theoretical flaw in the inet_aton version.
    >
    > :So why not keep it simple, then?
    >
    > :http://groups.google.se/groups?selm=bvck8u$kijvq$-berlin.de
    >
    > sprintf '%03s' of each quad leads to string comparisons that are
    > longer than they need be. Not important for a single such test, but
    > if you are doing many such tests, it could add up.


    Premature optimization is the root of all evil.

    Ben

    --
    Joy and Woe are woven fine,
    A Clothing for the Soul divine William Blake
    Under every grief and pine 'Auguries of Innocence'
    Runs a joy with silken twine.
    Ben Morrow, Jan 31, 2004
    #12
  13. Walter Roberson wrote:
    > sprintf '%03s' of each quad leads to string comparisons that are
    > longer than they need be.


    That's undoubtedly true.

    > Not important for a single such test, but if you are doing many
    > such tests, it could add up. More efficient string tests can be had
    > by pack()ing each octet as a character. Looking over some old code
    > last night, I find I have
    >
    > pack 'C*', split /\./ $_
    >
    > The question then would be whether conversions from the textual
    > multi-character octets into binary characters are more efficient
    > than the sprintf '%03s'.


    I made a benchmark (code below), and this is the result:

    Rate sprintf pack
    sprintf 8035/s -- -46%
    pack 14923/s 86% --

    > The %03s requires an internal string to binary conversion as it is
    > (the '3' into the number 3 internally) and sprintf has a lot of
    > overhead.


    Seems as if you are right, i.e. using pack() is more efficient.

    Here is the benchmarking code:

    use Benchmark 'cmpthese';
    cmpthese( -5, {
    pack => sub {
    my @ip = ('10.1.2.2', '10.1.2.255');
    for ( @ip ) {
    $_ = pack 'C*', split /\./, $_;
    }
    return 1 if $ip[0] lt $ip[1];
    },
    sprintf => sub {
    my @ip = ('10.1.2.2', '10.1.2.255');
    for ( @ip ) {
    $_ = join '',
    map { sprintf '%03s', $_ } split /\./, $_;
    }
    return 1 if $ip[0] lt $ip[1];
    },
    } );

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Jan 31, 2004
    #13
  14. Ben Morrow <> wrote:
    >
    > -cnrc.gc.ca (Walter Roberson) wrote:
    >> In article <>,
    >> mike <> wrote:
    >> :i need to verify if an ip-address falls inside a range for example,
    >> :say 10.1.1.1 to 10.1.2.255.
    >> :So if a user keys in 10.1.2.2, it should fall inside this range and
    >> :then the program can do something.
    >>
    >> :How can i go about declaring the range, and how can i check the ip
    >> :whether it falls inside the range. ?
    >>
    >> for each of the three IP addresses, split the IP address on '\.',
    >> say into @ipd;

    >
    > Or, better, use Regexp::Common.
    >


    Or, perhaps not better, the inet_aton() subroutine in Socket.

    /J\
    Jonathan Stowe, Feb 1, 2004
    #14
  15. In article <mW3Tb.1$>,
    Jonathan Stowe <> wrote:
    |Ben Morrow <> wrote:

    |> -cnrc.gc.ca (Walter Roberson) wrote:
    |>> In article <>,

    |>> for each of the three IP addresses, split the IP address on '\.',
    |>> say into @ipd;

    |> Or, better, use Regexp::Common.

    |Or, perhaps not better, the inet_aton() subroutine in Socket.

    We went over that already. Socket::inet_aton() is documented
    as producing an opaque structure, and the documentation says one
    should not assume the result is 32 bits wide. For example, if your
    system supports IPv6, then even though you feed a dotted quad in,
    the resulting structure is not certain to be 32 bits wide, and
    is not certain to be numerically comparable.
    --
    Usenet is one of those "Good News/Bad News" comedy routines.
    Walter Roberson, Feb 1, 2004
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. M O J O
    Replies:
    3
    Views:
    344
    Todd Bellamy
    Nov 4, 2003
  2. Phil Carmody
    Replies:
    13
    Views:
    524
    White Wolf
    Sep 12, 2003
  3. bill
    Replies:
    2
    Views:
    414
    P.J. Plauger
    May 25, 2004
  4. savvy
    Replies:
    1
    Views:
    361
    sloan
    May 12, 2006
  5. Replies:
    46
    Views:
    951
    Antoon Pardon
    Jul 25, 2006
Loading...

Share This Page