summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorScott Ullrich <sullrich@pfsense.org>2009-01-20 16:12:33 -0500
committerScott Ullrich <sullrich@pfsense.org>2009-01-20 16:12:33 -0500
commitd378a8bc50c594d4e75b993242183c5759874e06 (patch)
treeff315005112659662b492db086f30e4815f6b5d2 /etc
parentfce9b046462521e8e1dfc428a01e1f01f2d483a4 (diff)
parent9ce5e10ac4fe43e9b580344454dd27172b6c4456 (diff)
downloadpfsense-d378a8bc50c594d4e75b993242183c5759874e06.zip
pfsense-d378a8bc50c594d4e75b993242183c5759874e06.tar.gz
Merge branch 'master' of http://gitweb.pfsense.org/pfsense/mainline
Diffstat (limited to 'etc')
-rw-r--r--etc/inc/IPv6.inc918
-rw-r--r--etc/inc/filter.inc196
-rw-r--r--etc/inc/interfaces.inc84
-rw-r--r--etc/inc/pfsense-utils.inc52
-rw-r--r--etc/inc/system.inc145
-rw-r--r--etc/inc/util.inc64
6 files changed, 1323 insertions, 136 deletions
diff --git a/etc/inc/IPv6.inc b/etc/inc/IPv6.inc
new file mode 100644
index 0000000..45ea2d7
--- /dev/null
+++ b/etc/inc/IPv6.inc
@@ -0,0 +1,918 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * This file contains the implementation of the Net_IPv6 class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to the New BSD license, that is
+ * available through the world-wide-web at
+ * http://www.opensource.org/licenses/bsd-license.php
+ * If you did not receive a copy of the new BSDlicense and are unable
+ * to obtain it through the world-wide-web, please send a note to
+ * license@php.net so we can mail you a copy immediately
+ *
+ * @category Net
+ * @package Net_IPv6
+ * @author Alexander Merz <alexander.merz@web.de>
+ * @copyright 2003-2005 The PHP Group
+ * @license http://www.opensource.org/licenses/bsd-license.php
+ * @version CVS: $Id: IPv6.inc,v 1.2 2008/11/26 03:54:43 sumacob Exp $
+ * @link http://pear.php.net/package/Net_IPv6
+ */
+
+// {{{ constants
+
+/**
+ * Error message if netmask bits was not found
+ * @see isInNetmask
+ */
+define("NET_IPV6_NO_NETMASK_MSG", "Netmask length not found");
+
+/**
+ * Error code if netmask bits was not found
+ * @see isInNetmask
+ */
+define("NET_IPV6_NO_NETMASK", 10);
+
+/**
+ * Address Type: Unassigned (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_UNASSIGNED", 1);
+
+/**
+ * Address Type: Reserved (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_RESERVED", 11);
+
+/**
+ * Address Type: Reserved for NSAP Allocation (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_RESERVED_NSAP", 12);
+
+/**
+ * Address Type: Reserved for IPX Allocation (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_RESERVED_IPX", 13);
+
+/**
+ * Address Type: Reserved for Geographic-Based Unicast Addresses
+ * (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC", 14);
+
+/**
+ * Address Type: Provider-Based Unicast Address (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_UNICAST_PROVIDER", 22);
+
+/**
+ * Address Type: Multicast Addresses (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_MULTICAST", 31);
+
+/**
+ * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_LOCAL_LINK", 42);
+
+/**
+ * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3)
+ * @see getAddressType()
+ */
+define("NET_IPV6_LOCAL_SITE", 43);
+
+/**
+ * Address Type: address can not assigned to a specific type
+ * @see getAddressType()
+ */
+define("NET_IPV6_UNKNOWN_TYPE", 1001);
+
+// }}}
+// {{{ Net_IPv6
+
+/**
+ * Class to validate and to work with IPv6 addresses.
+ *
+ * @category Net
+ * @package Net_IPv6
+ * @copyright 2003-2005 The PHP Group
+ * @license http://www.opensource.org/licenses/bsd-license.php
+ * @version $Release$
+ * @link http://pear.php.net/package/Net_IPv6
+ * @author Alexander Merz <alexander.merz@web.de>
+ * @author <elfrink at introweb dot nl>
+ * @author Josh Peck <jmp at joshpeck dot org>
+ */
+class Net_IPv6 {
+
+ // {{{ removeNetmaskBits()
+
+ /**
+ * Removes a possible existing netmask specification at an IP addresse.
+ *
+ * @param String $ip the (compressed) IP as Hex representation
+ *
+ * @return String the IP without netmask length
+ * @since 1.1.0
+ * @access public
+ * @static
+ */
+ function removeNetmaskSpec($ip)
+ {
+ $addr = $ip;
+
+ if (false !== strpos($ip, '/')) {
+
+ $elements = explode('/', $ip);
+
+ if (2 == count($elements)) {
+
+ $addr = $elements[0];
+
+ }
+
+ }
+
+ return $addr;
+ }
+
+ /**
+ * Returns a possible existing netmask specification at an IP addresse.
+ *
+ * @param String $ip the (compressed) IP as Hex representation
+ *
+ * @return String the netmask spec
+ * @since 1.1.0
+ * @access public
+ * @static
+ */
+ function getNetmaskSpec($ip)
+ {
+ $spec = '';
+
+ if (false !== strpos($ip, '/')) {
+
+ $elements = explode('/', $ip);
+
+ if (2 == count($elements)) {
+
+ $spec = $elements[1];
+
+ }
+
+ }
+
+ return $spec;
+ }
+
+ // }}}
+ // {{{ getNetmask()
+
+ /**
+ * Calculates the network prefix based on the netmask bits.
+ *
+ * @param String $ip the (compressed) IP in Hex format
+ * @param int $bits if the number of netmask bits is not part of the IP
+ * you must provide the number of bits
+ *
+ * @return String the network prefix
+ * @since 1.1.0
+ * @access public
+ * @static
+ */
+ function getNetmask($ip, $bits = null)
+ {
+ if (null==$bits) {
+
+ $elements = explode('/', $ip);
+
+ if (2 == count($elements)) {
+
+ $addr = $elements[0];
+ $bits = $elements[1];
+
+ } else {
+
+ include_once 'PEAR.inc';
+
+ return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
+ NET_IPV6_NO_NETMASK);
+ }
+
+ } else {
+
+ $addr = $ip;
+
+ }
+
+ $addr = Net_IPv6::uncompress($addr);
+ $binNetmask = str_repeat('1', $bits).str_repeat('0', 128 - $bits);
+
+ return Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($addr) & $binNetmask);
+ }
+
+ // }}}
+ // {{{ isInNetmask()
+
+ /**
+ * Checks if an (compressed) IP is in a specific address space.
+ *
+ * IF the IP does not contains the number of netmask bits (F8000::FFFF/16)
+ * then you have to use the $bits parameter.
+ *
+ * @param String $ip the IP to check (eg. F800::FFFF)
+ * @param String $netmask the netmask (eg F800::)
+ * @param int $bits the number of netmask bits to compare,
+ * if not given in $ip
+ *
+ * @return boolean true if $ip is in the netmask
+ * @since 1.1.0
+ * @access public
+ * @static
+ */
+ function isInNetmask($ip, $netmask, $bits=null)
+ {
+ // try to get the bit count
+
+ if (null == $bits) {
+
+ $elements = explode('/', $ip);
+
+ if (2 == count($elements)) {
+
+ $ip = $elements[0];
+ $bits = $elements[1];
+
+ } else if (null == $bits) {
+
+ $elements = explode('/', $netmask);
+
+ if (2 == count($elements)) {
+
+ $netmask = $elements[0];
+ $bits = $elements[1];
+
+ }
+
+ if (null == $bits) {
+
+ include_once 'PEAR.inc';
+ return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
+ NET_IPV6_NO_NETMASK);
+
+ }
+
+ }
+
+ }
+
+ $binIp = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($ip));
+ $binNetmask = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($netmask));
+
+ if (null != $bits
+ && "" != $bits
+ && 0 == strncmp( $binNetmask, $binIp, $bits)) {
+
+ return true;
+
+ }
+
+ return false;
+ }
+
+ // }}}
+ // {{{ getAddressType()
+
+ /**
+ * Returns the type of an IPv6 address.
+ *
+ * RFC 1883, Section 2.3 describes several types of addresses in
+ * the IPv6 addresse space.
+ * Several addresse types are markers for reserved spaces and as
+ * consequence a subject to change.
+ *
+ * @param String $ip the IP address in Hex format,
+ * compressed IPs are allowed
+ *
+ * @return int one of the addresse type constants
+ * @access public
+ * @since 1.1.0
+ * @static
+ *
+ * @see NET_IPV6_UNASSIGNED
+ * @see NET_IPV6_RESERVED
+ * @see NET_IPV6_RESERVED_NSAP
+ * @see NET_IPV6_RESERVED_IPX
+ * @see NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC
+ * @see NET_IPV6_UNICAST_PROVIDER
+ * @see NET_IPV6_MULTICAST
+ * @see NET_IPV6_LOCAL_LINK
+ * @see NET_IPV6_LOCAL_SITE
+ * @see NET_IPV6_UNKNOWN_TYPE
+ */
+ function getAddressType($ip)
+ {
+ $ip = Net_IPv6::removeNetmaskSpec($ip);
+ $binip = Net_IPv6::_ip2Bin($ip);
+
+ if (0 == strncmp('1111111010', $binip, 10)) {
+
+ return NET_IPV6_LOCAL_LINK;
+
+ } else if (0 == strncmp('1111111011', $binip, 10)) {
+
+ return NET_IPV6_LOCAL_SITE;
+
+ } else if (0 == strncmp('111111100', $binip, 9)) {
+
+ return NET_IPV6_UNASSIGNED;
+
+ } else if (0 == strncmp('11111111', $binip, 8)) {
+
+ return NET_IPV6_MULTICAST;
+
+ } else if (0 == strncmp('00000000', $binip, 8)) {
+
+ return NET_IPV6_RESERVED;
+
+ } else if (0 == strncmp('00000001', $binip, 8)
+ || 0 == strncmp('1111110', $binip, 7)) {
+
+ return NET_IPV6_UNASSIGNED;
+
+ } else if (0 == strncmp('0000001', $binip, 7)) {
+
+ return NET_IPV6_RESERVED_NSAP;
+
+ } else if (0 == strncmp('0000010', $binip, 7)) {
+
+ return NET_IPV6_RESERVED_IPX;;
+
+ } else if (0 == strncmp('0000011', $binip, 7) ||
+ 0 == strncmp('111110', $binip, 6) ||
+ 0 == strncmp('11110', $binip, 5) ||
+ 0 == strncmp('00001', $binip, 5) ||
+ 0 == strncmp('1110', $binip, 4) ||
+ 0 == strncmp('0001', $binip, 4) ||
+ 0 == strncmp('001', $binip, 3) ||
+ 0 == strncmp('011', $binip, 3) ||
+ 0 == strncmp('101', $binip, 3) ||
+ 0 == strncmp('110', $binip, 3)) {
+
+ return NET_IPV6_UNASSIGNED;
+
+ } else if (0 == strncmp('010', $binip, 3)) {
+
+ return NET_IPV6_UNICAST_PROVIDER;
+
+ } else if (0 == strncmp('100', $binip, 3)) {
+
+ return NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC;
+
+ }
+
+ return NET_IPV6_UNKNOWN_TYPE;
+ }
+
+ // }}}
+ // {{{ Uncompress()
+
+ /**
+ * Uncompresses an IPv6 adress
+ *
+ * RFC 2373 allows you to compress zeros in an adress to '::'. This
+ * function expects an valid IPv6 adress and expands the '::' to
+ * the required zeros.
+ *
+ * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
+ * ::1 -> 0:0:0:0:0:0:0:1
+ *
+ * @access public
+ * @see Compress()
+ * @static
+ * @param string $ip a valid IPv6-adress (hex format)
+ * @return string the uncompressed IPv6-adress (hex format)
+ */
+ function uncompress($ip)
+ {
+
+ $prefix = Net_IPv6::getPrefixLength($ip);
+
+ if (false === $prefix) {
+
+ $prefix = '';
+
+ } else {
+
+ $ip = Net_IPv6::removePrefixLength($ip);
+ $prefix = '/'.$prefix;
+
+ }
+
+ $netmask = Net_IPv6::getNetmaskSpec($ip);
+ $uip = Net_IPv6::removeNetmaskSpec($ip);
+
+ $c1 = -1;
+ $c2 = -1;
+
+ if (false !== strpos($uip, '::') ) {
+
+ list($ip1, $ip2) = explode('::', $uip);
+
+ if("" == $ip1) {
+
+ $c1 = -1;
+
+ } else {
+
+ $pos = 0;
+
+ if (0 < ($pos = substr_count($ip1, ':'))) {
+
+ $c1 = $pos;
+
+ } else {
+
+ $c1 = 0;
+
+ }
+ }
+ if ("" == $ip2) {
+
+ $c2 = -1;
+
+ } else {
+
+ $pos = 0;
+
+ if (0 < ($pos = substr_count($ip2, ':'))) {
+
+ $c2 = $pos;
+
+ } else {
+
+ $c2 = 0;
+
+ }
+
+ }
+
+ if (strstr($ip2, '.')) {
+
+ $c2++;
+
+ }
+ if (-1 == $c1 && -1 == $c2) { // ::
+
+ $uip = "0:0:0:0:0:0:0:0";
+
+ } else if (-1 == $c1) { // ::xxx
+
+ $fill = str_repeat('0:', 7-$c2);
+ $uip = str_replace('::', $fill, $uip);
+
+ } else if (-1 == $c2) { // xxx::
+
+ $fill = str_repeat(':0', 7-$c1);
+ $uip = str_replace('::', $fill, $uip);
+
+ } else { // xxx::xxx
+
+ $fill = str_repeat(':0:', 6-$c2-$c1);
+ $uip = str_replace('::', $fill, $uip);
+ $uip = str_replace('::', ':', $uip);
+
+ }
+ }
+ if ('' != $netmask) {
+
+ $uip = $uip.'/'.$netmask;
+
+ }
+
+ return $uip.$prefix;
+ }
+
+ // }}}
+ // {{{ Compress()
+
+ /**
+ * Compresses an IPv6 adress
+ *
+ * RFC 2373 allows you to compress zeros in an adress to '::'. This
+ * function expects an valid IPv6 adress and compresses successive zeros
+ * to '::'
+ *
+ * Example: FF01:0:0:0:0:0:0:101 -> FF01::101
+ * 0:0:0:0:0:0:0:1 -> ::1
+ *
+ * @access public
+ * @see Uncompress()
+ * @static
+ * @param string $ip a valid IPv6-adress (hex format)
+ * @return string the compressed IPv6-adress (hex format)
+ * @author elfrink at introweb dot nl
+ */
+ function compress($ip)
+ {
+ $prefix = Net_IPv6::getPrefixLength($ip);
+
+ if (false === $prefix) {
+
+ $prefix = '';
+
+ } else {
+
+ $ip = Net_IPv6::removePrefixLength($ip);
+ $prefix = '/'.$prefix;
+
+ }
+
+ $netmask = Net_IPv6::getNetmaskSpec($ip);
+ $ip = Net_IPv6::removeNetmaskSpec($ip);
+
+ if (!strstr($ip, '::')) {
+
+ $ipp = explode(':',$ip);
+
+ for ($i = 0; $i < count($ipp); $i++) {
+
+ $ipp[$i] = dechex(hexdec($ipp[$i]));
+
+ }
+
+ $cip = ':' . join(':',$ipp) . ':';
+
+ preg_match_all("/(:0)+/", $cip, $zeros);
+
+ if (count($zeros[0]) > 0) {
+
+ $match = '';
+
+ foreach($zeros[0] as $zero) {
+
+ if (strlen($zero) > strlen($match)) {
+
+ $match = $zero;
+
+ }
+ }
+
+ $cip = preg_replace('/' . $match . '/', ':', $cip, 1);
+
+ }
+
+ $cip = preg_replace('/((^:)|(:$))/', '' ,$cip);
+ $cip = preg_replace('/((^:)|(:$))/', '::' ,$cip);
+
+ }
+ if ('' != $netmask) {
+
+ $cip = $cip.'/'.$netmask;
+
+ }
+
+ return $cip.$prefix;
+ }
+
+ // }}}
+ // {{{ SplitV64()
+
+ /**
+ * Splits an IPv6 adress into the IPv6 and a possible IPv4 part
+ *
+ * RFC 2373 allows you to note the last two parts of an IPv6 adress as
+ * an IPv4 compatible adress
+ *
+ * Example: 0:0:0:0:0:0:13.1.68.3
+ * 0:0:0:0:0:FFFF:129.144.52.38
+ *
+ * @param string $ip a valid IPv6-adress (hex format)
+ *
+ * @return array [0] contains the IPv6 part,
+ * [1] the IPv4 part (hex format)
+ * @access public
+ * @static
+ */
+ function SplitV64($ip, $uncompress = true)
+ {
+ $ip = Net_IPv6::removeNetmaskSpec($ip);
+
+ if ($uncompress) {
+
+ $ip = Net_IPv6::Uncompress($ip);
+
+ }
+
+ if (strstr($ip, '.')) {
+
+ $pos = strrpos($ip, ':');
+ $ip{$pos} = '_';
+ $ipPart = explode('_', $ip);
+
+ return $ipPart;
+
+ } else {
+
+ return array($ip, "");
+
+ }
+ }
+
+ // }}}
+ // {{{ checkIPv6()
+
+ /**
+ * Checks an IPv6 adress
+ *
+ * Checks if the given IP is IPv6-compatible
+ *
+ * @access public
+ * @static
+ * @param string $ip a valid IPv6-adress
+ * @return boolean true if $ip is an IPv6 adress
+ */
+ function checkIPv6($ip)
+ {
+ $ip = Net_IPv6::removePrefixLength($ip);
+ $ip = Net_IPv6::removeNetmaskSpec($ip);
+
+ $ipPart = Net_IPv6::SplitV64($ip);
+ $count = 0;
+
+ if (!empty($ipPart[0]))
+ {
+ $ipv6 =explode(':', $ipPart[0]);
+
+ for ($i = 0; $i < count($ipv6); $i++) {
+
+ $dec = hexdec($ipv6[$i]);
+ $hex = strtoupper(preg_replace("/^[0]{1,3}(.*[0-9a-fA-F])$/",
+ "\\1",
+ $ipv6[$i]));
+
+ if ($ipv6[$i] >= 0 && $dec <= 65535
+ && $hex == strtoupper(dechex($dec))) {
+
+ $count++;
+
+ }
+
+ }
+
+ if (8 == $count) {
+
+ return true;
+
+ } else if (6 == $count and !empty($ipPart[1])) {
+
+ $ipv4 = explode('.',$ipPart[1]);
+ $count = 0;
+
+ for ($i = 0; $i < count($ipv4); $i++) {
+
+ if ($ipv4[$i] >= 0 && (integer)$ipv4[$i] <= 255
+ && preg_match("/^\d{1,3}$/", $ipv4[$i])) {
+
+ $count++;
+
+ }
+
+ }
+
+ if (4 == $count) {
+
+ return true;
+
+ }
+
+ } else {
+
+ return false;
+
+ }
+
+ } else {
+
+ return false;
+
+ }
+
+ }
+
+ // }}}
+ // {{{ getPrefixLength()
+
+ /**
+ * Tests for a prefix length specification in the address
+ * and returns the prefix length, if exists
+ *
+ * @param String $ip a valid ipv6 address
+ *
+ * @return Mixed the prefix as String or false, if no prefix was found
+ * @access public
+ * @static
+ */
+ function getPrefixLength($ip)
+ {
+ if (preg_match("/^([0-9a-fA-F:]{2,39})\/(\d{1,3})*$/",
+ $ip, $matches)) {
+
+ return $matches[2];
+
+ } else {
+
+ return false;
+
+ }
+
+ }
+
+ // }}}
+ // {{{ removePrefixLength()
+
+ /**
+ * Tests for a prefix length specification in the address
+ * and removes the prefix length, if exists
+ *
+ * @param String $ip a valid ipv6 address
+ *
+ * @return String the address without a prefix length
+ * @access public
+ * @static
+ */
+ function removePrefixLength($ip)
+ {
+ $pos = strrpos($ip, '/');
+
+ if (false !== $pos) {
+
+ return substr($ip, 0, $pos);
+
+ }
+
+ return $ip;
+ }
+
+ // }}}
+
+ // {{{ _parseAddress()
+
+ /**
+ * Returns the lowest and highest IPv6 address
+ * for a given IP and netmask specification
+ *
+ * The netmask may be a part of the $ip or
+ * the number of netwask bits is provided via $bits
+ *
+ * The result is an indexed array. The key 'start'
+ * contains the lowest possible IP adress. The key
+ * 'end' the highest address.
+ *
+ * @param String $ip the IPv6 address
+ * @param String $bits the optional count of netmask bits
+ *
+ * @return Array ['start', 'end'] the lowest and highest IPv6 address
+ * @access public
+ * @static
+ * @author Nicholas Williams
+ */
+
+ function parseAddress($ipToParse, $bits = null)
+ {
+
+ $ip = null;
+ $bitmask = null;
+
+ if( null == $bits )
+ {
+
+ $elements = explode('/', $ipToParse);
+
+ if( 2 == count($elements) ) {
+
+ $ip = Net_IPv6::uncompress($elements[0]);
+ $bitmask = $elements[1];
+
+ } else {
+
+ include_once 'PEAR.inc';
+
+ return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG,
+ NET_IPV6_NO_NETMASK);
+ }
+ }
+ else
+ {
+
+ $ip = Net_IPv6::uncompress($ipToParse);
+ $bitmask = $bits;
+
+ }
+
+ $binNetmask = str_repeat('1', $bitmask).
+ str_repeat('0', 128 - $bitmask);
+ $maxNetmask = str_repeat('1', 128);
+ $netmask = Net_IPv6::_bin2Ip($binNetmask);
+
+ $startAddress = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip)
+ & $binNetmask);
+ $endAddress = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip)
+ | ($binNetmask ^ $maxNetmask));
+
+ return array('start' => $startAddress, 'end' => $endAddress);
+ }
+
+ // }}}
+
+ // {{{ _ip2Bin()
+
+ /**
+ * Converts an IPv6 address from Hex into Binary representation.
+ *
+ * @param String $ip the IP to convert (a:b:c:d:e:f:g:h),
+ * compressed IPs are allowed
+ *
+ * @return String the binary representation
+ * @access private
+ @ @since 1.1.0
+ */
+ function _ip2Bin($ip)
+ {
+ $binstr = '';
+
+ $ip = Net_IPv6::removeNetmaskSpec($ip);
+ $ip = Net_IPv6::Uncompress($ip);
+
+ $parts = explode(':', $ip);
+
+ foreach($parts as $v) {
+
+ $str = base_convert($v, 16, 2);
+ $binstr .= str_pad($str, 16, '0', STR_PAD_LEFT);
+
+ }
+
+ return $binstr;
+ }
+
+ // }}}
+ // {{{ _bin2Ip()
+
+ /**
+ * Converts an IPv6 address from Binary into Hex representation.
+ *
+ * @param String $ip the IP as binary
+ *
+ * @return String the uncompressed Hex representation
+ * @access private
+ @ @since 1.1.0
+ */
+ function _bin2Ip($bin)
+ {
+ $ip = "";
+
+ if (strlen($bin) < 128) {
+
+ $bin = str_pad($str, 128, '0', STR_PAD_LEFT);
+
+ }
+
+ $parts = str_split($bin, "16");
+
+ foreach($parts as $v) {
+
+ $str = base_convert($v, 2, 16);
+ $ip .= $str.":";
+
+ }
+
+ $ip = substr($ip, 0,-1);
+
+ return $ip;
+ }
+
+ // }}}
+}
+// }}}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+
+?>
diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc
index 4867aea..fc3af04 100644
--- a/etc/inc/filter.inc
+++ b/etc/inc/filter.inc
@@ -40,7 +40,8 @@
require_once("functions.inc");
require_once("pkg-utils.inc");
require_once("notices.inc");
-require_once ("shaper.inc");
+require_once("shaper.inc");
+require_once("IPv6.inc");
/* holds the items that will be executed *AFTER* the filter is fully loaded */
$after_filter_configure_run = array();
@@ -176,6 +177,7 @@ function filter_configure_sync() {
$max_states = pfsense_default_state_size();
$rules .= "set limit states {$max_states}\n";
}
+ $rules .= "set skip on { lo0, gif, tun, enc }\n";
$rules .= "\n";
update_filter_reload_status("Setting up SCRUB information");
$rules .= filter_generate_scrubing();
@@ -391,12 +393,15 @@ function generate_optcfg_array()
$oic = array();
$oic['if'] = get_real_interface($if);
$oic['ip'] = get_interface_ip($if);
+ $oic['ip6'] = get_interface_ip($if, 'ipv6');
if (!is_ipaddr($oc['ipaddr']) && !empty($oc['ipaddr']))
$oic['type'] = $oc['ipaddr'];
$oic['sn'] = get_interface_subnet($if);
+ $oic['sn6'] = get_interface_subnet($if, 'ipv6');
$oic['mtu'] = $oc['mtu'];
$oic['descr'] = $ifdetail;
$oic['sa'] = gen_subnet($oic['ip'], $oic['sn']);
+ $oic['sa6'] = $oic['ip6'] != '' ? Net_IPv6::getNetmask($oic['ip6'], $oic['sn6']) : null;
$oic['nonat'] = $oc['nonat'];
$oic['ftpproxy'] = !isset($oc['disableftpproxy']);
$oic['alias-address'] = $oc['alias-address'];
@@ -1240,13 +1245,24 @@ function generate_user_filter_rule($rule)
/* do not process reply-to for gateway'd rules */
if ($rule['gateway'] == "" && interface_has_gateway($rule['interface'])) {
- $rg = get_interface_gateway($rule['interface']);
- if (is_ipaddr($rg)) {
- $aline['reply'] = "reply-to ( {$ifcfg['if']} {$rg} ) ";
- } else {
- if($rule['interface'] <> "pptp") {
+ if (Net_IPv6::checkIPv6($rule['source']['address']) || Net_IPv6::checkIPv6($rule['destination']['address'])) {
+ $rg = get_interface_gateway($rule['interface'], 'IPv6');
+
+ if (Net_IPv6::checkIPv6($rg)) {
+ $aline['reply'] = "reply-to ( {$ifcfg['if']} {$rg} ) ";
+ } else {
log_error("Could not find gateway for interface({$rule['interface']}).");
}
+ } else {
+ $rg = get_interface_gateway($rule['interface']);
+
+ if (is_ipaddr($rg)) {
+ $aline['reply'] = "reply-to ( {$ifcfg['if']} {$rg} ) ";
+ } else {
+ if($rule['interface'] <> "pptp") {
+ log_error("Could not find gateway for interface({$rule['interface']}).");
+ }
+ }
}
}
/* if user has selected a custom gateway, lets work with it */
@@ -1300,12 +1316,29 @@ function generate_user_filter_rule($rule)
}
}
if (isset($rule['protocol'])) {
- if($rule['protocol'] == "tcp/udp")
- $aline['prot'] = " proto { tcp udp } ";
- elseif($rule['protocol'] == "icmp")
+ switch($rule['protocol']) {
+ case 'tcp/udp':
+ $aline['prot'] = " inet proto { tcp udp } ";
+ break;
+ case 'tcp6/udp6':
+ $aline['prot'] = " inet6 proto { tcp udp } ";
+ break;
+ case 'tcp6':
+ $aline['prot'] = " inet6 proto tcp ";
+ break;
+ case 'udp6':
+ $aline['prot'] = " inet6 proto udp ";
+ break;
+ case 'icmp':
$aline['prot'] = " inet proto icmp ";
- else
+ break;
+ case 'icmp6':
+ $aline['prot'] = " inet6 proto ipv6-icmp ";
+ break;
+ default:
$aline['prot'] = " proto {$rule['protocol']} ";
+ break;
+ }
} else {
if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "") {
$aline['prot'] = " proto tcp ";
@@ -1328,30 +1361,58 @@ function generate_user_filter_rule($rule)
}
} else {
switch ($rule['source']['network']) {
- case 'wanip':
- $src = $FilterIflist["wan"]['ip'];
- break;
- case 'lanip':
- $src = $FilterIflist["lan"]['ip'];
- break;
- case 'lan':
- $lansa = $FilterIflist['lan']['sa'];
- $lansn = $FilterIflist['lan']['sn'];
- $src = "{$lansa}/{$lansn}";
- break;
- case 'pptp':
- $pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
- $pptpsn = $FilterIflist['pptp']['sn'];
- $src = "{$pptpsa}/{$pptpsn}";
- break;
- case 'pppoe':
- $pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
- $pppoesn = $FilterIflist['pppoe']['sn'];
- $src = "{$pppoesa}/{$pppoesn}";
- break;
+ case 'wanip':
+ if (isset($FilterIflist['wan']['ip6']) && isset($FilterIflist['wan']['ip'])) {
+ $src = "{ {$FilterIflist['wan']['ip6']}, {$FilterIflist['wan']['ip']} }";
+ } else if (isset($FilterIflist['wan']['ip6'])) {
+ $src = $FilterIflist['wan']['ip6'];
+ } else {
+ $src = $FilterIflist['wan']['ip'];
}
- if (isset($rule['source']['not'])) $src = "!{$src}";
+
+ break;
+ case 'lanip':
+ if (isset($FilterIflist['lan']['ip6']) && isset($FilterIflist['lan']['ip'])) {
+ $src = "{ {$FilterIflist['lan']['ip6']}, {$FilterIflist['lan']['ip']} }";
+ } else if (isset($FilterIflist['lan']['ip6'])) {
+ $src = $FilterIflist['lan']['ip6'];
+ } else {
+ $src = $FilterIflist['lan']['ip'];
+ }
+
+ break;
+ case 'lan':
+ if ($FilterIflist['lan']['sa6'] != '' && $FilterIflist['lan']['sn6'] != '' &&
+ $FilterIflist['lan']['sa'] != '' && $FilterIflist['lan']['sn'] != '') {
+ $lansa = $FilterIflist['lan']['sa'];
+ $lansn = $FilterIflist['lan']['sn'];
+ $lansa6 = $FilterIflist['lan']['sa6'];
+ $lansn6 = $FilterIflist['lan']['sn6'];
+ $src = "{ $lansa/$lansn, $lansa6/$lansn6 }";
+ } else if ($FilterIflist['lan']['sa6'] != '' && $FilterIflist['lan']['sn6'] != '') {
+ $lansa6 = $FilterIflist['lan']['sa6'];
+ $lansn6 = $FilterIflist['lan']['sn6'];
+ $src = "{ $lansa6/$lansn6 }";
+ } else {
+ $lansa = $FilterIflist['lan']['sa'];
+ $lansn = $FilterIflist['lan']['sn'];
+ $src = "{ $lansa/$lansn }";
+ }
+
+ break;
+ case 'pptp':
+ $pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
+ $pptpsn = $FilterIflist['pptp']['sn'];
+ $src = "{$pptpsa}/{$pptpsn}";
+ break;
+ case 'pppoe':
+ $pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
+ $pppoesn = $FilterIflist['pppoe']['sn'];
+ $src = "{$pppoesa}/{$pppoesn}";
+ break;
}
+ if (isset($rule['source']['not'])) $src = "!{$src}";
+ }
} else if ($rule['source']['address']) {
$expsrc = alias_expand($rule['source']['address']);
if (isset($rule['source']['not']))
@@ -1427,27 +1488,54 @@ function generate_user_filter_rule($rule)
if (isset($rule['destination']['not'])) $dst = " !{$dst}";
} else {
switch ($rule['destination']['network']) {
- case 'wanip':
- $dst = $FilterIflist["wan"]['ip'];
- break;
- case 'lanip':
- $dst = $FilterIflist["lan"]['ip'];
- break;
- case 'lan':
+ case 'wanip':
+ if (isset($FilterIflist['wan']['ip6']) && isset($FilterIflist['wan']['ip'])) {
+ $dst = "{ {$FilterIflist['wan']['ip6']}, {$FilterIflist['wan']['ip']} }";
+ } else if (isset($FilterIflist['wan']['ip6'])) {
+ $dst = $FilterIflist['wan']['ip6'];
+ } else {
+ $dst = $FilterIflist['wan']['ip'];
+ }
+
+ break;
+ case 'lanip':
+ if (isset($FilterIflist['lan']['ip6']) && isset($FilterIflist['lan']['ip'])) {
+ $dst = "{ {$FilterIflist['lan']['ip6']}, {$FilterIflist['lan']['ip']} }";
+ } else if (isset($FilterIflist['lan']['ip6'])) {
+ $dst = $FilterIflist['lan']['ip6'];
+ } else {
+ $dst = $FilterIflist['lan']['ip'];
+ }
+
+ break;
+ case 'lan':
+ if (isset($FilterIflist['lan']['sa6']) && isset($FilterIflist['lan']['sn6']) &&
+ isset($FilterIflist['lan']['sa']) && isset($FilterIflist['lan']['sn'])) {
$lansa = $FilterIflist['lan']['sa'];
$lansn = $FilterIflist['lan']['sn'];
- $dst = "{$lansa}/{$lansn}";
- break;
- case 'pptp':
- $pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
- $pptpsn = $FilterIflist['pptp']['sn'];
- $dst = "{$pptpsa}/{$pptpsn}";
- break;
- case 'pppoe':
- $pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
- $pppoesn = $FilterIflist['pppoe']['sn'];
- $dst = "{$pppoesa}/{$pppoesn}";
- break;
+ $lansa6 = $FilterIflist['lan']['sa6'];
+ $lansn6 = $FilterIflist['lan']['sn6'];
+ $dst = "{ $lansa/$lansn, $lansa6/$lansn6 }";
+ } else if (isset($FilterIflist['lan']['sa6']) && isset($FilterIflist['lan']['sn6'])) {
+ $lansa6 = $FilterIflist['lan']['sa6'];
+ $lansn6 = $FilterIflist['lan']['sn6'];
+ $dst = "{ $lansa6/$lansn6 }";
+ } else {
+ $lansa = $FilterIflist['lan']['sa'];
+ $lansn = $FilterIflist['lan']['sn'];
+ $dst = "{ $lansa/$lansn }";
+ }
+ break;
+ case 'pptp':
+ $pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
+ $pptpsn = $FilterIflist['pptp']['sn'];
+ $dst = "{$pptpsa}/{$pptpsn}";
+ break;
+ case 'pppoe':
+ $pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
+ $pppoesn = $FilterIflist['pppoe']['sn'];
+ $dst = "{$pppoesa}/{$pppoesn}";
+ break;
}
if (isset($rule['destination']['not'])) $dst = " !{$dst}";
}
@@ -1520,6 +1608,9 @@ function generate_user_filter_rule($rule)
if (($rule['protocol'] == "icmp") && $rule['icmptype']) {
$aline['icmp-type'] = "icmp-type {$rule['icmptype']} ";
}
+ if (($rule['protocol'] == "icmp6") && $rule['icmp6type']) {
+ $aline['icmp-type'] = "icmp6-type {$rule['icmp6type']} ";
+ }
if ($type == "pass") {
if (isset($rule['tag']) && $rule['tag'] <> "")
$aline['tag'] = " tag " .$rule['tag']. " ";
@@ -2433,7 +2524,7 @@ function generate_ipsec_filter_rules() {
$interface = $FilterIflist[$parentinterface]['if'];
/* Just in case */
- if (!is_ipaddr($gateway) || empty($interface)) {
+ if ((!is_ipaddr($gateway) && !Net_IPv6::checkIPv6($gateway)) || empty($interface)) {
$route_to = " ";
$reply_to = " ";
} else {
@@ -2441,6 +2532,7 @@ function generate_ipsec_filter_rules() {
$reply_to = " reply-to ( $interface $gateway ) ";
}
+ /* TODO: Put IPv6 here */
/* Add rules to allow IKE to pass */
$shorttunneldescr = substr($descr, 0, 36);
$ipfrules .= <<<EOD
diff --git a/etc/inc/interfaces.inc b/etc/inc/interfaces.inc
index 23a5ca6..c3f507b 100644
--- a/etc/inc/interfaces.inc
+++ b/etc/inc/interfaces.inc
@@ -51,6 +51,7 @@ function interfaces_bring_up($interface) {
function interfaces_loopback_configure() {
mwexec("/sbin/ifconfig lo0 127.0.0.1");
+ mwexec("/sbin/ifconfig lo0 inet6 ::1 prefixlen 128");
interfaces_bring_up("lo0");
return 0;
}
@@ -970,7 +971,8 @@ EOD;
}
-function interfaces_ipalias_configure() {
+function interfaces_ipalias_configure()
+{
global $g, $config;
if(isset($config['system']['developerspew'])) {
$mt = microtime();
@@ -981,7 +983,11 @@ function interfaces_ipalias_configure() {
foreach ($viparr as $vip) {
if ($vip['mode'] == "ipalias") {
$if = get_real_interface($vip['interface']);
- mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
+ if ($vip['subnet_ipv6'] != '') {
+ mwexec("/sbin/ifconfig " . escapeshellarg($if) . " inet6 {$vip['subnet_ipv6']} alias");
+ } else {
+ mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
+ }
}
}
}
@@ -1258,12 +1264,21 @@ function interface_configure($interface = "wan") {
$realif = get_real_interface($interface);
- if(!$g['booting']) {
- /* remove all addresses first */
+ if (!$g['booting']) {
+ /* remove all IPv4 addresses */
while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
interface_bring_down($interface);
+
+ /* remove all IPv6 addresses */
+ $str = <<<EOD
+ while i="`/sbin/ifconfig $realif | /usr/bin/grep inet6 | /usr/bin/grep -m 1 -v '%'`"; do
+ ifconfig $realif \$i delete
+ done
+EOD;
+ mwexec("($str)");
mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " down");
- }
+ }
+
/* wireless configuration? */
if (is_array($wancfg['wireless']))
interface_wireless_configure($realif, $wancfg['wireless']);
@@ -1326,15 +1341,32 @@ function interface_configure($interface = "wan") {
escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
" " . escapeshellarg($wancfg['pointtopoint']) . " up");
} else {
- if($wancfg['ipaddr'] && $wancfg['subnet'])
+ if($wancfg['ipaddr'] && $wancfg['subnet']) {
mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
" " . escapeshellarg($wancfg['ipaddr'] . "/" .
$wancfg['subnet']));
+ }
}
}
- if (is_ipaddr($wancfg['gateway']))
+ if ($wancfg['ipaddr_ipv6'] <> "" && $wancfg['subnet_ipv6'] <> "") {
+ if (isset($wancfg['ispointtopoint_ipv6']) && $wancfg['pointtopoint_ipv6']) {
+ // TODO: do something
+ } else {
+ mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
+ " inet6 " . escapeshellarg($wancfg['ipaddr_ipv6'] . "/" .
+ $wancfg['subnet_ipv6']));
+ }
+ }
+
+ if (is_ipaddr($wancfg['gateway'])) {
file_put_contents("/tmp/{$realif}_router", $wancfg['gateway']);
+ }
+
+ if (Net_IPv6::checkIPv6($wancfg['gateway_ipv6'])) {
+ // TODO: IPv6 needs to be configured too
+ file_put_contents("/tmp/{$realif}_router_ipv6", $wancfg['gateway_ipv6']);
+ }
}
if($wancfg['if'])
interfaces_bring_up($wancfg['if']);
@@ -1502,6 +1534,10 @@ pppoeclient:
EOD;
+ /*
+ * XXX: mpd seems to use netgraph interfaces so ngX interfaces are created
+ * instead of pppoeX. =) -simoncpu-
+ */
if ($interface == "wan")
$realif = "pppoe0";
else {
@@ -1816,6 +1852,10 @@ function get_real_interface($interface = "wan") {
}
break;
case "pppoe":
+ /*
+ * XXX: mpd seems to use netgraph interfaces so ngX interfaces are created
+ * instead of pppoeX. =) -simoncpu-
+ */
if ($if == "wan")
$wanif = "pppoe0";
else
@@ -1841,28 +1881,42 @@ function get_real_interface($interface = "wan") {
return $wanif;
}
-function get_interface_ip($interface = "wan") {
+function get_interface_ip($interface = "wan", $type = "ipv4")
+{
+ global $config, $g;
+
$realif = get_real_interface($interface);
/* Do we really come here for these interfaces ?! */
if (in_array($realif, array("pptp", "pppoe", "openvpn", "enc0" /* , "ppp" */)))
return "";
- $curip = find_interface_ip($realif);
- if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
- return $curip;
+ $curip = find_interface_ip($realif, false, $type);
+
+ if ($type == 'ipv6') {
+ if ($curip && Net_IPv6::checkIPv6($curip)) {
+ return $curip;
+ }
+ } else {
+ if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0")) {
+ return $curip;
+ }
+ }
return null;
}
-function get_interface_subnet($interface = "wan") {
+function get_interface_subnet($interface = "wan", $type = "ipv4")
+{
$realif = get_real_interface($interface);
/* Do we really come here for these interfaces ?! */
- if (in_array($realif, array("pptp", "pppoe", "openvpn", "enc0" /* , "ppp" */)))
+ if (in_array($realif, array("pptp", "pppoe", "openvpn", "enc0" /* , "ppp" */))) {
return "";
+ }
- $cursn = find_interface_subnet($realif);
- if (!empty($cursn))
+ $cursn = find_interface_subnet($realif, false, $type);
+ if (!empty($cursn)) {
return $cursn;
+ }
return null;
}
diff --git a/etc/inc/pfsense-utils.inc b/etc/inc/pfsense-utils.inc
index 300c102..c493371 100644
--- a/etc/inc/pfsense-utils.inc
+++ b/etc/inc/pfsense-utils.inc
@@ -1424,36 +1424,61 @@ function convert_ip_to_network_format($ip, $subnet) {
/*
* find_interface_ip($interface): return the interface ip (first found)
*/
-function find_interface_ip($interface, $flush = false) {
+function find_interface_ip($interface, $flush = false, $type = "ipv4") {
global $interface_ip_arr_cache;
+ global $interface_ip_arr_cache_ipv6; // putting this into a 2D array is a good idea
$interface = str_replace("\n", "", $interface);
if(does_interface_exist($interface) == false)
return;
/* Setup IP cache */
- if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
- $interface_ip_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2| /usr/bin/head -1");
- $interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
- }
+ if ($type == 'ipv4') {
+ if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
+ $interface_ip_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2| /usr/bin/head -1");
+ $interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
+ }
- return $interface_ip_arr_cache[$interface];
+ return $interface_ip_arr_cache[$interface];
+ } else {
+ /*
+ This assumes that the first IP in ifconfig is the "real" IP.
+ What if the first IP is an alias?
+ */
+ if (!isset($interface_ip_arr_cache_ipv6[$interface]) or $flush) {
+ $interface_ip_arr_cache_ipv6[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet6\" | /usr/bin/grep -v '%' | /usr/bin/cut -d\" \" -f 2| /usr/bin/head -1");
+ $interface_ip_arr_cache_ipv6[$interface] = str_replace("\n", "", $interface_ip_arr_cache_ipv6[$interface]);
+ }
+ return $interface_ip_arr_cache_ipv6[$interface];
+ }
}
-function find_interface_subnet($interface, $flush = false)
+function find_interface_subnet($interface, $flush = false, $type = "ipv4")
{
global $interface_sn_arr_cache;
+ global $interface_sn_arr_cache_ipv6;
$interface = str_replace("\n", "", $interface);
- if (does_interface_exist($interface) == false)
+ if (does_interface_exist($interface) == false) {
return;
-
- if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
- $interface_sn_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 4 | /usr/bin/head -1");
- $interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
}
- return $interface_sn_arr_cache[$interface];
+ if ($type == 'ipv4') {
+ if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
+ $interface_sn_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 4 | /usr/bin/head -1");
+ $interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
+ log_error("int:{$interface} - generated subnet mask {$interface_sn_arr_cache[$interface]}");
+ }
+
+ return $interface_sn_arr_cache[$interface];
+ } else {
+ if (!isset($interface_sn_arr_cache_ipv6[$interface]) or $flush) {
+ $interface_sn_arr_cache_ipv6[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet6\" | /usr/bin/grep -v '%' | /usr/bin/cut -d\" \" -f 4 | /usr/bin/head -1");
+ log_error("int:{$interface} - IPv6 prefixlen {$interface_sn_arr_cache_ipv6[$interface]}");
+ }
+
+ return $interface_sn_arr_cache_ipv6[$interface];
+ }
}
function guess_interface_from_ip($ipaddress) {
@@ -3488,5 +3513,4 @@ function compare_hostname_to_dnscache($hostname) {
}
}
-
?>
diff --git a/etc/inc/system.inc b/etc/inc/system.inc
index 36aa641..4359782 100644
--- a/etc/inc/system.inc
+++ b/etc/inc/system.inc
@@ -218,9 +218,14 @@ function system_routing_configure() {
return 1;
}
while (!feof($fd)) {
- $oldrt = trim(fgets($fd));
- if (($oldrt) && (stristr($route_str, $oldrt)))
- mwexec("/sbin/route delete " . escapeshellarg($oldrt));
+ $oldrt = fgets($fd);
+ if ($oldrt && stristr($route_str, trim($oldrt))) {
+ if (Net_IPv6::checkIPv6(trim($oldrt))) {
+ mwexec("/sbin/route delete -inet6 " . escapeshellarg(trim($oldrt)));
+ } else {
+ mwexec("/sbin/route delete " . escapeshellarg(trim($oldrt)));
+ }
+ }
}
fclose($fd);
unlink("{$g['vardb_path']}/routes.db");
@@ -229,19 +234,21 @@ function system_routing_configure() {
/* if list */
$iflist = get_configured_interface_list();
- $dont_remove_route = false;
- foreach ($iflist as $ifent => $ifname) {
- /* do not process interfaces that will end up with gateways */
- if (interface_has_gateway($ifent))
- $dont_remove_route = true;
- }
+ $dont_remove_route = false;
+ foreach ($iflist as $ifent => $ifname) {
+ /* do not process interfaces that will end up with gateways */
+ if (interface_has_gateway($ifent))
+ $dont_remove_route = true;
+ }
- if($config['interfaces']['wan']['ipaddr'] == "carpdev-dhcp")
+ if($config['interfaces']['wan']['ipaddr'] == "carpdev-dhcp") {
$dont_remove_route = true;
+ }
if($dont_remove_route == false) {
- /* remove default route */
- mwexec("/sbin/route delete default", true);
+ /* remove default routes */
+ mwexec("/sbin/route delete default");
+ mwexec("/sbin/route delete -inet6 default");
}
$dont_add_route = false;
@@ -256,14 +263,41 @@ function system_routing_configure() {
if($dont_add_route == false) {
if(is_array($config['gateways']['gateway_item'])) {
+ $gatewayip = '';
+ $interfacegw = '';
+
+ $gatewayip_ipv6 = '';
+ $interfacegw_ipv6 = '';
+
foreach($config['gateways']['gateway_item'] as $gateway) {
if(isset($gateway['defaultgw'])) {
- $gatewayip = $gateway['gateway'];
- $interfacegw = $gateway['interface'];
+ if ($gateway['type'] == 'IPv4') {
+ $gatewayip = $gateway['gateway'];
+ $interfacegw = $gateway['interface'];
+ } else if ($gateway['type'] == 'IPv6') {
+ $gatewayip_ipv6 = $gateway['gateway'];
+ $interfacegw_ipv6 = $gateway['interface'];
+ }
+ }
+ }
+
+ if($interfacegw != "bgpd") {
+ /*
+ if (Net_IPv6::checkIPv6($gatewayip)) {
+ mwexec("/sbin/route add -inet6 default " . escapeshellarg($gatewayip));
+ } else {
+ mwexec("/sbin/route add default " . escapeshellarg($gatewayip));
+ }
+ */
+
+ if ($gatewayip != '') {
+ mwexec("/sbin/route add default " . escapeshellarg($gatewayip), true);
+ }
+
+ if ($gatewayip_ipv6 != '') {
+ mwexec("/sbin/route add -inet6 default " . escapeshellarg($gatewayip_ipv6), true);
}
}
- if(($interfacegw <> "bgpd") && (is_ipaddr($gatewayip)))
- mwexec("/sbin/route add default " . escapeshellarg($gatewayip), true);
} else {
/* FIXME */
/* adding gateway for 1.2-style configs without the new
@@ -275,6 +309,11 @@ function system_routing_configure() {
$gatewayip = $config['interfaces']['wan']['gateway'];
mwexec("/sbin/route add default " . escapeshellarg($gatewayip), true);
}
+
+ if (Net_IPv6::checkIPv6($config['interfaces']['wan']['gateway_ipv6'])) {
+ $gatewayip = $config['interfaces']['wan']['gateway_ipv6'];
+ mwexec("/sbin/route add -inet6 default " . escapeshellarg($gatewayip), true);
+ }
}
}
@@ -295,19 +334,42 @@ function system_routing_configure() {
}
}
}
- if((is_ipaddr($rtent['gateway'])) && ($gatewayip == "")) {
- $gatewayip = $rtent['gateway'];
- $interfacegw = $rtent['interface'];
- }
- if(isset($rtent['interfacegateway'])) {
- mwexec("/sbin/route add " . escapeshellarg($rtent['network']) .
- " -iface " . escapeshellarg(convert_friendly_interface_to_real_interface_name($interfacegw)));
- } else {
- mwexec("/sbin/route add " . escapeshellarg($rtent['network']) .
- " " . escapeshellarg($gatewayip));
+
+ if ($rtent['ip_version'] == 'IPv4') {
+ if(is_ipaddr($rtent['gateway']) && $gatewayip == "") {
+ $gatewayip = $rtent['gateway'];
+ $interfacegw = $rtent['interface'];
+ }
+
+ if(isset($rtent['interfacegateway'])) {
+ mwexec("/sbin/route add " . escapeshellarg($rtent['network']) .
+ " -iface " . escapeshellarg(convert_friendly_interface_to_real_interface_name($interfacegw)));
+ } else {
+ mwexec("/sbin/route add " . escapeshellarg($rtent['network']) .
+ " " . escapeshellarg($gatewayip));
+ }
+
+ /* record route so it can be easily removed later (if necessary) */
+ fwrite($fd, $rtent['network'] . "\n");
+ } else if ($rtent['ip_version'] == 'IPv6') {
+ ///
+ if(Net_IPv6::checkIPv6($rtent['gateway']) && $gatewayip == "") {
+ $gatewayip = $rtent['gateway'];
+ $interfacegw = $rtent['interface'];
+ }
+
+ if(isset($rtent['interfacegateway'])) {
+ mwexec("/sbin/route add -inet6 " . escapeshellarg($rtent['network']) .
+ " -iface " . escapeshellarg(convert_friendly_interface_to_real_interface_name($interfacegw)));
+ } else {
+ mwexec("/sbin/route add -inet6 " . escapeshellarg($rtent['network']) .
+ " " . escapeshellarg($gatewayip));
+ }
+
+ /* record route so it can be easily removed later (if necessary) */
+ fwrite($fd, $rtent['network'] . "\n");
}
- /* record route so it can be easily removed later (if necessary) */
- fwrite($fd, $rtent['network'] . "\n");
+
}
fclose($fd);
}
@@ -317,12 +379,17 @@ function system_routing_configure() {
function system_routing_enable() {
global $config, $g;
+ $retval = false;
+
if(isset($config['system']['developerspew'])) {
$mt = microtime();
echo "system_routing_enable() being called $mt\n";
}
- return mwexec("/sbin/sysctl net.inet.ip.forwarding=1");
+ $retval = mwexec("/sbin/sysctl net.inet.ip.forwarding=1") && mwexec("/sbin/sysctl net.inet6.ip6.forwarding=1");
+
+ return $retval;
+
}
function system_syslogd_start() {
@@ -622,9 +689,9 @@ function system_generate_lighty_config($filename,
if($captive_portal == true) {
$bin_environment = <<<EOC
- "bin-environment" => (
- "PHP_FCGI_CHILDREN" => "16",
- "PHP_FCGI_MAX_REQUESTS" => "{$max_requests}"
+ "bin-environment" => (
+ "PHP_FCGI_CHILDREN" => "16",
+ "PHP_FCGI_MAX_REQUESTS" => "{$max_requests}"
),
EOC;
@@ -649,7 +716,7 @@ fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/tmp/php-fastcgi.socket",
- "min-procs" => 1,
+ "min-procs" => 2,
"max-procs" => {$max_procs},
{$bin_environment}
"bin-path" => "/usr/local/bin/php"
@@ -829,6 +896,8 @@ expire.url = (
"" => "access 50 hours",
)
+server.use-ipv6 = "enable"
+
EOD;
$cert = str_replace("\r", "", $cert);
@@ -848,7 +917,7 @@ EOD;
fwrite($fd, "\n");
fwrite($fd, $key);
fclose($fd);
- $lighty_config .= "\n";
+
$lighty_config .= "## ssl configuration\n";
$lighty_config .= "ssl.engine = \"enable\"\n";
$lighty_config .= "ssl.pemfile = \"{$g['varetc_path']}/{$cert_location}\"\n\n";
@@ -862,6 +931,12 @@ EOD;
fwrite($fd, $lighty_config);
fclose($fd);
+ /*
+ * Hard-code sysctl knob to ensure that lighttpd would work
+ * with IPv4 + IPv6.
+ */
+ mwexec("/sbin/sysctl net.inet6.ip6.v6only=0");
+
return 0;
}
@@ -925,7 +1000,7 @@ function system_ntp_configure() {
$ifaces = array_filter($ifaces, 'does_interface_exist');
$ips = array_map('find_interface_ip', $ifaces);
foreach ($ips as $ip) {
- if (is_ipaddr($ip))
+ if (is_ipaddr($ip) || Net_IPv6::checkIPv6($ip))
fwrite($fd, "listen on $ip\n");
}
}
diff --git a/etc/inc/util.inc b/etc/inc/util.inc
index 3ef01fc..7b8ebe8 100644
--- a/etc/inc/util.inc
+++ b/etc/inc/util.inc
@@ -27,6 +27,8 @@
POSSIBILITY OF SUCH DAMAGE.
*/
+require_once 'IPv6.inc';
+
/* kill a process by pid file */
function killbypid($pidfile) {
sigkillbypid($pidfile, "TERM");
@@ -120,9 +122,8 @@ function is_ipaddr($ipaddr) {
return false;
}
-/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
+/* returns true if $ipaddr is a valid IPv4/IPv6 address or an alias thereof */
function is_ipaddroralias($ipaddr) {
-
global $aliastable, $config;
if(is_array($config['aliases']['alias'])) {
@@ -132,22 +133,22 @@ function is_ipaddroralias($ipaddr) {
}
}
- if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
+ if (isset($aliastable[$ipaddr]) && (is_ipaddr($aliastable[$ipaddr]) || Net_IPv6::checkIPv6($aliastable[$ipaddr]))) {
return true;
- else
- return is_ipaddr($ipaddr);
-
+ } else {
+ return (is_ipaddr($ipaddr) || Net_IPv6::checkIPv6($ipaddr));
+ }
}
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
function is_ipaddroranyalias($ipaddr) {
-
global $aliastable;
- if (isset($aliastable[$ipaddr]))
+ if (isset($aliastable[$ipaddr])) {
return true;
- else
- return is_ipaddr($ipaddr);
+ } else {
+ return (is_ipaddr($ipaddr) || Net_IPv6::checkIPv6($ipaddr));
+ }
}
/* returns true if $subnet is a valid subnet in CIDR format */
@@ -166,6 +167,26 @@ function is_subnet($subnet) {
return true;
}
+/* returns true if $subnet is a valid IPv6 network address */
+function is_subnet_ipv6($subnet, $max = 64) {
+ if (!is_string($subnet)) {
+ return false;
+ }
+
+ list ($hp, $np) = explode('/', $subnet);
+
+ if (!Net_IPv6::checkIPv6($hp)) {
+ return false;
+ }
+
+ if (!is_numeric($np) || ($np < 1) || ($np > $max)) {
+ return false;
+ }
+
+ return true;
+}
+
+
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
function is_subnetoralias($subnet) {
@@ -503,15 +524,15 @@ function alias_expand_value($name) {
/* expand a host or network alias, if necessary */
function alias_expand($name) {
-
global $aliastable;
- if (isset($aliastable[$name]))
+ if (isset($aliastable[$name])) {
return "\${$name}";
- else if (is_ipaddr($name) || is_subnet($name))
+ } else if (is_ipaddr($name) || is_subnet($name) || Net_IPv6::checkIPv6($name) || is_subnet_ipv6($name)) {
return "{$name}";
- else
+ } else {
return null;
+ }
}
/* expand a host alias, if necessary */
@@ -521,14 +542,16 @@ function alias_expand_host($name) {
if (isset($aliastable[$name])) {
$ip_arr = explode(" ", $aliastable[$name]);
foreach($ip_arr as $ip) {
- if (!is_ipaddr($ip))
+ if (!is_ipaddr($ip) || Net_IPv6::checkIPv6($ip)) {
return null;
+ }
}
return $aliastable[$name];
- } else if (is_ipaddr($name))
+ } else if (is_ipaddr($name) || Net_IPv6::checkIPv6($name)) {
return $name;
- else
+ } else {
return null;
+ }
}
/* expand a network alias, if necessary */
@@ -612,8 +635,8 @@ function arp_get_mac_by_ip($ip) {
/* return a fieldname that is safe for xml usage */
function xml_safe_fieldname($fieldname) {
- $replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
+ $replace = array('/', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
':', ',', '.', '\'', '\\'
);
return strtolower(str_replace($replace, "", $fieldname));
@@ -647,8 +670,9 @@ function mac_format($clientmac) {
function resolve_retry($hostname, $retries = 5) {
- if (is_ipaddr($hostname))
+ if (is_ipaddr($hostname) || Net_IPv6::checkIPv6($hostname)) {
return $hostname;
+ }
for ($i = 0; $i < $retries; $i++) {
$ip = gethostbyname($hostname);
OpenPOWER on IntegriCloud