aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2023-12-13 15:55:28 +0000
committerKristof Provost <kp@FreeBSD.org>2024-01-16 08:45:55 +0000
commitfc6e50699615c93f39d008709f87c754d9b6c7d3 (patch)
tree207e33cbe559ac5dea320dab27ca58586ef79339
parent85b71dcfc99952c0b8d78be93a0104873e8f81f7 (diff)
downloadsrc-fc6e50699615c93f39d008709f87c754d9b6c7d3.tar.gz
src-fc6e50699615c93f39d008709f87c754d9b6c7d3.zip
-rw-r--r--sbin/pfctl/parse.y16
-rw-r--r--sys/net/pflow.h44
-rw-r--r--sys/netpfil/pf/pf.c3
-rw-r--r--sys/netpfil/pf/pflow.c213
4 files changed, 260 insertions, 16 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 94b7e241cd25..9ec86f898240 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -4680,6 +4680,7 @@ natrule : nataction interface af proto fromto tag tagged rtable
redirpool pool_opts
{
struct pfctl_rule r;
+ struct node_state_opt *o;
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
@@ -4855,6 +4856,21 @@ natrule : nataction interface af proto fromto tag tagged rtable
r.rpool.mape = $10.mape;
}
+ o = keep_state_defaults;
+ while (o) {
+ switch (o->type) {
+ case PF_STATE_OPT_PFLOW:
+ if (r.rule_flag & PFRULE_PFLOW) {
+ yyerror("state pflow option: "
+ "multiple definitions");
+ YYERROR;
+ }
+ r.rule_flag |= PFRULE_PFLOW;
+ break;
+ }
+ o = o->next;
+ }
+
expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
$5.dst.port, 0, 0, 0, "");
diff --git a/sys/net/pflow.h b/sys/net/pflow.h
index 4a63f7640629..84fcf1327a17 100644
--- a/sys/net/pflow.h
+++ b/sys/net/pflow.h
@@ -68,6 +68,14 @@
#define PFIX_IE_destinationIPv6Address 28
#define PFIX_IE_flowStartMilliseconds 152
#define PFIX_IE_flowEndMilliseconds 153
+#define PFIX_IE_postNATSourceIPv4Address 225
+#define PFIX_IE_postNATDestinationIPv4Address 226
+#define PFIX_IE_postNAPTSourceTransportPort 227
+#define PFIX_IE_postNAPTDestinationTransportPort 228
+#define PFIX_IE_natEvent 230
+#define PFIX_NAT_EVENT_SESSION_CREATE 4
+#define PFIX_NAT_EVENT_SESSION_DELETE 5
+#define PFIX_IE_timeStamp 323
struct pflow_flow {
u_int32_t src_ip;
@@ -148,10 +156,28 @@ struct pflow_ipfix_tmpl_ipv6 {
#define PFLOW_IPFIX_TMPL_IPV6_ID 257
} __packed;
+struct pflow_ipfix_tmpl_nat44 {
+ struct pflow_tmpl_hdr h;
+ struct pflow_tmpl_fspec timestamp;
+ struct pflow_tmpl_fspec nat_event;
+ struct pflow_tmpl_fspec protocol;
+ struct pflow_tmpl_fspec src_ip;
+ struct pflow_tmpl_fspec src_port;
+ struct pflow_tmpl_fspec postnat_src_ip;
+ struct pflow_tmpl_fspec postnat_src_port;
+ struct pflow_tmpl_fspec dst_ip;
+ struct pflow_tmpl_fspec dst_port;
+ struct pflow_tmpl_fspec postnat_dst_ip;
+ struct pflow_tmpl_fspec postnat_dst_port;
+#define PFLOW_IPFIX_TMPL_NAT44_FIELD_COUNT 11
+#define PFLOW_IPFIX_TMPL_NAT44_ID 258
+};
+
struct pflow_ipfix_tmpl {
struct pflow_set_header set_header;
struct pflow_ipfix_tmpl_ipv4 ipv4_tmpl;
struct pflow_ipfix_tmpl_ipv6 ipv6_tmpl;
+ struct pflow_ipfix_tmpl_nat44 nat44_tmpl;
} __packed;
struct pflow_ipfix_flow4 {
@@ -186,6 +212,20 @@ struct pflow_ipfix_flow6 {
/* XXX padding needed? */
} __packed;
+struct pflow_ipfix_nat4 {
+ u_int64_t timestamp; /* timeStamp */
+ u_int8_t nat_event; /* natEvent */
+ u_int8_t protocol; /* protocolIdentifier */
+ u_int32_t src_ip; /* sourceIPv4Address */
+ u_int16_t src_port; /* sourceTransportPort */
+ u_int32_t postnat_src_ip; /* postNATSourceIPv4Address */
+ u_int16_t postnat_src_port;/* postNAPTSourceTransportPort */
+ u_int32_t dest_ip; /* destinationIPv4Address */
+ u_int16_t dest_port; /* destinationTransportPort */
+ u_int32_t postnat_dest_ip;/* postNATDestinationIPv4Address */
+ u_int16_t postnat_dest_port;/* postNAPTDestinationTransportPort */
+} __packed;
+
#ifdef _KERNEL
struct pflow_softc {
@@ -199,13 +239,16 @@ struct pflow_softc {
unsigned int sc_count;
unsigned int sc_count4;
unsigned int sc_count6;
+ unsigned int sc_count_nat4;
unsigned int sc_maxcount;
unsigned int sc_maxcount4;
unsigned int sc_maxcount6;
+ unsigned int sc_maxcount_nat4;
u_int64_t sc_gcounter;
u_int32_t sc_sequence;
struct callout sc_tmo;
struct callout sc_tmo6;
+ struct callout sc_tmo_nat4;
struct callout sc_tmo_tmpl;
struct intr_event *sc_swi_ie;
void *sc_swi_cookie;
@@ -219,6 +262,7 @@ struct pflow_softc {
u_int32_t sc_observation_dom;
struct mbuf *sc_mbuf; /* current cumulative mbuf */
struct mbuf *sc_mbuf6; /* current cumulative mbuf */
+ struct mbuf *sc_mbuf_nat4;
CK_LIST_ENTRY(pflow_softc) sc_next;
struct epoch_context sc_epoch_ctx;
};
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 89f6e000f6cf..9bd9828a99d9 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -4875,7 +4875,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
s->state_flags |= PFSTATE_SLOPPY;
if (pd->flags & PFDESC_TCP_NORM) /* Set by old-style scrub rules */
s->state_flags |= PFSTATE_SCRUB_TCP;
- if (r->rule_flag & PFRULE_PFLOW)
+ if ((r->rule_flag & PFRULE_PFLOW) ||
+ (nr != NULL && nr->rule_flag & PFRULE_PFLOW))
s->state_flags |= PFSTATE_PFLOW;
s->act.log = pd->act.log & PF_LOG_ALL;
diff --git a/sys/netpfil/pf/pflow.c b/sys/netpfil/pf/pflow.c
index 398851bf17d0..ce5e8ec6547c 100644
--- a/sys/netpfil/pf/pflow.c
+++ b/sys/netpfil/pf/pflow.c
@@ -70,6 +70,12 @@
#define DPRINTF(x)
#endif
+enum pflow_family_t {
+ PFLOW_INET,
+ PFLOW_INET6,
+ PFLOW_NAT4,
+};
+
static void pflow_output_process(void *);
static int pflow_create(int);
static int pflow_destroy(int, bool);
@@ -80,12 +86,13 @@ static int pflowvalidsockaddr(const struct sockaddr *, int);
static struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t);
static void pflow_flush(struct pflow_softc *);
static int pflow_sendout_v5(struct pflow_softc *);
-static int pflow_sendout_ipfix(struct pflow_softc *, sa_family_t);
+static int pflow_sendout_ipfix(struct pflow_softc *, enum pflow_family_t);
static int pflow_sendout_ipfix_tmpl(struct pflow_softc *);
static int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
static void pflow_timeout(void *);
static void pflow_timeout6(void *);
static void pflow_timeout_tmpl(void *);
+static void pflow_timeout_nat4(void *);
static void copy_flow_data(struct pflow_flow *, struct pflow_flow *,
const struct pf_kstate *, struct pf_state_key *, int, int);
static void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *,
@@ -106,6 +113,9 @@ static int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow,
struct pflow_softc *sc);
static int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow,
struct pflow_softc *sc);
+static int copy_nat_ipfix_4_to_m(struct pflow_ipfix_nat4 *,
+ const struct pf_kstate *, struct pflow_softc *,
+ uint8_t, uint64_t);
static const char pflowname[] = "pflow";
@@ -303,6 +313,53 @@ pflow_create(int unit)
htons(PFIX_IE_protocolIdentifier);
pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.len = htons(1);
+ /* NAT44 create template */
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.h.tmpl_id =
+ htons(PFLOW_IPFIX_TMPL_NAT44_ID);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.h.field_count =
+ htons(PFLOW_IPFIX_TMPL_NAT44_FIELD_COUNT);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.timestamp.field_id =
+ htons(PFIX_IE_timeStamp);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.timestamp.len =
+ htons(8);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.nat_event.field_id =
+ htons(PFIX_IE_natEvent);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.nat_event.len =
+ htons(1);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.protocol.field_id =
+ htons(PFIX_IE_protocolIdentifier);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.protocol.len = htons(1);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.src_ip.field_id =
+ htons(PFIX_IE_sourceIPv4Address);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.src_ip.len =
+ htons(4);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.src_port.field_id =
+ htons(PFIX_IE_sourceTransportPort);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.src_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_src_ip.field_id =
+ htons(PFIX_IE_postNATSourceIPv4Address);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_src_ip.len =
+ htons(4);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_src_port.field_id =
+ htons(PFIX_IE_postNAPTSourceTransportPort);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_src_port.len =
+ htons(2);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.dst_ip.field_id =
+ htons(PFIX_IE_destinationIPv4Address);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.dst_ip.len =
+ htons(4);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.dst_port.field_id =
+ htons(PFIX_IE_destinationTransportPort);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.dst_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_dst_ip.field_id =
+ htons(PFIX_IE_postNATDestinationIPv4Address);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_dst_ip.len =
+ htons(4);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_dst_port.field_id =
+ htons(PFIX_IE_postNAPTDestinationTransportPort);
+ pflowif->sc_tmpl_ipfix.nat44_tmpl.postnat_dst_port.len =
+ htons(2);
+
pflowif->sc_id = unit;
pflowif->sc_vnet = curvnet;
@@ -311,6 +368,7 @@ pflow_create(int unit)
callout_init_mtx(&pflowif->sc_tmo, &pflowif->sc_lock, 0);
callout_init_mtx(&pflowif->sc_tmo6, &pflowif->sc_lock, 0);
+ callout_init_mtx(&pflowif->sc_tmo_nat4, &pflowif->sc_lock, 0);
callout_init_mtx(&pflowif->sc_tmo_tmpl, &pflowif->sc_lock, 0);
error = swi_add(&pflowif->sc_swi_ie, pflowname, pflow_output_process,
@@ -374,10 +432,12 @@ pflow_destroy(int unit, bool drain)
callout_drain(&sc->sc_tmo);
callout_drain(&sc->sc_tmo6);
+ callout_drain(&sc->sc_tmo_nat4);
callout_drain(&sc->sc_tmo_tmpl);
m_freem(sc->sc_mbuf);
m_freem(sc->sc_mbuf6);
+ m_freem(sc->sc_mbuf_nat4);
PFLOW_LOCK(sc);
mbufq_drain(&sc->sc_outputqueue);
@@ -425,18 +485,26 @@ pflowvalidsockaddr(const struct sockaddr *sa, int ignore_port)
int
pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz)
{
+ size_t min;
sc->sc_maxcount4 = (mtu - hdrsz -
sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow4);
sc->sc_maxcount6 = (mtu - hdrsz -
sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow6);
+ sc->sc_maxcount_nat4 = (mtu - hdrsz -
+ sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_nat4);
if (sc->sc_maxcount4 > PFLOW_MAXFLOWS)
sc->sc_maxcount4 = PFLOW_MAXFLOWS;
if (sc->sc_maxcount6 > PFLOW_MAXFLOWS)
sc->sc_maxcount6 = PFLOW_MAXFLOWS;
- return (hdrsz + sizeof(struct udpiphdr) +
- MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4),
- sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6)));
+ if (sc->sc_maxcount_nat4 > PFLOW_MAXFLOWS)
+ sc->sc_maxcount_nat4 = PFLOW_MAXFLOWS;
+
+ min = MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4),
+ sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6));
+ min = MIN(min, sc->sc_maxcount_nat4 * sizeof(struct pflow_ipfix_nat4));
+
+ return (hdrsz + sizeof(struct udpiphdr) + min);
}
static void
@@ -629,6 +697,28 @@ copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
}
static void
+copy_nat_ipfix_4_data(struct pflow_ipfix_nat4 *nat1,
+ struct pflow_ipfix_nat4 *nat2, const struct pf_kstate *st,
+ struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
+{
+ nat1->src_ip = nat2->dest_ip = st->key[PF_SK_STACK]->addr[src].v4.s_addr;
+ nat1->src_port = nat2->dest_port = st->key[PF_SK_STACK]->port[src];
+ nat1->dest_ip = nat2->src_ip = st->key[PF_SK_STACK]->addr[dst].v4.s_addr;
+ nat1->dest_port = nat2->src_port = st->key[PF_SK_STACK]->port[dst];
+ nat1->postnat_src_ip = nat2->postnat_dest_ip = st->key[PF_SK_WIRE]->addr[src].v4.s_addr;
+ nat1->postnat_src_port = nat2->postnat_dest_port = st->key[PF_SK_WIRE]->port[src];
+ nat1->postnat_dest_ip = nat2->postnat_src_ip = st->key[PF_SK_WIRE]->addr[dst].v4.s_addr;
+ nat1->postnat_dest_port = nat2->postnat_src_port = st->key[PF_SK_WIRE]->port[dst];
+ nat1->protocol = nat2->protocol = sk->proto;
+
+ /*
+ * Because we have to generate a create and delete event we'll fill out the
+ * timestamp and nat_event fields when we transmit. As opposed to doing this
+ * work a second time.
+ */
+}
+
+static void
export_pflow(const struct pf_kstate *st)
{
struct pflow_softc *sc = NULL;
@@ -755,7 +845,7 @@ copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc)
sc->sc_count4++;
if (sc->sc_count4 >= sc->sc_maxcount4)
- ret = pflow_sendout_ipfix(sc, AF_INET);
+ ret = pflow_sendout_ipfix(sc, PFLOW_INET);
return(ret);
}
@@ -785,11 +875,46 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
sc->sc_count6++;
if (sc->sc_count6 >= sc->sc_maxcount6)
- ret = pflow_sendout_ipfix(sc, AF_INET6);
+ ret = pflow_sendout_ipfix(sc, PFLOW_INET6);
return(ret);
}
+int
+copy_nat_ipfix_4_to_m(struct pflow_ipfix_nat4 *nat, const struct pf_kstate *st,
+ struct pflow_softc *sc, uint8_t event, uint64_t timestamp)
+{
+ int ret = 0;
+
+ PFLOW_ASSERT(sc);
+
+ if (sc->sc_mbuf_nat4 == NULL) {
+ if ((sc->sc_mbuf_nat4 =
+ pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_NAT44_ID)) == NULL) {
+ return (ENOBUFS);
+ }
+ sc->sc_count_nat4 = 0;
+ callout_reset(&sc->sc_tmo, PFLOW_TIMEOUT * hz,
+ pflow_timeout_nat4, sc);
+ }
+
+ nat->nat_event = event;
+ nat->timestamp = htobe64(pf_get_time() - (pf_get_uptime() - timestamp));
+ m_copyback(sc->sc_mbuf_nat4, PFLOW_SET_HDRLEN +
+ (sc->sc_count_nat4 * sizeof(struct pflow_ipfix_nat4)),
+ sizeof(struct pflow_ipfix_nat4), (caddr_t)nat);
+ sc->sc_count_nat4++;
+
+ if (V_pflowstats.pflow_flows == sc->sc_gcounter)
+ V_pflowstats.pflow_flows++;
+
+ sc->sc_gcounter++;
+ if (sc->sc_count_nat4 >= sc->sc_maxcount_nat4)
+ ret = pflow_sendout_ipfix(sc, PFLOW_NAT4);
+
+ return (ret);
+}
+
static int
pflow_pack_flow(const struct pf_kstate *st, struct pf_state_key *sk,
struct pflow_softc *sc)
@@ -815,17 +940,30 @@ pflow_pack_flow(const struct pf_kstate *st, struct pf_state_key *sk,
return (ret);
}
+static bool
+pflow_is_natd(const struct pf_kstate *st)
+{
+ /* If ports or addresses are different we've been NAT-ed. */
+ return (memcmp(st->key[PF_SK_WIRE], st->key[PF_SK_STACK],
+ sizeof(struct pf_addr) * 2 + sizeof(uint16_t) * 2) != 0);
+}
+
static int
pflow_pack_flow_ipfix(const struct pf_kstate *st, struct pf_state_key *sk,
struct pflow_softc *sc)
{
struct pflow_ipfix_flow4 flow4_1, flow4_2;
+ struct pflow_ipfix_nat4 nat4_1, nat4_2;
struct pflow_ipfix_flow6 flow6_1, flow6_2;
int ret = 0;
+ bool nat = false;
+
if (sk->af == AF_INET) {
bzero(&flow4_1, sizeof(flow4_1));
bzero(&flow4_2, sizeof(flow4_2));
+ nat = pflow_is_natd(st);
+
if (st->direction == PF_OUT)
copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
1, 0);
@@ -833,11 +971,30 @@ pflow_pack_flow_ipfix(const struct pf_kstate *st, struct pf_state_key *sk,
copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
0, 1);
- if (st->bytes[0] != 0) /* first flow from state */
+ if (nat)
+ copy_nat_ipfix_4_data(&nat4_1, &nat4_2, st, sk, sc, 1, 0);
+
+ if (st->bytes[0] != 0) /* first flow from state */ {
ret = copy_flow_ipfix_4_to_m(&flow4_1, sc);
- if (st->bytes[1] != 0) /* second flow from state */
+ if (ret == 0 && nat) {
+ ret = copy_nat_ipfix_4_to_m(&nat4_1, st, sc,
+ PFIX_NAT_EVENT_SESSION_CREATE, st->creation);
+ ret |= copy_nat_ipfix_4_to_m(&nat4_1, st, sc,
+ PFIX_NAT_EVENT_SESSION_DELETE, st->expire);
+ }
+ }
+
+ if (st->bytes[1] != 0) /* second flow from state */ {
ret = copy_flow_ipfix_4_to_m(&flow4_2, sc);
+
+ if (ret == 0 && nat) {
+ ret = copy_nat_ipfix_4_to_m(&nat4_2, st, sc,
+ PFIX_NAT_EVENT_SESSION_CREATE, st->creation);
+ ret |= copy_nat_ipfix_4_to_m(&nat4_2, st, sc,
+ PFIX_NAT_EVENT_SESSION_DELETE, st->expire);
+ }
+ }
} else if (sk->af == AF_INET6) {
bzero(&flow6_1, sizeof(flow6_1));
bzero(&flow6_2, sizeof(flow6_2));
@@ -871,7 +1028,7 @@ pflow_timeout(void *v)
pflow_sendout_v5(sc);
break;
case PFLOW_PROTO_10:
- pflow_sendout_ipfix(sc, AF_INET);
+ pflow_sendout_ipfix(sc, PFLOW_INET);
break;
default: /* NOTREACHED */
panic("Unsupported version %d", sc->sc_version);
@@ -892,7 +1049,7 @@ pflow_timeout6(void *v)
return;
CURVNET_SET(sc->sc_vnet);
- pflow_sendout_ipfix(sc, AF_INET6);
+ pflow_sendout_ipfix(sc, PFLOW_INET6);
CURVNET_RESTORE();
}
@@ -912,6 +1069,21 @@ pflow_timeout_tmpl(void *v)
}
static void
+pflow_timeout_nat4(void *v)
+{
+ struct pflow_softc *sc = v;
+
+ PFLOW_ASSERT(sc);
+
+ if (sc->sc_version != PFLOW_PROTO_10)
+ return;
+
+ CURVNET_SET(sc->sc_vnet);
+ pflow_sendout_ipfix(sc, PFLOW_NAT4);
+ CURVNET_RESTORE();
+}
+
+static void
pflow_flush(struct pflow_softc *sc)
{
PFLOW_ASSERT(sc);
@@ -921,8 +1093,9 @@ pflow_flush(struct pflow_softc *sc)
pflow_sendout_v5(sc);
break;
case PFLOW_PROTO_10:
- pflow_sendout_ipfix(sc, AF_INET);
- pflow_sendout_ipfix(sc, AF_INET6);
+ pflow_sendout_ipfix(sc, PFLOW_INET);
+ pflow_sendout_ipfix(sc, PFLOW_INET6);
+ pflow_sendout_ipfix(sc, PFLOW_NAT4);
break;
default: /* NOTREACHED */
break;
@@ -960,7 +1133,7 @@ pflow_sendout_v5(struct pflow_softc *sc)
}
static int
-pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
+pflow_sendout_ipfix(struct pflow_softc *sc, enum pflow_family_t af)
{
struct mbuf *m;
struct pflow_v10_header *h10;
@@ -971,7 +1144,7 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
PFLOW_ASSERT(sc);
switch (af) {
- case AF_INET:
+ case PFLOW_INET:
m = sc->sc_mbuf;
callout_stop(&sc->sc_tmo);
if (m == NULL)
@@ -981,7 +1154,7 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
set_length = sizeof(struct pflow_set_header)
+ sc->sc_count4 * sizeof(struct pflow_ipfix_flow4);
break;
- case AF_INET6:
+ case PFLOW_INET6:
m = sc->sc_mbuf6;
callout_stop(&sc->sc_tmo6);
if (m == NULL)
@@ -991,6 +1164,16 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
set_length = sizeof(struct pflow_set_header)
+ sc->sc_count6 * sizeof(struct pflow_ipfix_flow6);
break;
+ case PFLOW_NAT4:
+ m = sc->sc_mbuf_nat4;
+ callout_stop(&sc->sc_tmo_nat4);
+ if (m == NULL)
+ return (0);
+ sc->sc_mbuf_nat4 = NULL;
+ count = sc->sc_count_nat4;
+ set_length = sizeof(struct pflow_set_header)
+ + sc->sc_count_nat4 * sizeof(struct pflow_ipfix_nat4);
+ break;
default:
panic("Unsupported AF %d", af);
}