Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 +++ sbin/ipfw/ipfw.8 @@ -1343,7 +1343,7 @@ with multiple addresses) is provided for convenience only and its use is discouraged. .It Ar addr : Oo Cm not Oc Bro -.Cm any | me | me6 | +.Cm any | me | me4 | me6 | .Cm table Ns Pq Ar name Ns Op , Ns Ar value .Ar | addr-list | addr-set .Brc @@ -1351,7 +1351,11 @@ .It Cm any Matches any IP address. .It Cm me -Matches any IP address configured on an interface in the system. +Matches any IPv4 or IPv6 address configured on an interface in the system. +.It Cm me4 +Matches any IPv4 address configured on an interface in the system. +The address list is evaluated at the time the packet is +analysed. .It Cm me6 Matches any IPv6 address configured on an interface in the system. The address list is evaluated at the time the packet is Index: sbin/ipfw/ipfw2.c =================================================================== --- sbin/ipfw/ipfw2.c +++ sbin/ipfw/ipfw2.c @@ -3717,11 +3717,10 @@ if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) ret = add_srcip6(cmd, av, cblen, tstate); - /* XXX: should check for IPv4, not !IPv6 */ - if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || - inet_pton(AF_INET6, host, &a) != 1)) + else if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || + strcmp(av, "me4") == 0 || inet_pton(AF_INET, host, &a))) ret = add_srcip(cmd, av, cblen, tstate); - if (ret == NULL && strcmp(av, "any") != 0) + else if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; return ret; @@ -3748,11 +3747,10 @@ if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) ret = add_dstip6(cmd, av, cblen, tstate); - /* XXX: should check for IPv4, not !IPv6 */ - if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || - inet_pton(AF_INET6, host, &a) != 1)) + else if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || + strcmp(av, "me4") == 0 || inet_pton(AF_INET, host, &a))) ret = add_dstip(cmd, av, cblen, tstate); - if (ret == NULL && strcmp(av, "any") != 0) + else if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; return ret; Index: sbin/ipfw/ipv6.c =================================================================== --- sbin/ipfw/ipv6.c +++ sbin/ipfw/ipv6.c @@ -348,6 +348,11 @@ return (1); } + if (strcmp(av, "me4") == 0) { /* Set the data for "me" opt*/ + cmd->o.len |= F_INSN_SIZE(ipfw_insn); + return (1); + } + if (strcmp(av, "me6") == 0) { /* Set the data for "me" opt*/ cmd->o.len |= F_INSN_SIZE(ipfw_insn); return (1); Index: tests/sys/netpfil/common/Makefile =================================================================== --- tests/sys/netpfil/common/Makefile +++ tests/sys/netpfil/common/Makefile @@ -10,7 +10,8 @@ nat \ tos \ fragments \ - forward + forward \ + ipfw_me4 ${PACKAGE}FILES+= \ utils.subr \ Index: tests/sys/netpfil/common/ipfw_me4.sh =================================================================== --- tests/sys/netpfil/common/ipfw_me4.sh +++ tests/sys/netpfil/common/ipfw_me4.sh @@ -0,0 +1,202 @@ +#- +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# +# Copyright (c) 2020 Neel Chauhan +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +. $(atf_get_srcdir)/utils.subr +. $(atf_get_srcdir)/runner.subr + +me4_allow_head() +{ + atf_set descr 'IPFW me4 allow identifier test' + atf_set require.user root +} + +me4_allow_body() +{ + firewall=$1 + firewall_init $firewall + jname_cli="client" + jname_srv="server" + + epair=$(vnet_mkepair) + vnet_mkjail ${jname_cli} ${epair}a + jexec ${jname_cli} ifconfig ${epair}a 192.0.2.1/30 up + vnet_mkjail ${jname_srv} ${epair}b + jexec ${jname_srv} ifconfig ${epair}b 192.0.2.2/30 up + + firewall_config ${jname_srv} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + firewall_config ${jname_cli} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + atf_check -s exit:0 -o ignore jexec ${jname_cli} ping -c 1 -t 1 192.0.2.2 +} + +me4_allow_cleanup() +{ + firewall=$1 + firewall_cleanup $firewall +} + +me4_deny_head() +{ + atf_set descr 'IPFW me4 deny identifier test' + atf_set require.user root +} + +me4_deny_body() +{ + firewall=$1 + firewall_init $firewall + jname_cli="client" + jname_srv="server" + + epair=$(vnet_mkepair) + vnet_mkjail ${jname_cli} ${epair}a + jexec ${jname_cli} ifconfig ${epair}a 192.0.2.1/30 up + vnet_mkjail ${jname_srv} ${epair}b + jexec ${jname_srv} ifconfig ${epair}b 192.0.2.2/30 up + + firewall_config ${jname_srv} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 deny all from any to me4" + firewall_config ${jname_cli} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + atf_check -s exit:2 -o ignore jexec ${jname_cli} ping -c 1 -t 1 192.0.2.2 + + firewall_config ${jname_srv} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 deny all from me4 to any" + firewall_config ${jname_cli} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + atf_check -s exit:2 -o ignore jexec ${jname_cli} ping -c 1 -t 1 192.0.2.2 +} + +me4_deny_cleanup() +{ + firewall=$1 + firewall_cleanup $firewall +} + +me4_nonlocal_head() +{ + atf_set descr 'IPFW me4 non-local identifier test' + atf_set require.user root +} + +me4_nonlocal_body() +{ + firewall=$1 + firewall_init $firewall + jname_cli="client" + jname_srv="server" + + epair1=$(vnet_mkepair) + epair2=$(vnet_mkepair) + + vnet_mkjail ${jname_cli} ${epair1}a + jexec ${jname_cli} ifconfig ${epair1}a 192.0.2.1/30 up + + vnet_mkjail ${jname_srv} ${epair1}b ${epair2}b + jexec ${jname_srv} ifconfig ${epair1}a 192.0.2.2/30 up + jexec ${jname_srv} ifconfig ${epair2}b 198.51.100.1/30 up + + ifconfig ${epair2}a 198.51.100.2/30 up + + jexec ${jname_srv} sysctl net.inet.ip.forwarding=1 + jexec ${jname_cli} route add -net 198.51.100.0/30 192.0.2.2 + route add -net 192.0.2.0/30 198.51.100.1 + + firewall_config ${jname_srv} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 deny tcp from any to me4 7" \ + "ipfw -q add 200 allow all from any to any" + firewall_config ${jname_cli} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + + atf_check -s exit:2 -o ignore jexec ${jname_cli} ping -c 1 -t 1 198.51.100.2 +} + +me4_nonlocal_cleanup() +{ + firewall=$1 + firewall_cleanup $firewall +} + +me4_ipv6_head() +{ + atf_set descr 'IPFW me4 identifier ipv6 test' + atf_set require.user root +} + +me4_ipv6_body() +{ + firewall=$1 + firewall_init $firewall + jname_cli="client" + jname_srv="server" + + epair=$(vnet_mkepair) + vnet_mkjail ${jname_cli} ${epair}a + jexec ${jname_cli} ifconfig ${epair}a 192.0.2.1/30 up + jexec ${jname_cli} ifconfig ${epair}a inet6 fd7a:803f:cc4b::1/64 up no_dad + vnet_mkjail ${jname_srv} ${epair}b + jexec ${jname_srv} ifconfig ${epair}b 192.0.2.2/30 up + jexec ${jname_srv} ifconfig ${epair}b inet6 fd7a:803f:cc4b::2/64 up no_dad + + firewall_config ${jname_srv} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 deny all from any to me4" \ + "ipfw -q add 200 allow all from any to any" + firewall_config ${jname_cli} ${firewall} \ + "ipfw" \ + "ipfw -q add 100 allow all from any to any" + + atf_check -s exit:0 -o ignore jexec ${jname_cli} ping6 -c 1 -W 1 fd7a:803f:cc4b::2 +} + +me4_ipv6_cleanup() +{ + firewall=$1 + firewall_cleanup $firewall +} + + +setup_tests \ + me4_allow \ + ipfw \ + me4_deny \ + ipfw \ + me4_ipv6 \ + ipfw \ + me4_nonlocal \ + ipfw