From man ipfw: ... RULE OPTIONS (MATCH PATTERNS) ... 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)); break; ... 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 Regards,
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.
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
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
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".
Dear Andrey, You are right. Sorry for the noise, Regards.