IP Address Validation

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
MichaelR
Forum Contributor
Posts: 148
Joined: Sat Jan 03, 2009 3:27 pm

IP Address Validation

Post by MichaelR »

Checks for IPv4, IPv6, and IPv4-mapped IPv6 addresses:

Code: Select all

  function is_ip_address($ip_address) {

    return preg_match('/^(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9](?::|$)){8,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,6})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,6})?))|(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){6,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4}:)?))?(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))$/i', $ip_address);

  }
 
Or, as a class:

Code: Select all

  /*
   * Copyright © Michael Rushton 2010
   * http://squiloople.com/
   * Feel free to use and redistribute this code. But please keep this copyright notice.
   */

  final class IPAddressValidator {

    private $ip_address;

    private $ipv4   = true;
    private $ipv6   = true;
    private $ipv6v4 = true;

    private function __construct($ip_address, $strict) {

      $this->ip_address = $ip_address;

      if ($strict) {
        $this->SetStrict();
      }

    }

    public static function SetIPAddress($ip_address, $strict = false) {
      return new self($ip_address, $strict);
    }

    public function SetStrict($strict = true) {

      $this->SetIPv4();
      $this->SetIPv6(!$strict);
      $this->SetIPv6v4(!$strict);

      return $this;

    }

    public function SetIPv4($allow = true) {

      $this->ipv4 = $allow;

      return $this;

    }

    public function SetIPv6($allow = true) {

      $this->ipv6 = $allow;

      return $this;

    }

    public function SetIPv6v4($allow = true) {

      $this->ipv6v4 = $allow;

      return $this;

    }

    public function Validate() {

      $ipv6_full       = '[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7}';

      $ipv6_comp       = '(?!(?:.*[a-f0-9](?::|$)){8,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,6})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,6})?';

      $ipv6            = '(?:' . $ipv6_full . ')|(?:' . $ipv6_comp . ')';

      $ipv6v4_full     = '[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:';

      $ipv6v4_comp     = '(?!(?:.*[a-f0-9]:){6,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4}:)?';

      $ipv6v4          = '(?:' . $ipv6v4_full . ')|(?:' . $ipv6v4_comp . ')';

      $ipv4            = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}';

      switch (true) {

        case ($this->ipv4 && $this->ipv6 && $this->ipv6v4):
          $ip = '(?:(?:' . $ipv6 . ')|(?:(?:' . $ipv6v4 . ')?' . $ipv4 . '))';
          break;
        case ($this->ipv4 && $this->ipv6):
          $ip = '(?:(?:' . $ipv6 . ')|(?:' . $ipv4 . '))';
          break;
        case ($this->ipv4 && $this->ipv6v4):
          $ip = '(?:' . $ipv6v4 . ')?' . $ipv4;
          break;
        case ($this->ipv6 && $this->ipv6v4):
          $ip = '(?:(?:' . $ipv6 . ')|(?:(?:' . $ipv6v4 . ')' . $ipv4 . '))';
          break;
        case ($this->ipv6):
          $ip = $ipv6;
          break;
        case ($this->ipv6v4):
          $ip = '(?:' . $ipv6v4 . ')' . $ipv4;
          break;
        default:
          $ip = $ipv4;

      }

      return preg_match('/^' . $ip . '$/i', $this->ip_address);

    }

  }
Last edited by MichaelR on Tue Aug 31, 2010 4:50 pm, edited 4 times in total.
User avatar
AbraCadaver
DevNet Master
Posts: 2572
Joined: Mon Feb 24, 2003 10:12 am
Location: The Republic of Texas
Contact:

Re: IP Address Validation

Post by AbraCadaver »

Nice work, however I normally use:

Code: Select all

// v4 or v6
filter_var($ip, FILTER_VALIDATE_IP);
 
// v4 only
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
 
// v6 only
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
mysql_function(): WARNING: This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQLextension should be used. See also MySQL: choosing an API guide and related FAQ for more information.
MichaelR
Forum Contributor
Posts: 148
Joined: Sat Jan 03, 2009 3:27 pm

Re: IP Address Validation

Post by MichaelR »

Heh. I didn't know about that. 8O

Thanks. :D
MichaelR
Forum Contributor
Posts: 148
Joined: Sat Jan 03, 2009 3:27 pm

Re: IP Address Validation

Post by MichaelR »

There is a problem with that function, though:

Code: Select all

 
filter_var('FFFF::255.255.255.255', FILTER_VALIDATE_IP);
 
// Returns false
 
filter_var('FFFF:::255.255.255.255', FILTER_VALIDATE_IP);
 
// Returns true
 
This is wrong. As per RFC 5321, the correct syntax of a compressed IPv6v4 address is:

Code: Select all

[IPv6-hex *3(":" IPv6-hex)] "::" [IPv6-hex *3(":" IPv6-hex) ":"] IPv4-address-literal
Three consecutive colons are not allowed.
User avatar
AbraCadaver
DevNet Master
Posts: 2572
Joined: Mon Feb 24, 2003 10:12 am
Location: The Republic of Texas
Contact:

Re: IP Address Validation

Post by AbraCadaver »

MichaelR wrote:There is a problem with that function, though:

Code: Select all

 
filter_var('FFFF::255.255.255.255', FILTER_VALIDATE_IP);
 
// Returns false
 
filter_var('FFFF:::255.255.255.255', FILTER_VALIDATE_IP);
 
// Returns true
 
This is wrong. As per RFC 5321, the correct syntax of a compressed IPv6v4 address is:

Code: Select all

[IPv6-hex *3(":" IPv6-hex)] "::" [IPv6-hex *3(":" IPv6-hex) ":"] IPv4-address-literal
Three consecutive colons are not allowed.
Submit it as a bug.
mysql_function(): WARNING: This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQLextension should be used. See also MySQL: choosing an API guide and related FAQ for more information.
n1tr0b
Forum Newbie
Posts: 5
Joined: Fri Jan 29, 2010 7:48 pm
Contact:

Re: IP Address Validation

Post by n1tr0b »

Well.. I just stumbled upon a cool code... I tested it on Vista... and works like a charm.. and I think I use AbraCadaver's code
User avatar
AbraCadaver
DevNet Master
Posts: 2572
Joined: Mon Feb 24, 2003 10:12 am
Location: The Republic of Texas
Contact:

Re: IP Address Validation

Post by AbraCadaver »

MichaelR, did you submit a bug report? If it truly is a bug then as PHP users we need to help out and alert the core team to bugs.
mysql_function(): WARNING: This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQLextension should be used. See also MySQL: choosing an API guide and related FAQ for more information.
MichaelR
Forum Contributor
Posts: 148
Joined: Sat Jan 03, 2009 3:27 pm

Re: IP Address Validation

Post by MichaelR »

Yeah, it's here.
Post Reply