Revision 3490b8dd
Added by Phil Davis over 10 years ago
etc/inc/pfsense-utils.inc | ||
---|---|---|
2709 | 2709 |
* INPUTS |
2710 | 2710 |
* IP Address to check. |
2711 | 2711 |
* If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip |
2712 |
* check_localip - if true then also check for matches with PPTP and LT2P addresses |
|
2713 |
* check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address |
|
2714 |
* cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr. |
|
2715 |
* If check_subnets is true and cidrprefix is specified, |
|
2716 |
* then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address |
|
2712 | 2717 |
* RESULT |
2713 |
* returns true if the IP Address is |
|
2714 |
* configured and present on this device. |
|
2718 |
* returns true if the IP Address is configured and present on this device or overlaps a configured subnet. |
|
2715 | 2719 |
*/ |
2716 |
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false) { |
|
2720 |
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") { |
|
2721 |
if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) { |
|
2722 |
return true; |
|
2723 |
} |
|
2724 |
return false; |
|
2725 |
} |
|
2726 |
|
|
2727 |
/****f* pfsense-utils/where_is_ipaddr_configured |
|
2728 |
* NAME |
|
2729 |
* where_is_ipaddr_configured |
|
2730 |
* INPUTS |
|
2731 |
* IP Address to check. |
|
2732 |
* If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip |
|
2733 |
* check_localip - if true then also check for matches with PPTP and LT2P addresses |
|
2734 |
* check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address |
|
2735 |
* cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr. |
|
2736 |
* If check_subnets is true and cidrprefix is specified, |
|
2737 |
* then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address |
|
2738 |
* RESULT |
|
2739 |
* Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check. |
|
2740 |
* If there are no matches then an empty array is returned. |
|
2741 |
*/ |
|
2742 |
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") { |
|
2717 | 2743 |
global $config; |
2718 | 2744 |
|
2745 |
$where_configured = array(); |
|
2746 |
|
|
2719 | 2747 |
$pos = strpos($ignore_if, '_virtualip'); |
2720 | 2748 |
if ($pos !== false) { |
2721 | 2749 |
$ignore_vip_id = substr($ignore_if, $pos+10); |
... | ... | |
2728 | 2756 |
$isipv6 = is_ipaddrv6($ipaddr); |
2729 | 2757 |
|
2730 | 2758 |
if ($check_subnets) { |
2759 |
$cidrprefix = intval($cidrprefix); |
|
2760 |
if ($isipv6) { |
|
2761 |
if (($cidrprefix < 1) || ($cidrprefix > 128)) { |
|
2762 |
$cidrprefix = 128; |
|
2763 |
} |
|
2764 |
} else { |
|
2765 |
if (($cidrprefix < 1) || ($cidrprefix > 32)) { |
|
2766 |
$cidrprefix = 32; |
|
2767 |
} |
|
2768 |
} |
|
2731 | 2769 |
$iflist = get_configured_interface_list(); |
2732 | 2770 |
foreach ($iflist as $if => $ifname) { |
2733 | 2771 |
if ($ignore_if == $if) { |
2734 | 2772 |
continue; |
2735 | 2773 |
} |
2736 | 2774 |
|
2737 |
if ($isipv6 === true) { |
|
2738 |
$bitmask = get_interface_subnetv6($if); |
|
2739 |
$subnet = gen_subnetv6(get_interface_ipv6($if), $bitmask); |
|
2775 |
if ($isipv6) { |
|
2776 |
$if_ipv6 = get_interface_ipv6($if); |
|
2777 |
$if_snbitsv6 = get_interface_subnetv6($if); |
|
2778 |
if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) { |
|
2779 |
$where_entry = array(); |
|
2780 |
$where_entry['if'] = $if; |
|
2781 |
$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if); |
|
2782 |
$where_configured[] = $where_entry; |
|
2783 |
} |
|
2740 | 2784 |
} else { |
2741 |
$bitmask = get_interface_subnet($if); |
|
2742 |
$subnet = gen_subnet(get_interface_ip($if), $bitmask); |
|
2743 |
} |
|
2744 |
|
|
2745 |
if (ip_in_subnet($ipaddr, $subnet . '/' . $bitmask)) { |
|
2746 |
return true; |
|
2785 |
$if_ipv4 = get_interface_ip($if); |
|
2786 |
$if_snbitsv4 = get_interface_subnet($if); |
|
2787 |
if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) { |
|
2788 |
$where_entry = array(); |
|
2789 |
$where_entry['if'] = $if; |
|
2790 |
$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if); |
|
2791 |
$where_configured[] = $where_entry; |
|
2792 |
} |
|
2747 | 2793 |
} |
2748 | 2794 |
} |
2749 | 2795 |
} else { |
2750 |
if ($isipv6 === true) {
|
|
2796 |
if ($isipv6) { |
|
2751 | 2797 |
$interface_list_ips = get_configured_ipv6_addresses(); |
2752 | 2798 |
} else { |
2753 | 2799 |
$interface_list_ips = get_configured_ip_addresses(); |
... | ... | |
2758 | 2804 |
continue; |
2759 | 2805 |
} |
2760 | 2806 |
if (strcasecmp($ipaddr, $ilips) == 0) { |
2761 |
return true; |
|
2807 |
$where_entry = array(); |
|
2808 |
$where_entry['if'] = $if; |
|
2809 |
$where_entry['ip_or_subnet'] = $ilips; |
|
2810 |
$where_configured[] = $where_entry; |
|
2762 | 2811 |
} |
2763 | 2812 |
} |
2764 | 2813 |
} |
... | ... | |
2770 | 2819 |
continue; |
2771 | 2820 |
} |
2772 | 2821 |
if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) { |
2773 |
return true; |
|
2822 |
$where_entry = array(); |
|
2823 |
$where_entry['if'] = $vip['if']; |
|
2824 |
$where_entry['ip_or_subnet'] = $vip['ipaddr']; |
|
2825 |
$where_configured[] = $where_entry; |
|
2774 | 2826 |
} |
2775 | 2827 |
} |
2776 | 2828 |
|
2777 | 2829 |
if ($check_localip) { |
2778 | 2830 |
if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0)) { |
2779 |
return true; |
|
2831 |
$where_entry = array(); |
|
2832 |
$where_entry['if'] = 'pptp'; |
|
2833 |
$where_entry['ip_or_subnet'] = $config['pptpd']['localip']; |
|
2834 |
$where_configured[] = $where_entry; |
|
2780 | 2835 |
} |
2781 | 2836 |
|
2782 | 2837 |
if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) { |
2783 |
return true; |
|
2838 |
$where_entry = array(); |
|
2839 |
$where_entry['if'] = 'l2tp'; |
|
2840 |
$where_entry['ip_or_subnet'] = $config['l2tp']['localip']; |
|
2841 |
$where_configured[] = $where_entry; |
|
2784 | 2842 |
} |
2785 | 2843 |
} |
2786 | 2844 |
|
2787 |
return false;
|
|
2845 |
return $where_configured;
|
|
2788 | 2846 |
} |
2789 | 2847 |
|
2790 | 2848 |
/****f* pfsense-utils/pfSense_handle_custom_code |
Also available in: Unified diff
Check for overlapping subnets when saving interface addresses
This checks if a static IP address entered for an interface has a subnet
that overlaps with any other configured subnet. e.g.:
LAN is IPv4 10.10.12.1/24
Then try to set OPT1 to 10.10.13.1/23 - it overlaps with LAN because
"/23" covers the "12" and "13" together.
In the input errors message, display to the user the other interfaces
and subnets that overlap/conflict. Then the user has some idea what it
is that conflicts and can easily go looking in the right place for the
problem.
Do the same thing for IPv6 address/CIDR.
Note: I have not enhanced any of the checks for conflicts with static
routes - there could be cases where a user has a static route like
10.0.0.0/8 pointing to some internal router that has the rest of
10.0.0.0/8 behind it, but the user has some direct-attached subnet
inside that - e.g. 10.1.2.0/24 - the routing table should cope with
this, delivering directly to 10.1.2.0/24 and routing for the rest of
10.0.0.0/8. So we cannot invalidate all overlaps with static routes.
I think this validation will not invalidate any exotic-but-valid use
cases. I can't think of when the interface subnets on 2 interfaces can
overlap and still be a valid/useful configuration.
This should stop people setting up dumb mixes of LAN/OPT1/OPT2... with
random addresses and CIDR prefix that overlap each other.