Bug 200169

Summary: ipfw table list uses IPv6 format for zero IPv4 addresses
Product: Base System Reporter: zuborg
Component: kernAssignee: freebsd-ipfw (Nobody) <ipfw>
Status: Closed FIXED    
Severity: Affects Many People CC: ae, allanjude, egypcio, gondim, pi, re
Priority: ---    
Version: 10.1-RELEASE   
Hardware: Any   
OS: Any   

Description zuborg 2015-05-13 12:42:31 UTC
`ipfw table N list` command print '::' string instead of '0.0.0.0' for some reason. Even on systems without IPv6 support.
While `ipfw table N delete` require 0.0.0.0 to operate correctly.

Here is log of terminal:
(System without IPv6 support)
# ipfw table 1 list
# ipfw table 1 add 0.0.0.0/8
# ipfw table 1 list
::/8 0
# ipfw table 1 delete ::/8
ipfw: setsockopt(IP_FW_TABLE_XDEL): Invalid argument
# ipfw table 1 list
::/8 0
# ipfw table 1 delete 0.0.0.0/8
# ipfw table 1 list
# 

(System with IPv6 support)
# ipfw table 1 list
# ipfw table 1 add ::/8
# ipfw table 1 list
::/8 0
# ipfw table 1 add 0.0.0.0/8
# ipfw table 1 list
::/8 0
::/8 0
# ipfw table 1 delete ::/8
# ipfw table 1 list
::/8 0
# ipfw table 1 delete ::/8
ipfw: setsockopt(IP_FW_TABLE_XDEL): No such process
# ipfw table 1 list
::/8 0
# ipfw table 1 delete 0.0.0.0/8
# ipfw table 1 list
#
Comment 1 zuborg 2015-05-13 16:03:37 UTC
The problem is in IN6_IS_ADDR_V4COMPAT macro:
ipfw2.c:

static void
table_list(uint16_t num, int need_header)
...
                        if (IN6_IS_ADDR_V4COMPAT(addr6)) {
                                /* IPv4 address */
                                inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
                        } else {
                                /* IPv6 address */
                                inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf));
                        }
...

netinet6/in6.h:

/*
 * IPv4 compatible
 */
#define IN6_IS_ADDR_V4COMPAT(a)         \
        ((a)->__u6_addr.__u6_addr32[0] == 0 &&  \
         (a)->__u6_addr.__u6_addr32[1] == 0 &&  \
         (a)->__u6_addr.__u6_addr32[2] == 0 &&  \
         (a)->__u6_addr.__u6_addr32[3] != 0 &&  \
         (a)->__u6_addr.__u6_addr32[3] != ntohl(1))

this macro consider values 0.0.0.0 and 0.0.0.1 as non IPv4 compatible.

# ipfw table 1 flush
# ipfw table 1 add 0.0.0.0/32
# ipfw table 1 add 0.0.0.1/32
# ipfw table 1 add 0.0.0.2/32
# ipfw table 1 add 0.0.0.128/32
# ipfw table 1 list
::/32 0
::1/32 0
0.0.0.2/32 0
0.0.0.128/32 0
#
Comment 2 Kurt Jaeger freebsd_committer 2015-07-24 14:29:37 UTC
Fixed in HEAD with

https://lists.freebsd.org/pipermail/svn-src-all/2014-May/085380.html
r266310, based on PR 189471.

Can this be merged to 10.2 before REL ?
Comment 3 Vinícius Zavam freebsd_committer 2015-09-18 14:02:11 UTC
(In reply to Kurt Jaeger from comment #2)

HEAD is okay.

# uname -a
FreeBSD box 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r287824: Tue Sep 15 14:35:24 BRT 2015     root@box:/usr/obj/panzer/freebsd/base/sys/BOX  amd64
# kldload ipfw
# ipfw table 123 create
# ipfw table 123 add 0.0.0.0/8
added: 0.0.0.0/8 0
# ipfw table 123 list
--- table(123), set(0) ---
0.0.0.0/8 0

STABLE/10 still not patched. How to reproduce:

# sysctl -n hw.model
Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz
# fetch ftp://ftp.geo.freebsd.org/pub/FreeBSD/snapshots/VM-IMAGES/10.2-STABLE/i386/Latest/FreeBSD-10.2-STABLE-i386.raw.xz
FreeBSD-10.2-STABLE-i386.raw.xz               100% of  125 MB  192 kBps 11m06s
# xz -d FreeBSD-10.2-STABLE-i386.raw.xz
# kldload vmm
# /bin/sh /usr/share/examples/bhyve/vmrun.sh -d FreeBSD-10.2-STABLE-i386.raw vm0

[bhyve]
  root@:~ # uname -a
  FreeBSD  10.2-STABLE FreeBSD 10.2-STABLE #0 r287435: Thu Sep  3 22:15:32 UTC 2015     root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  i386
  root@:~ # kldload ipfw
  ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled
  root@:~ # ipfw table 123 add 0.0.0.0/8
  root@:~ # ipfw table 123 list
  ::/8 0
[/bhyve]
Comment 4 commit-hook freebsd_committer 2015-09-18 17:29:49 UTC
A commit references this bug:

Author: melifaro
Date: Fri Sep 18 17:29:25 UTC 2015
New revision: 287963
URL: https://svnweb.freebsd.org/changeset/base/287963

Log:
  MFC r266310

    Fix wrong formatting of 0.0.0.0/X table records in ipfw(8).

    Add `flags` u16 field to the hole in ipfw_table_xentry structure.
    Kernel has been guessing address family for supplied record based
    on xent length size.
    Userland, however, has been getting fixed-size ipfw_table_xentry structures
    guessing address family by checking address by IN6_IS_ADDR_V4COMPAT().

    Fix this behavior by providing specific IPFW_TCF_INET flag for IPv4 records.

  PR:		bin/189471,kern/200169

Changes:
_U  stable/10/
  stable/10/sbin/ipfw/ipfw2.c
  stable/10/sys/netinet/ip_fw.h
  stable/10/sys/netpfil/ipfw/ip_fw_table.c
Comment 5 gondim 2015-09-21 18:55:16 UTC
Thanks melifaro! Your commit in revision [1] fixed the problem.

[1] https://svnweb.freebsd.org/changeset/base/287963