From owner-svn-src-stable@freebsd.org Mon Apr 3 08:50:57 2017 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DA859D27081; Mon, 3 Apr 2017 08:50:57 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 944A81EE; Mon, 3 Apr 2017 08:50:57 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v338oulC078935; Mon, 3 Apr 2017 08:50:56 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v338othf078916; Mon, 3 Apr 2017 08:50:55 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201704030850.v338othf078916@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Mon, 3 Apr 2017 08:50:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r316446 - in stable/11: sbin/ipfw sys/conf sys/modules sys/modules/ipfw sys/modules/ipfw_nat64 sys/netinet sys/netinet6 sys/netpfil/ipfw sys/netpfil/ipfw/nat64 X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Apr 2017 08:50:58 -0000 Author: ae Date: Mon Apr 3 08:50:54 2017 New Revision: 316446 URL: https://svnweb.freebsd.org/changeset/base/316446 Log: MFC r304041: Move logging via BPF support into separate file. * make interface cloner VNET-aware; * simplify cloner code and use if_clone_simple(); * migrate LOGIF_LOCK() to rmlock; * add ipfw_bpf_mtap2() function to pass mbuf to BPF; * introduce new additional ipfwlog0 pseudo interface. It differs from ipfw0 by DLT type used in bpfattach. This interface is intended to used by ipfw modules to dump packets with additional info attached. Currently pflog format is used. ipfw_bpf_mtap2() function uses second argument to determine which interface use for dumping. If dlen is equal to ETHER_HDR_LEN it uses old ipfw0 interface, if dlen is equal to PFLOG_HDRLEN - ipfwlog0 will be used. Obtained from: Yandex LLC Sponsored by: Yandex LLC MFC r304043: Add three helper function to manage tables from external modules. ipfw_objhash_lookup_table_kidx does lookup kernel index of table; ipfw_ref_table/ipfw_unref_table takes and releases reference to table. Obtained from: Yandex LLC Sponsored by: Yandex LLC MFC r304046, 304108: Add ipfw_nat64 module that implements stateless and stateful NAT64. The module works together with ipfw(4) and implemented as its external action module. Stateless NAT64 registers external action with name nat64stl. This keyword should be used to create NAT64 instance and to address this instance in rules. Stateless NAT64 uses two lookup tables with mapped IPv4->IPv6 and IPv6->IPv4 addresses to perform translation. A configuration of instance should looks like this: 1. Create lookup tables: # ipfw table T46 create type addr valtype ipv6 # ipfw table T64 create type addr valtype ipv4 2. Fill T46 and T64 tables. 3. Add rule to allow neighbor solicitation and advertisement: # ipfw add allow icmp6 from any to any icmp6types 135,136 4. Create NAT64 instance: # ipfw nat64stl NAT create table4 T46 table6 T64 5. Add rules that matches the traffic: # ipfw add nat64stl NAT ip from any to table(T46) # ipfw add nat64stl NAT ip from table(T64) to 64:ff9b::/96 6. Configure DNS64 for IPv6 clients and add route to 64:ff9b::/96 via NAT64 host. Stateful NAT64 registers external action with name nat64lsn. The only one option required to create nat64lsn instance - prefix4. It defines the pool of IPv4 addresses used for translation. A configuration of instance should looks like this: 1. Add rule to allow neighbor solicitation and advertisement: # ipfw add allow icmp6 from any to any icmp6types 135,136 2. Create NAT64 instance: # ipfw nat64lsn NAT create prefix4 A.B.C.D/28 3. Add rules that matches the traffic: # ipfw add nat64lsn NAT ip from any to A.B.C.D/28 # ipfw add nat64lsn NAT ip6 from any to 64:ff9b::/96 4. Configure DNS64 for IPv6 clients and add route to 64:ff9b::/96 via NAT64 host. Obtained from: Yandex LLC Relnotes: yes Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D6434 MFC r304048: Replace __noinline with special debug macro NAT64NOINLINE. MFC r304061: Use %ju to print unsigned 64-bit value. MFC r304076: Make statistics nat64lsn, nat64stl an nptv6 output netstat-like: "@value @description" and fix build due to -Wformat errors. MFC r304378 (by bz): Try to fix gcc compilation errors (which are right). nat64_getlasthdr() returns an int, which can be -1 in case of error, storing the result in an uint8_t and then comparing to < 0 is not helpful. Do what is done in the rest of the code and make proto an int here as well. MFC r309187: Fix ICMPv6 Time Exceeded error message translation. MFC r314718: Use new ipfw_lookup_table() in the nat64 too. MFC r315204,315233: Use memset with structure size. Added: stable/11/sbin/ipfw/nat64lsn.c - copied, changed from r304046, head/sbin/ipfw/nat64lsn.c stable/11/sbin/ipfw/nat64stl.c - copied, changed from r304046, head/sbin/ipfw/nat64stl.c stable/11/sys/modules/ipfw_nat64/ - copied from r304046, head/sys/modules/ipfw_nat64/ stable/11/sys/netinet6/ip_fw_nat64.h - copied unchanged from r304046, head/sys/netinet6/ip_fw_nat64.h stable/11/sys/netpfil/ipfw/ip_fw_bpf.c - copied unchanged from r304041, head/sys/netpfil/ipfw/ip_fw_bpf.c stable/11/sys/netpfil/ipfw/nat64/ - copied from r304046, head/sys/netpfil/ipfw/nat64/ Modified: stable/11/sbin/ipfw/Makefile stable/11/sbin/ipfw/ipfw.8 stable/11/sbin/ipfw/ipfw2.c stable/11/sbin/ipfw/ipfw2.h stable/11/sbin/ipfw/main.c stable/11/sbin/ipfw/tables.c stable/11/sys/conf/NOTES stable/11/sys/conf/files stable/11/sys/conf/options stable/11/sys/modules/Makefile stable/11/sys/modules/ipfw/Makefile stable/11/sys/netinet/ip_fw.h stable/11/sys/netpfil/ipfw/ip_fw2.c stable/11/sys/netpfil/ipfw/ip_fw_log.c stable/11/sys/netpfil/ipfw/ip_fw_private.h stable/11/sys/netpfil/ipfw/ip_fw_table.c stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c stable/11/sys/netpfil/ipfw/nat64/nat64lsn.c stable/11/sys/netpfil/ipfw/nat64/nat64lsn_control.c stable/11/sys/netpfil/ipfw/nat64/nat64stl.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sbin/ipfw/Makefile ============================================================================== --- stable/11/sbin/ipfw/Makefile Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/Makefile Mon Apr 3 08:50:54 2017 (r316446) @@ -5,7 +5,7 @@ PACKAGE=ipfw PROG= ipfw SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c tables.c -SRCS+= nptv6.c +SRCS+= nat64lsn.c nat64stl.c nptv6.c WARNS?= 2 .if ${MK_PF} != "no" Modified: stable/11/sbin/ipfw/ipfw.8 ============================================================================== --- stable/11/sbin/ipfw/ipfw.8 Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/ipfw.8 Mon Apr 3 08:50:54 2017 (r316446) @@ -113,6 +113,37 @@ in-kernel NAT. .Oc .Oc .Ar pathname +.Ss STATEFUL IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION +.Nm +.Oo Cm set Ar N Oc Cm nat64lsn Ar name Cm create Ar create-options +.Nm +.Oo Cm set Ar N Oc Cm nat64lsn Ar name Cm config Ar config-options +.Nm +.Oo Cm set Ar N Oc Cm nat64lsn +.Brq Ar name | all +.Brq Cm list | show +.Op Cm states +.Nm +.Oo Cm set Ar N Oc Cm nat64lsn +.Brq Ar name | all +.Cm destroy +.Nm +.Oo Cm set Ar N Oc Cm nat64lsn Ar name Cm stats Op Cm reset +.Ss STATELESS IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION +.Nm +.Oo Cm set Ar N Oc Cm nat64stl Ar name Cm create Ar create-options +.Nm +.Oo Cm set Ar N Oc Cm nat64stl Ar name Cm config Ar config-options +.Nm +.Oo Cm set Ar N Oc Cm nat64stl +.Brq Ar name | all +.Brq Cm list | show +.Nm +.Oo Cm set Ar N Oc Cm nat64stl +.Brq Ar name | all +.Cm destroy +.Nm +.Oo Cm set Ar N Oc Cm nat64stl Ar name Cm stats Op Cm reset .Ss IPv6-to-IPv6 NETWORK PREFIX TRANSLATION .Nm .Oo Cm set Ar N Oc Cm nptv6 Ar name Cm create Ar create-options @@ -837,6 +868,16 @@ nat instance see the .Sx NETWORK ADDRESS TRANSLATION (NAT) Section for further information. +.It Cm nat64lsn Ar name +Pass packet to a stateful NAT64 instance (for IPv6/IPv4 network address and +protocol translation): see the +.Sx IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION +Section for further information. +.It Cm nat64stl Ar name +Pass packet to a stateless NAT64 instance (for IPv6/IPv4 network address and +protocol translation): see the +.Sx IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION +Section for further information. .It Cm nptv6 Ar name Pass packet to a NPTv6 instance (for IPv6-to-IPv6 network prefix translation): see the @@ -2944,9 +2985,189 @@ instances. See .Sx SYSCTL VARIABLES for more info. +.Sh IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION +.Nm +supports in-kernel IPv6/IPv4 network address and protocol translation. +Stateful NAT64 translation allows IPv6-only clients to contact IPv4 servers +using unicast TCP, UDP or ICMP protocols. +One or more IPv4 addresses assigned to a stateful NAT64 translator are shared +among serveral IPv6-only clients. +When stateful NAT64 is used in conjunction with DNS64, no changes are usually +required in the IPv6 client or the IPv4 server. +The kernel module +.Cm ipfw_nat64 +should be loaded or kernel should have +.Cm options IPFIREWALL_NAT64 +to be able use stateful NAT64 translator. +.Pp +Stateful NAT64 uses a bunch of memory for several types of objects. +When IPv6 client initiates connection, NAT64 translator creates a host entry +in the states table. +Each host entry has a number of ports group entries allocated on demand. +Ports group entries contains connection state entries. +There are several options to control limits and lifetime for these objects. +.Pp +NAT64 translator follows RFC7915 when does ICMPv6/ICMP translation, +unsupported message types will be silently dropped. +IPv6 needs several ICMPv6 message types to be explicitly allowed for correct +operation. +Make sure that ND6 neighbor solicitation (ICMPv6 type 135) and neighbor +advertisement (ICMPv6 type 136) messages will not be handled by translation +rules. +.Pp +After translation NAT64 translator sends packets through corresponding netisr +queue. +Thus translator host should be configured as IPv4 and IPv6 router. +.Pp +Currently both stateful and stateless NAT64 translators use Well-Known IPv6 +Prefix +.Ar 64:ff9b::/96 +to represent IPv4 addresses in the IPv6 address. +Thus DNS64 service and routing should be configured to use Well-Known IPv6 +Prefix. +.Pp +The stateful NAT64 configuration command is the following: +.Bd -ragged -offset indent +.Bk -words +.Cm nat64lsn +.Ar name +.Cm create +.Ar create-options +.Ek +.Ed +.Pp +The following parameters can be configured: +.Bl -tag -width indent +.It Cm prefix4 Ar ipv4_prefix/mask +The IPv4 prefix with mask defines the pool of IPv4 addresses used as +source address after translation. +Stateful NAT64 module translates IPv6 source address of client to one +IPv4 address from this pool. +Note that incoming IPv4 packets that don't have corresponding state entry +in the states table will be dropped by translator. +Make sure that translation rules handle packets, destined to configured prefix. +.It Cm max_ports Ar number +Maximum number of ports reserved for upper level protocols to one IPv6 client. +All reserved ports are divided into chunks between supported protocols. +The number of connections from one IPv6 client is limited by this option. +Note that closed TCP connections still remain in the list of connections until +.Cm tcp_close_age +interval will not expire. +Default value is +.Ar 2048 . +.It Cm host_del_age Ar seconds +The number of seconds until the host entry for a IPv6 client will be deleted +and all its resources will be released due to inactivity. +Default value is +.Ar 3600 . +.It Cm pg_del_age Ar seconds +The number of seconds until a ports group with unused state entries will +be released. +Default value is +.Ar 900 . +.It Cm tcp_syn_age Ar seconds +The number of seconds while a state entry for TCP connection with only SYN +sent will be kept. +If TCP connection establishing will not be finished, +state entry will be deleted. +Default value is +.Ar 10 . +.It Cm tcp_est_age Ar seconds +The number of seconds while a state entry for established TCP connection +will be kept. +Default value is +.Ar 7200 . +.It Cm tcp_close_age Ar seconds +The number of seconds while a state entry for closed TCP connection +will be kept. +Keeping state entries for closed connections is needed, because IPv4 servers +typically keep closed connections in a TIME_WAIT state for a several minutes. +Since translator's IPv4 addresses are shared among all IPv6 clients, +new connections from the same addresses and ports may be rejected by server, +because these connections are still in a TIME_WAIT state. +Keeping them in translator's state table protects from such rejects. +Default value is +.Ar 180 . +.It Cm udp_age Ar seconds +The number of seconds while translator keeps state entry in a waiting for +reply to the sent UDP datagram. +Default value is +.Ar 120 . +.It Cm icmp_age Ar seconds +The number of seconds while translator keeps state entry in a waiting for +reply to the sent ICMP message. +Default value is +.Ar 60 . +.It Cm log +Turn on logging of all handled packets via BPF through +.Ar ipfwlog0 +interface. +.Ar ipfwlog0 +is a pseudo interface and can be created after a boot manually with +.Cm ifconfig +command. +Note that it has different purpose than +.Ar ipfw0 +interface. +Translators sends to BPF an additional information with each packet. +With +.Cm tcpdump +you are able to see each handled packet before and after translation. +.It Cm -log +Turn off logging of all handled packets via BPF. +.El +.Pp +To inspect a states table of stateful NAT64 the following command can be used: +.Bd -ragged -offset indent +.Bk -words +.Cm nat64lsn +.Ar name +.Cm show Cm states +.Ek +.Ed +.Pp +.Pp +Stateless NAT64 translator doesn't use a states table for translation +and converts IPv4 addresses to IPv6 and vice versa solely based on the +mappings taken from configured lookup tables. +Since a states table doesn't used by stateless translator, +it can be configured to pass IPv4 clients to IPv6-only servers. +.Pp +The stateless NAT64 configuration command is the following: +.Bd -ragged -offset indent +.Bk -words +.Cm nat64stl +.Ar name +.Cm create +.Ar create-options +.Ek +.Ed +.Pp +The following parameters can be configured: +.Bl -tag -width indent +.It Cm table4 Ar table46 +The lookup table +.Ar table46 +contains mapping how IPv4 addresses should be translated to IPv6 addresses. +.It Cm table6 Ar table64 +The lookup table +.Ar table64 +contains mapping how IPv6 addresses should be translated to IPv4 addresses. +.It Cm log +Turn on logging of all handled packets via BPF through +.Ar ipfwlog0 +interface. +.It Cm -log +Turn off logging of all handled packets via BPF. +.El +.Pp +Note that the behavior of stateless translator with respect to not matched +packets differs from stateful translator. +If corresponding addresses was not found in the lookup tables, the packet +will not be dropped and the search continues. .Sh IPv6-to-IPv6 NETWORK PREFIX TRANSLATION (NPTv6) .Nm -support in-kernel IPv6-to-IPv6 network prefix translation as described +supports in-kernel IPv6-to-IPv6 network prefix translation as described in RFC6296. The kernel module .Cm ipfw_nptv6 Modified: stable/11/sbin/ipfw/ipfw2.c ============================================================================== --- stable/11/sbin/ipfw/ipfw2.c Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/ipfw2.c Mon Apr 3 08:50:54 2017 (r316446) @@ -235,6 +235,8 @@ static struct _s_x ether_types[] = { }; static struct _s_x rule_eactions[] = { + { "nat64lsn", TOK_NAT64LSN }, + { "nat64stl", TOK_NAT64STL }, { "nptv6", TOK_NPTV6 }, { NULL, 0 } /* terminator */ }; Modified: stable/11/sbin/ipfw/ipfw2.h ============================================================================== --- stable/11/sbin/ipfw/ipfw2.h Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/ipfw2.h Mon Apr 3 08:50:54 2017 (r316446) @@ -254,7 +254,30 @@ enum tokens { TOK_UNLOCK, TOK_VLIST, TOK_OLIST, + + /* NAT64 tokens */ + TOK_NAT64STL, + TOK_NAT64LSN, TOK_STATS, + TOK_STATES, + TOK_CONFIG, + TOK_TABLE4, + TOK_TABLE6, + TOK_PREFIX4, + TOK_PREFIX6, + TOK_AGG_LEN, + TOK_AGG_COUNT, + TOK_MAX_PORTS, + TOK_JMAXLEN, + TOK_PORT_RANGE, + TOK_HOST_DEL_AGE, + TOK_PG_DEL_AGE, + TOK_TCP_SYN_AGE, + TOK_TCP_CLOSE_AGE, + TOK_TCP_EST_AGE, + TOK_UDP_AGE, + TOK_ICMP_AGE, + TOK_LOGOFF, /* NPTv6 tokens */ TOK_NPTV6, @@ -347,6 +370,8 @@ void ipfw_flush(int force); void ipfw_zero(int ac, char *av[], int optname); void ipfw_list(int ac, char *av[], int show_counters); void ipfw_internal_handler(int ac, char *av[]); +void ipfw_nat64lsn_handler(int ac, char *av[]); +void ipfw_nat64stl_handler(int ac, char *av[]); void ipfw_nptv6_handler(int ac, char *av[]); int ipfw_check_object_name(const char *name); @@ -389,7 +414,10 @@ void fill_table(struct _ipfw_insn *cmd, /* tables.c */ struct _ipfw_obj_ctlv; +struct _ipfw_obj_ntlv; int table_check_name(const char *tablename); void ipfw_list_ta(int ac, char *av[]); void ipfw_list_values(int ac, char *av[]); +void table_fill_ntlv(struct _ipfw_obj_ntlv *ntlv, const char *name, + uint8_t set, uint16_t uidx); Modified: stable/11/sbin/ipfw/main.c ============================================================================== --- stable/11/sbin/ipfw/main.c Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/main.c Mon Apr 3 08:50:54 2017 (r316446) @@ -425,6 +425,10 @@ ipfw_main(int oldac, char **oldav) if (co.use_set || try_next) { if (_substrcmp(*av, "delete") == 0) ipfw_delete(av); + else if (!strncmp(*av, "nat64stl", strlen(*av))) + ipfw_nat64stl_handler(ac, av); + else if (!strncmp(*av, "nat64lsn", strlen(*av))) + ipfw_nat64lsn_handler(ac, av); else if (!strncmp(*av, "nptv6", strlen(*av))) ipfw_nptv6_handler(ac, av); else if (_substrcmp(*av, "flush") == 0) Copied and modified: stable/11/sbin/ipfw/nat64lsn.c (from r304046, head/sbin/ipfw/nat64lsn.c) ============================================================================== --- head/sbin/ipfw/nat64lsn.c Sat Aug 13 16:09:49 2016 (r304046, copy source) +++ stable/11/sbin/ipfw/nat64lsn.c Mon Apr 3 08:50:54 2017 (r316446) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -687,7 +688,6 @@ nat64lsn_get_stats(const char *name, uin return (-1); } -#define _P_STAT(_s, _f) printf("%8s:\t%lu\n", #_f, _s._f) static void nat64lsn_stats(const char *name, uint8_t set) { @@ -696,34 +696,61 @@ nat64lsn_stats(const char *name, uint8_t if (nat64lsn_get_stats(name, set, &stats) != 0) err(EX_OSERR, "Error retrieving stats"); - _P_STAT(stats, opcnt64); - _P_STAT(stats, opcnt46); - _P_STAT(stats, ofrags); - _P_STAT(stats, ifrags); - _P_STAT(stats, oerrors); - _P_STAT(stats, noroute4); - _P_STAT(stats, noroute6); - _P_STAT(stats, noproto); - _P_STAT(stats, nomem); - _P_STAT(stats, dropped); - - _P_STAT(stats, hostcount); - _P_STAT(stats, tcpchunks); - _P_STAT(stats, udpchunks); - _P_STAT(stats, icmpchunks); - _P_STAT(stats, jcalls); - _P_STAT(stats, jrequests); - _P_STAT(stats, jhostsreq); - _P_STAT(stats, jportreq); - _P_STAT(stats, jhostfails); - _P_STAT(stats, jportfails); - _P_STAT(stats, jreinjected); - _P_STAT(stats, jmaxlen); - _P_STAT(stats, jnomem); - _P_STAT(stats, screated); - _P_STAT(stats, sdeleted); - _P_STAT(stats, spgcreated); - _P_STAT(stats, spgdeleted); + if (co.use_set != 0 || set != 0) + printf("set %u ", set); + printf("nat64lsn %s\n", name); + printf("\t%ju packets translated from IPv6 to IPv4\n", + (uintmax_t)stats.opcnt64); + printf("\t%ju packets translated from IPv4 to IPv6\n", + (uintmax_t)stats.opcnt46); + printf("\t%ju IPv6 fragments created\n", + (uintmax_t)stats.ofrags); + printf("\t%ju IPv4 fragments received\n", + (uintmax_t)stats.ifrags); + printf("\t%ju output packets dropped due to no bufs, etc.\n", + (uintmax_t)stats.oerrors); + printf("\t%ju output packets discarded due to no IPv4 route\n", + (uintmax_t)stats.noroute4); + printf("\t%ju output packets discarded due to no IPv6 route\n", + (uintmax_t)stats.noroute6); + printf("\t%ju packets discarded due to unsupported protocol\n", + (uintmax_t)stats.noproto); + printf("\t%ju packets discarded due to memory allocation problems\n", + (uintmax_t)stats.nomem); + printf("\t%ju packets discarded due to some errors\n", + (uintmax_t)stats.dropped); + printf("\t%ju packets not matched with IPv4 prefix\n", + (uintmax_t)stats.nomatch4); + + printf("\t%ju mbufs queued for post processing\n", + (uintmax_t)stats.jreinjected); + printf("\t%ju times the job queue was processed\n", + (uintmax_t)stats.jcalls); + printf("\t%ju job requests queued\n", + (uintmax_t)stats.jrequests); + printf("\t%ju job requests queue limit reached\n", + (uintmax_t)stats.jmaxlen); + printf("\t%ju job requests failed due to memory allocation problems\n", + (uintmax_t)stats.jnomem); + + printf("\t%ju hosts allocated\n", (uintmax_t)stats.hostcount); + printf("\t%ju hosts requested\n", (uintmax_t)stats.jhostsreq); + printf("\t%ju host requests failed\n", (uintmax_t)stats.jhostfails); + + printf("\t%ju portgroups requested\n", (uintmax_t)stats.jportreq); + printf("\t%ju portgroups allocated\n", (uintmax_t)stats.spgcreated); + printf("\t%ju portgroups deleted\n", (uintmax_t)stats.spgdeleted); + printf("\t%ju portgroup requests failed\n", + (uintmax_t)stats.jportfails); + printf("\t%ju portgroups allocated for TCP\n", + (uintmax_t)stats.tcpchunks); + printf("\t%ju portgroups allocated for UDP\n", + (uintmax_t)stats.udpchunks); + printf("\t%ju portgroups allocated for ICMP\n", + (uintmax_t)stats.icmpchunks); + + printf("\t%ju states created\n", (uintmax_t)stats.screated); + printf("\t%ju states deleted\n", (uintmax_t)stats.sdeleted); } static int Copied and modified: stable/11/sbin/ipfw/nat64stl.c (from r304046, head/sbin/ipfw/nat64stl.c) ============================================================================== --- head/sbin/ipfw/nat64stl.c Sat Aug 13 16:09:49 2016 (r304046, copy source) +++ stable/11/sbin/ipfw/nat64stl.c Mon Apr 3 08:50:54 2017 (r316446) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -386,7 +387,6 @@ nat64stl_get_stats(const char *name, uin return (-1); } -#define _P_STAT(_s, _f) printf("%8s:\t%lu\n", #_f, _s._f) static void nat64stl_stats(const char *name, uint8_t set) { @@ -395,16 +395,30 @@ nat64stl_stats(const char *name, uint8_t if (nat64stl_get_stats(name, set, &stats) != 0) err(EX_OSERR, "Error retrieving stats"); - _P_STAT(stats, opcnt64); - _P_STAT(stats, opcnt46); - _P_STAT(stats, ofrags); - _P_STAT(stats, ifrags); - _P_STAT(stats, oerrors); - _P_STAT(stats, noroute4); - _P_STAT(stats, noroute6); - _P_STAT(stats, noproto); - _P_STAT(stats, nomem); - _P_STAT(stats, dropped); + if (co.use_set != 0 || set != 0) + printf("set %u ", set); + printf("nat64stl %s\n", name); + + printf("\t%ju packets translated from IPv6 to IPv4\n", + (uintmax_t)stats.opcnt64); + printf("\t%ju packets translated from IPv4 to IPv6\n", + (uintmax_t)stats.opcnt46); + printf("\t%ju IPv6 fragments created\n", + (uintmax_t)stats.ofrags); + printf("\t%ju IPv4 fragments received\n", + (uintmax_t)stats.ifrags); + printf("\t%ju output packets dropped due to no bufs, etc.\n", + (uintmax_t)stats.oerrors); + printf("\t%ju output packets discarded due to no IPv4 route\n", + (uintmax_t)stats.noroute4); + printf("\t%ju output packets discarded due to no IPv6 route\n", + (uintmax_t)stats.noroute6); + printf("\t%ju packets discarded due to unsupported protocol\n", + (uintmax_t)stats.noproto); + printf("\t%ju packets discarded due to memory allocation problems\n", + (uintmax_t)stats.nomem); + printf("\t%ju packets discarded due to some errors\n", + (uintmax_t)stats.dropped); } /* Modified: stable/11/sbin/ipfw/tables.c ============================================================================== --- stable/11/sbin/ipfw/tables.c Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sbin/ipfw/tables.c Mon Apr 3 08:50:54 2017 (r316446) @@ -53,8 +53,6 @@ static void table_lock(ipfw_obj_header * static int table_swap(ipfw_obj_header *oh, char *second); static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i); static int table_show_info(ipfw_xtable_info *i, void *arg); -static void table_fill_ntlv(ipfw_obj_ntlv *ntlv, const char *name, - uint32_t set, uint16_t uidx); static int table_flush_one(ipfw_xtable_info *i, void *arg); static int table_show_one(ipfw_xtable_info *i, void *arg); @@ -155,7 +153,7 @@ ipfw_table_handler(int ac, char *av[]) ipfw_xtable_info i; ipfw_obj_header oh; char *tablename; - uint32_t set; + uint8_t set; void *arg; memset(&oh, 0, sizeof(oh)); @@ -292,8 +290,8 @@ ipfw_table_handler(int ac, char *av[]) } } -static void -table_fill_ntlv(ipfw_obj_ntlv *ntlv, const char *name, uint32_t set, +void +table_fill_ntlv(ipfw_obj_ntlv *ntlv, const char *name, uint8_t set, uint16_t uidx) { Modified: stable/11/sys/conf/NOTES ============================================================================== --- stable/11/sys/conf/NOTES Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/conf/NOTES Mon Apr 3 08:50:54 2017 (r316446) @@ -953,6 +953,8 @@ device lagg # IPFIREWALL_NAT adds support for in kernel nat in ipfw, and it requires # LIBALIAS. # +# IPFIREWALL_NAT64 adds support for in kernel NAT64 in ipfw. +# # IPFIREWALL_NPTV6 adds support for in kernel NPTv6 in ipfw. # # IPSTEALTH enables code to support stealth forwarding (i.e., forwarding @@ -976,6 +978,7 @@ options IPFIREWALL_VERBOSE #enable logg options IPFIREWALL_VERBOSE_LIMIT=100 #limit verbosity options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default options IPFIREWALL_NAT #ipfw kernel nat support +options IPFIREWALL_NAT64 #ipfw kernel NAT64 support options IPFIREWALL_NPTV6 #ipfw kernel IPv6 NPT support options IPDIVERT #divert sockets options IPFILTER #ipfilter support Modified: stable/11/sys/conf/files ============================================================================== --- stable/11/sys/conf/files Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/conf/files Mon Apr 3 08:50:54 2017 (r316446) @@ -3932,6 +3932,7 @@ netpfil/ipfw/ip_dummynet.c optional inet netpfil/ipfw/ip_dn_io.c optional inet dummynet netpfil/ipfw/ip_dn_glue.c optional inet dummynet netpfil/ipfw/ip_fw2.c optional inet ipfirewall +netpfil/ipfw/ip_fw_bpf.c optional inet ipfirewall netpfil/ipfw/ip_fw_dynamic.c optional inet ipfirewall netpfil/ipfw/ip_fw_eaction.c optional inet ipfirewall netpfil/ipfw/ip_fw_log.c optional inet ipfirewall @@ -3942,6 +3943,18 @@ netpfil/ipfw/ip_fw_table_algo.c optional netpfil/ipfw/ip_fw_table_value.c optional inet ipfirewall netpfil/ipfw/ip_fw_iface.c optional inet ipfirewall netpfil/ipfw/ip_fw_nat.c optional inet ipfirewall_nat +netpfil/ipfw/nat64/ip_fw_nat64.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 +netpfil/ipfw/nat64/nat64lsn.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 +netpfil/ipfw/nat64/nat64lsn_control.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 +netpfil/ipfw/nat64/nat64stl.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 +netpfil/ipfw/nat64/nat64stl_control.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 +netpfil/ipfw/nat64/nat64_translate.c optional inet inet6 ipfirewall \ + ipfirewall_nat64 netpfil/ipfw/nptv6/ip_fw_nptv6.c optional inet inet6 ipfirewall \ ipfirewall_nptv6 netpfil/ipfw/nptv6/nptv6.c optional inet inet6 ipfirewall \ Modified: stable/11/sys/conf/options ============================================================================== --- stable/11/sys/conf/options Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/conf/options Mon Apr 3 08:50:54 2017 (r316446) @@ -419,6 +419,8 @@ IPFILTER_LOOKUP opt_ipfilter.h IPFIREWALL opt_ipfw.h IPFIREWALL_DEFAULT_TO_ACCEPT opt_ipfw.h IPFIREWALL_NAT opt_ipfw.h +IPFIREWALL_NAT64 opt_ipfw.h +IPFIREWALL_NAT64_DIRECT_OUTPUT opt_ipfw.h IPFIREWALL_NPTV6 opt_ipfw.h IPFIREWALL_VERBOSE opt_ipfw.h IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h Modified: stable/11/sys/modules/Makefile ============================================================================== --- stable/11/sys/modules/Makefile Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/modules/Makefile Mon Apr 3 08:50:54 2017 (r316446) @@ -173,6 +173,7 @@ SUBDIR= \ ${_ipfilter} \ ${_ipfw} \ ipfw_nat \ + ${_ipfw_nat64} \ ${_ipfw_nptv6} \ ${_ipmi} \ ip6_mroute_mod \ @@ -473,6 +474,9 @@ _if_stf= if_stf _if_me= if_me _ipdivert= ipdivert _ipfw= ipfw +.if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) +_ipfw_nat64= ipfw_nat64 +.endif .endif .if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) Modified: stable/11/sys/modules/ipfw/Makefile ============================================================================== --- stable/11/sys/modules/ipfw/Makefile Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/modules/ipfw/Makefile Mon Apr 3 08:50:54 2017 (r316446) @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../netpfil/ipfw KMOD= ipfw -SRCS= ip_fw2.c ip_fw_pfil.c +SRCS= ip_fw2.c ip_fw_pfil.c ip_fw_bpf.c SRCS+= ip_fw_dynamic.c ip_fw_log.c ip_fw_eaction.c SRCS+= ip_fw_sockopt.c ip_fw_table.c ip_fw_table_algo.c ip_fw_iface.c SRCS+= ip_fw_table_value.c Modified: stable/11/sys/netinet/ip_fw.h ============================================================================== --- stable/11/sys/netinet/ip_fw.h Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/netinet/ip_fw.h Mon Apr 3 08:50:54 2017 (r316446) @@ -110,6 +110,21 @@ typedef struct _ip_fw3_opheader { #define IP_FW_DUMP_SOPTCODES 116 /* Dump available sopts/versions */ #define IP_FW_DUMP_SRVOBJECTS 117 /* Dump existing named objects */ +#define IP_FW_NAT64STL_CREATE 130 /* Create stateless NAT64 instance */ +#define IP_FW_NAT64STL_DESTROY 131 /* Destroy stateless NAT64 instance */ +#define IP_FW_NAT64STL_CONFIG 132 /* Modify stateless NAT64 instance */ +#define IP_FW_NAT64STL_LIST 133 /* List stateless NAT64 instances */ +#define IP_FW_NAT64STL_STATS 134 /* Get NAT64STL instance statistics */ +#define IP_FW_NAT64STL_RESET_STATS 135 /* Reset NAT64STL instance statistics */ + +#define IP_FW_NAT64LSN_CREATE 140 /* Create stateful NAT64 instance */ +#define IP_FW_NAT64LSN_DESTROY 141 /* Destroy stateful NAT64 instance */ +#define IP_FW_NAT64LSN_CONFIG 142 /* Modify stateful NAT64 instance */ +#define IP_FW_NAT64LSN_LIST 143 /* List stateful NAT64 instances */ +#define IP_FW_NAT64LSN_STATS 144 /* Get NAT64LSN instance statistics */ +#define IP_FW_NAT64LSN_LIST_STATES 145 /* Get stateful NAT64 states */ +#define IP_FW_NAT64LSN_RESET_STATS 146 /* Reset NAT64LSN instance statistics */ + #define IP_FW_NPTV6_CREATE 150 /* Create NPTv6 instance */ #define IP_FW_NPTV6_DESTROY 151 /* Destroy NPTv6 instance */ #define IP_FW_NPTV6_CONFIG 152 /* Modify NPTv6 instance */ @@ -793,11 +808,17 @@ typedef struct _ipfw_obj_tlv { #define IPFW_TLV_RANGE 9 #define IPFW_TLV_EACTION 10 #define IPFW_TLV_COUNTERS 11 +#define IPFW_TLV_OBJDATA 12 #define IPFW_TLV_STATE_NAME 14 #define IPFW_TLV_EACTION_BASE 1000 #define IPFW_TLV_EACTION_NAME(arg) (IPFW_TLV_EACTION_BASE + (arg)) +typedef struct _ipfw_obj_data { + ipfw_obj_tlv head; + void *data[0]; +} ipfw_obj_data; + /* Object name TLV */ typedef struct _ipfw_obj_ntlv { ipfw_obj_tlv head; /* TLV header */ Copied: stable/11/sys/netinet6/ip_fw_nat64.h (from r304046, head/sys/netinet6/ip_fw_nat64.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/11/sys/netinet6/ip_fw_nat64.h Mon Apr 3 08:50:54 2017 (r316446, copy of r304046, head/sys/netinet6/ip_fw_nat64.h) @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2015 Yandex LLC + * Copyright (c) 2015 Alexander V. Chernikov + * Copyright (c) 2016 Andrey V. Elsukov + * All rights reserved. + * + * 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 ``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 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$ + */ + +#ifndef _NETINET6_IP_FW_NAT64_H_ +#define _NETINET6_IP_FW_NAT64_H_ + +struct ipfw_nat64stl_stats { + uint64_t opcnt64; /* 6to4 of packets translated */ + uint64_t opcnt46; /* 4to6 of packets translated */ + uint64_t ofrags; /* number of fragments generated */ + uint64_t ifrags; /* number of fragments received */ + uint64_t oerrors; /* number of output errors */ + uint64_t noroute4; + uint64_t noroute6; + uint64_t noproto; /* Protocol not supported */ + uint64_t nomem; /* mbuf allocation filed */ + uint64_t dropped; /* dropped due to some errors */ +}; + +struct ipfw_nat64lsn_stats { + uint64_t opcnt64; /* 6to4 of packets translated */ + uint64_t opcnt46; /* 4to6 of packets translated */ + uint64_t ofrags; /* number of fragments generated */ + uint64_t ifrags; /* number of fragments received */ + uint64_t oerrors; /* number of output errors */ + uint64_t noroute4; + uint64_t noroute6; + uint64_t noproto; /* Protocol not supported */ + uint64_t nomem; /* mbuf allocation filed */ + uint64_t dropped; /* dropped due to some errors */ + + uint64_t nomatch4; /* No addr/port match */ + uint64_t jcalls; /* Number of job handler calls */ + uint64_t jrequests; /* Number of job requests */ + uint64_t jhostsreq; /* Number of job host requests */ + uint64_t jportreq; /* Number of portgroup requests */ + uint64_t jhostfails; /* Number of failed host allocs */ + uint64_t jportfails; /* Number of failed portgroup allocs */ + uint64_t jreinjected; /* Number of packets reinjected to q */ + uint64_t jmaxlen; /* Max queue length reached */ + uint64_t jnomem; /* No memory to alloc queue item */ + + uint64_t screated; /* Number of states created */ + uint64_t sdeleted; /* Number of states deleted */ + uint64_t spgcreated; /* Number of portgroups created */ + uint64_t spgdeleted; /* Number of portgroups deleted */ + uint64_t hostcount; /* Number of hosts */ + uint64_t tcpchunks; /* Number of TCP chunks */ + uint64_t udpchunks; /* Number of UDP chunks */ + uint64_t icmpchunks; /* Number of ICMP chunks */ + + uint64_t _reserved[4]; +}; + +#define NAT64_LOG 0x0001 /* Enable logging via BPF */ + +typedef struct _ipfw_nat64stl_cfg { + char name[64]; /* NAT name */ + ipfw_obj_ntlv ntlv6; /* object name tlv */ + ipfw_obj_ntlv ntlv4; /* object name tlv */ + struct in6_addr prefix6; /* NAT64 prefix */ + uint8_t plen6; /* Prefix length */ + uint8_t set; /* Named instance set [0..31] */ + uint8_t spare[2]; + uint32_t flags; +} ipfw_nat64stl_cfg; + +/* + * NAT64LSN default configuration values + */ +#define NAT64LSN_MAX_PORTS 2048 /* Max number of ports per host */ +#define NAT64LSN_JMAXLEN 2048 /* Max outstanding requests. */ +#define NAT64LSN_TCP_SYN_AGE 10 /* State's TTL after SYN received. */ +#define NAT64LSN_TCP_EST_AGE (2 * 3600) /* TTL for established connection */ +#define NAT64LSN_TCP_FIN_AGE 180 /* State's TTL after FIN/RST received */ +#define NAT64LSN_UDP_AGE 120 /* TTL for UDP states */ +#define NAT64LSN_ICMP_AGE 60 /* TTL for ICMP states */ +#define NAT64LSN_HOST_AGE 3600 /* TTL for stale host entry */ +#define NAT64LSN_PG_AGE 900 /* TTL for stale ports groups */ + +typedef struct _ipfw_nat64lsn_cfg { + char name[64]; /* NAT name */ + uint32_t flags; + uint32_t max_ports; /* Max ports per client */ + uint32_t agg_prefix_len; /* Prefix length to count */ + uint32_t agg_prefix_max; /* Max hosts per agg prefix */ + struct in_addr prefix4; + uint16_t plen4; /* Prefix length */ + uint16_t plen6; /* Prefix length */ + struct in6_addr prefix6; /* NAT64 prefix */ + uint32_t jmaxlen; /* Max jobqueue length */ + uint16_t min_port; /* Min port group # to use */ + uint16_t max_port; /* Max port group # to use */ + uint16_t nh_delete_delay;/* Stale host delete delay */ + uint16_t pg_delete_delay;/* Stale portgroup delete delay */ + uint16_t st_syn_ttl; /* TCP syn expire */ + uint16_t st_close_ttl; /* TCP fin expire */ + uint16_t st_estab_ttl; /* TCP established expire */ + uint16_t st_udp_ttl; /* UDP expire */ + uint16_t st_icmp_ttl; /* ICMP expire */ + uint8_t set; /* Named instance set [0..31] */ + uint8_t spare; +} ipfw_nat64lsn_cfg; + +typedef struct _ipfw_nat64lsn_state { + struct in_addr daddr; /* Remote IPv4 address */ + uint16_t dport; /* Remote destination port */ + uint16_t aport; /* Local alias port */ + uint16_t sport; /* Source port */ + uint8_t flags; /* State flags */ + uint8_t spare[3]; + uint16_t idle; /* Last used time */ +} ipfw_nat64lsn_state; + +typedef struct _ipfw_nat64lsn_stg { + uint64_t next_idx; /* next state index */ + struct in_addr alias4; /* IPv4 alias address */ + uint8_t proto; /* protocol */ + uint8_t flags; + uint16_t spare; + struct in6_addr host6; /* Bound IPv6 host */ + uint32_t count; /* Number of states */ + uint32_t spare2; +} ipfw_nat64lsn_stg; + +#endif /* _NETINET6_IP_FW_NAT64_H_ */ + Modified: stable/11/sys/netpfil/ipfw/ip_fw2.c ============================================================================== --- stable/11/sys/netpfil/ipfw/ip_fw2.c Mon Apr 3 07:40:38 2017 (r316445) +++ stable/11/sys/netpfil/ipfw/ip_fw2.c Mon Apr 3 08:50:54 2017 (r316446) @@ -2846,6 +2846,7 @@ vnet_ipfw_init(const void *unused) #ifdef LINEAR_SKIPTO ipfw_init_skipto_cache(chain); #endif + ipfw_bpf_init(first); /* First set up some values that are compile time options */ V_ipfw_vnet_ready = 1; /* Open for business */ @@ -2864,7 +2865,6 @@ vnet_ipfw_init(const void *unused) * is checked on each packet because there are no pfil hooks. */ V_ip_fw_ctl_ptr = ipfw_ctl3; - ipfw_log_bpf(1); /* init */ error = ipfw_attach_hooks(1); return (error); } @@ -2888,8 +2888,6 @@ vnet_ipfw_uninit(const void *unused) (void)ipfw_attach_hooks(0 /* detach */); V_ip_fw_ctl_ptr = NULL; - ipfw_log_bpf(0); /* uninit */ - last = IS_DEFAULT_VNET(curvnet) ? 1 : 0; IPFW_UH_WLOCK(chain); @@ -2918,6 +2916,7 @@ vnet_ipfw_uninit(const void *unused) IPFW_LOCK_DESTROY(chain); ipfw_dyn_uninit(1); /* free the remaining parts */ ipfw_destroy_counters(); + ipfw_bpf_uninit(last); return (0); } Copied: stable/11/sys/netpfil/ipfw/ip_fw_bpf.c (from r304041, head/sys/netpfil/ipfw/ip_fw_bpf.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/11/sys/netpfil/ipfw/ip_fw_bpf.c Mon Apr 3 08:50:54 2017 (r316446, copy of r304041, head/sys/netpfil/ipfw/ip_fw_bpf.c) @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 2016 Yandex LLC + * Copyright (c) 2016 Andrey V. Elsukov + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static VNET_DEFINE(struct ifnet *, log_if); +static VNET_DEFINE(struct ifnet *, pflog_if); +static VNET_DEFINE(struct if_clone *, ipfw_cloner); +static VNET_DEFINE(struct if_clone *, ipfwlog_cloner); +#define V_ipfw_cloner VNET(ipfw_cloner) +#define V_ipfwlog_cloner VNET(ipfwlog_cloner) +#define V_log_if VNET(log_if) +#define V_pflog_if VNET(pflog_if) + +static struct rmlock log_if_lock; +#define LOGIF_LOCK_INIT(x) rm_init(&log_if_lock, "ipfw log_if lock") +#define LOGIF_LOCK_DESTROY(x) rm_destroy(&log_if_lock) +#define LOGIF_RLOCK_TRACKER struct rm_priotracker _log_tracker +#define LOGIF_RLOCK(x) rm_rlock(&log_if_lock, &_log_tracker) +#define LOGIF_RUNLOCK(x) rm_runlock(&log_if_lock, &_log_tracker) +#define LOGIF_WLOCK(x) rm_wlock(&log_if_lock) +#define LOGIF_WUNLOCK(x) rm_wunlock(&log_if_lock) + +static const char ipfwname[] = "ipfw"; +static const char ipfwlogname[] = "ipfwlog"; + +static int +ipfw_bpf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) +{ + + return (EINVAL); +} + +static int +ipfw_bpf_output(struct ifnet *ifp, struct mbuf *m, + const struct sockaddr *dst, struct route *ro) +{ + + if (m != NULL) + FREE_PKT(m); + return (0); +} + +static void +ipfw_clone_destroy(struct ifnet *ifp) +{ + + LOGIF_WLOCK(); + if (ifp->if_hdrlen == ETHER_HDR_LEN) + V_log_if = NULL; + else + V_pflog_if = NULL; + LOGIF_WUNLOCK(); + + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); +} + +static int +ipfw_clone_create(struct if_clone *ifc, int unit, caddr_t params) +{ + struct ifnet *ifp; + + ifp = if_alloc(IFT_PFLOG); + if (ifp == NULL) + return (ENOSPC); + if_initname(ifp, ipfwname, unit); + ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_mtu = 65536; + ifp->if_ioctl = ipfw_bpf_ioctl; + ifp->if_output = ipfw_bpf_output; + ifp->if_hdrlen = ETHER_HDR_LEN; + if_attach(ifp); + bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN); + LOGIF_WLOCK(); + if (V_log_if != NULL) { + LOGIF_WUNLOCK(); + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); + return (EEXIST); + } + V_log_if = ifp; + LOGIF_WUNLOCK(); + return (0); +} + +static int +ipfwlog_clone_create(struct if_clone *ifc, int unit, caddr_t params) +{ + struct ifnet *ifp; + + ifp = if_alloc(IFT_PFLOG); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***