Bug 242201

Summary: ipfw - option 'ipversion 6' not working
Product: Base System Reporter: Freddy DISSAUX <dsx>
Component: kernAssignee: freebsd-ipfw (Nobody) <ipfw>
Status: Closed Works As Intended    
Severity: Affects Only Me CC: ae, bapt, olivier
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   
Description Flags
Allow using 'ipver 6' as matching rule none

Description Freddy DISSAUX 2019-11-24 18:46:39 UTC
From man ipfw:

     ipversion ver
             Matches IP packets whose IP version field is ver.

This option add opcode 'O_IPVER'.

From sys/netpfil/ipfw/ip_fw2.c:

    case O_IPVER:
            match = (is_ipv4 && (cmd->arg1 == ip->ip_v));

Flag 'is_ipv4' (may be a copy/paste from another case) must not be used in this case.

Without this flag, i can use the following rule to match ipv6 icmp packet:

/sbin/ipfw add pass log ipversion 6 proto ipv6-icmp

Comment 1 Andrey V. Elsukov freebsd_committer 2019-11-26 01:54:03 UTC
I think this opcode was designed to match the ip_v field of IPv4 packets. It was introduced much early than IPv6 support was added.
Comment 2 Freddy DISSAUX 2019-11-26 06:00:04 UTC
The flag is_ipv6 is set by:

        /* Identify IP packets and fill up variables. */
        if (pktlen >= sizeof(struct ip6_hdr) &&
            (eh == NULL || eh->ether_type == htons(ETHERTYPE_IPV6)) &&
            ip->ip_v == 6) {
                struct ip6_hdr *ip6 = (struct ip6_hdr *)ip;

                is_ipv6 = 1;

Test ip->ip_v seems correct
Comment 3 Olivier Cochard freebsd_committer 2019-11-26 09:39:13 UTC
Created attachment 209447 [details]
Allow using 'ipver 6' as matching rule

Here is a prototype of a patch that fix this problem.
Not sure if I could use is_ipv6() outside an #ifdef INET6.

But with this applied, now using 'ipver 6' as matching rule is fixed:

[root@router]~# ipfw show
00100 4 336 allow ipver 4 proto icmp
00200 8 504 allow ipver 6 proto ipv6-icmp
65535 4 272 deny ip from any to any
Comment 4 Andrey V. Elsukov freebsd_committer 2019-11-26 09:48:29 UTC
As I said before, this opcode is designed to match ip_v field of IPv4 header. It already works as expected.
If you want to match IPv4 or IPv6 packets, you can use corresponding opcodes, they are "ip4" and "ip6".
Comment 5 Freddy DISSAUX 2019-11-27 19:02:10 UTC
Dear Andrey,

You are right. Sorry for the noise,