summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2013-08-13 08:44:06 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2013-08-13 08:44:06 +0000
commit0a059bc1c663c12221108b3e18bb10e9a25ff466 (patch)
tree2e178be5f7c2c0bca378542ea43267dc0ee34d14 /sys/net
parenta1bd9b00f4b2fdf76515f8d2e73164f76a30f2cb (diff)
Split pflow version 9 and version 10 to be able to send 64 bit
time values for version 10. While there mark places which will blow up in 2038. OK benno@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_pflow.c841
-rw-r--r--sys/net/if_pflow.h123
2 files changed, 677 insertions, 287 deletions
diff --git a/sys/net/if_pflow.c b/sys/net/if_pflow.c
index 4b60bf18e12..ba51cb1849e 100644
--- a/sys/net/if_pflow.c
+++ b/sys/net/if_pflow.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflow.c,v 1.33 2013/08/10 18:33:21 florian Exp $ */
+/* $OpenBSD: if_pflow.c,v 1.34 2013/08/13 08:44:05 florian Exp $ */
/*
* Copyright (c) 2011 Florian Obser <florian@narrans.de>
@@ -82,7 +82,9 @@ void pflowstart(struct ifnet *);
struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t);
void pflow_flush(struct pflow_softc *);
int pflow_sendout_v5(struct pflow_softc *);
+int pflow_sendout_v9(struct pflow_softc *, sa_family_t);
int pflow_sendout_ipfix(struct pflow_softc *, sa_family_t);
+int pflow_sendout_v9_tmpl(struct pflow_softc *);
int pflow_sendout_ipfix_tmpl(struct pflow_softc *);
int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
void pflow_timeout(void *);
@@ -90,22 +92,36 @@ void pflow_timeout6(void *);
void pflow_timeout_tmpl(void *);
void copy_flow_data(struct pflow_flow *, struct pflow_flow *,
struct pf_state *, struct pf_state_key *, int, int);
-void copy_flow4_data(struct pflow_flow4 *, struct pflow_flow4 *,
+void copy_flow_v9_4_data(struct pflow_v9_flow4 *, struct pflow_v9_flow4 *,
struct pf_state *, struct pf_state_key *, struct pflow_softc *, int,
int);
-void copy_flow6_data(struct pflow_flow6 *, struct pflow_flow6 *,
+void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *,
+ struct pflow_ipfix_flow4 *, struct pf_state *, struct pf_state_key *,
+ struct pflow_softc *, int, int);
+void copy_flow_v9_6_data(struct pflow_v9_flow6 *, struct pflow_v9_flow6 *,
struct pf_state *, struct pf_state_key *, struct pflow_softc *, int,
int);
+void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *,
+ struct pflow_ipfix_flow6 *, struct pf_state *, struct pf_state_key *,
+ struct pflow_softc *, int, int);
int pflow_pack_flow(struct pf_state *, struct pf_state_key *,
struct pflow_softc *);
+int pflow_pack_flow_v9(struct pf_state *, struct pf_state_key *,
+ struct pflow_softc *);
int pflow_pack_flow_ipfix(struct pf_state *, struct pf_state_key *,
struct pflow_softc *);
int pflow_get_dynport(void);
int export_pflow_if(struct pf_state*, struct pf_state_key *,
struct pflow_softc *);
int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc);
-int copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc);
-int copy_flow6_to_m(struct pflow_flow6 *flow, struct pflow_softc *sc);
+int copy_flow_v9_4_to_m(struct pflow_v9_flow4 *flow, struct pflow_softc
+ *sc);
+int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow,
+ struct pflow_softc *sc);
+int copy_flow_v9_6_to_m(struct pflow_v9_flow6 *flow, struct pflow_softc
+ *sc);
+int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow,
+ struct pflow_softc *sc);
struct if_clone pflow_cloner =
IF_CLONE_INITIALIZER("pflow", pflow_clone_create,
@@ -140,102 +156,185 @@ pflow_clone_create(struct if_clone *ifc, int unit)
pflowif->sc_sender_ip.s_addr = INADDR_ANY;
pflowif->sc_sender_port = pflow_get_dynport();
pflowif->sc_version = PFLOW_PROTO_DEFAULT;
- bzero(&pflowif->sc_tmpl,sizeof(pflowif->sc_tmpl));
- pflowif->sc_tmpl.set_header.set_id =
- htons(pflowif->sc_version == PFLOW_PROTO_9?
- PFLOW_V9_TMPL_SET_ID:PFLOW_V10_TMPL_SET_ID);
- pflowif->sc_tmpl.set_header.set_length =
- htons(sizeof(struct pflow_tmpl));
-
- /* v9/v10 IPv4 template */
- pflowif->sc_tmpl.ipv4_tmpl.h.tmpl_id = htons(PFLOW_TMPL_IPV4_ID);
- pflowif->sc_tmpl.ipv4_tmpl.h.field_count
- = htons(PFLOW_TMPL_IPV4_FIELD_COUNT);
- pflowif->sc_tmpl.ipv4_tmpl.src_ip.field_id =
+
+ /* v9 template init */
+ bzero(&pflowif->sc_tmpl_v9,sizeof(pflowif->sc_tmpl_v9));
+ pflowif->sc_tmpl_v9.set_header.set_id = htons(PFLOW_V9_TMPL_SET_ID);
+ pflowif->sc_tmpl_v9.set_header.set_length =
+ htons(sizeof(struct pflow_v9_tmpl));
+
+ /* v9 IPv4 template */
+ pflowif->sc_tmpl_v9.ipv4_tmpl.h.tmpl_id = htons(PFLOW_V9_TMPL_IPV4_ID);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.h.field_count
+ = htons(PFLOW_V9_TMPL_IPV4_FIELD_COUNT);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.src_ip.field_id =
htons(PFIX_IE_sourceIPv4Address);
- pflowif->sc_tmpl.ipv4_tmpl.src_ip.len = htons(4);
- pflowif->sc_tmpl.ipv4_tmpl.dest_ip.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.src_ip.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.dest_ip.field_id =
htons(PFIX_IE_destinationIPv4Address);
- pflowif->sc_tmpl.ipv4_tmpl.dest_ip.len = htons(4);
- pflowif->sc_tmpl.ipv4_tmpl.if_index_in.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.dest_ip.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.if_index_in.field_id =
htons(PFIX_IE_ingressInterface);
- pflowif->sc_tmpl.ipv4_tmpl.if_index_in.len = htons(4);
- pflowif->sc_tmpl.ipv4_tmpl.if_index_out.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.if_index_in.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.if_index_out.field_id =
htons(PFIX_IE_egressInterface);
- pflowif->sc_tmpl.ipv4_tmpl.if_index_out.len = htons(4);
- pflowif->sc_tmpl.ipv4_tmpl.packets.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.if_index_out.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.packets.field_id =
htons(PFIX_IE_packetDeltaCount);
- pflowif->sc_tmpl.ipv4_tmpl.packets.len = htons(8);
- pflowif->sc_tmpl.ipv4_tmpl.octets.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.packets.len = htons(8);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.octets.field_id =
htons(PFIX_IE_octetDeltaCount);
- pflowif->sc_tmpl.ipv4_tmpl.octets.len = htons(8);
- /* keep in sync with SIOCSETPFLOW */
- pflowif->sc_tmpl.ipv4_tmpl.start.field_id =
- htons(pflowif->sc_version == PFLOW_PROTO_9?
- PFIX_IE_flowStartSysUpTime:PFIX_IE_flowStartSeconds);
- pflowif->sc_tmpl.ipv4_tmpl.start.len = htons(4);
- /* keep in sync with SIOCSETPFLOW */
- pflowif->sc_tmpl.ipv4_tmpl.finish.field_id =
- htons(pflowif->sc_version == PFLOW_PROTO_9?
- PFIX_IE_flowEndSysUpTime:PFIX_IE_flowEndSeconds);
- pflowif->sc_tmpl.ipv4_tmpl.finish.len = htons(4);
- pflowif->sc_tmpl.ipv4_tmpl.src_port.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.octets.len = htons(8);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.start.field_id =
+ htons(PFIX_IE_flowStartSysUpTime);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.start.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.finish.field_id =
+ htons(PFIX_IE_flowEndSysUpTime);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.finish.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.src_port.field_id =
htons(PFIX_IE_sourceTransportPort);
- pflowif->sc_tmpl.ipv4_tmpl.src_port.len = htons(2);
- pflowif->sc_tmpl.ipv4_tmpl.dest_port.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.src_port.len = htons(2);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.dest_port.field_id =
htons(PFIX_IE_destinationTransportPort);
- pflowif->sc_tmpl.ipv4_tmpl.dest_port.len = htons(2);
- pflowif->sc_tmpl.ipv4_tmpl.tos.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.dest_port.len = htons(2);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.tos.field_id =
htons(PFIX_IE_ipClassOfService);
- pflowif->sc_tmpl.ipv4_tmpl.tos.len = htons(1);
- pflowif->sc_tmpl.ipv4_tmpl.protocol.field_id =
+ pflowif->sc_tmpl_v9.ipv4_tmpl.tos.len = htons(1);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.protocol.field_id =
htons(PFIX_IE_protocolIdentifier);
- pflowif->sc_tmpl.ipv4_tmpl.protocol.len = htons(1);
+ pflowif->sc_tmpl_v9.ipv4_tmpl.protocol.len = htons(1);
- /* v9/v10 IPv6 template */
- pflowif->sc_tmpl.ipv6_tmpl.h.tmpl_id = htons(PFLOW_TMPL_IPV6_ID);
- pflowif->sc_tmpl.ipv6_tmpl.h.field_count =
- htons(PFLOW_TMPL_IPV6_FIELD_COUNT);
- pflowif->sc_tmpl.ipv6_tmpl.src_ip.field_id =
+ /* v9 IPv6 template */
+ pflowif->sc_tmpl_v9.ipv6_tmpl.h.tmpl_id = htons(PFLOW_V9_TMPL_IPV6_ID);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.h.field_count =
+ htons(PFLOW_V9_TMPL_IPV6_FIELD_COUNT);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.src_ip.field_id =
htons(PFIX_IE_sourceIPv6Address);
- pflowif->sc_tmpl.ipv6_tmpl.src_ip.len = htons(16);
- pflowif->sc_tmpl.ipv6_tmpl.dest_ip.field_id =
+ pflowif->sc_tmpl_v9.ipv6_tmpl.src_ip.len = htons(16);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.dest_ip.field_id =
htons(PFIX_IE_destinationIPv6Address);
- pflowif->sc_tmpl.ipv6_tmpl.dest_ip.len = htons(16);
- pflowif->sc_tmpl.ipv6_tmpl.if_index_in.field_id =
+ pflowif->sc_tmpl_v9.ipv6_tmpl.dest_ip.len = htons(16);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.if_index_in.field_id =
+ htons(PFIX_IE_ingressInterface);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.if_index_in.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.if_index_out.field_id =
+ htons(PFIX_IE_egressInterface);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.if_index_out.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.packets.field_id =
+ htons(PFIX_IE_packetDeltaCount);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.packets.len = htons(8);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.octets.field_id =
+ htons(PFIX_IE_octetDeltaCount);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.octets.len = htons(8);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.start.field_id =
+ htons(PFIX_IE_flowStartSysUpTime);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.start.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.finish.field_id =
+ htons(PFIX_IE_flowEndSysUpTime);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.finish.len = htons(4);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.src_port.field_id =
+ htons(PFIX_IE_sourceTransportPort);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.src_port.len = htons(2);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.dest_port.field_id =
+ htons(PFIX_IE_destinationTransportPort);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.dest_port.len = htons(2);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.tos.field_id =
+ htons(PFIX_IE_ipClassOfService);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.tos.len = htons(1);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.protocol.field_id =
+ htons(PFIX_IE_protocolIdentifier);
+ pflowif->sc_tmpl_v9.ipv6_tmpl.protocol.len = htons(1);
+
+ /* ipfix template init */
+ bzero(&pflowif->sc_tmpl_ipfix,sizeof(pflowif->sc_tmpl_ipfix));
+ pflowif->sc_tmpl_ipfix.set_header.set_id =
+ htons(PFLOW_IPFIX_TMPL_SET_ID);
+ pflowif->sc_tmpl_ipfix.set_header.set_length =
+ htons(sizeof(struct pflow_ipfix_tmpl));
+
+ /* ipfix IPv4 template */
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.tmpl_id =
+ htons(PFLOW_IPFIX_TMPL_IPV4_ID);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.field_count
+ = htons(PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.field_id =
+ htons(PFIX_IE_sourceIPv4Address);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.field_id =
+ htons(PFIX_IE_destinationIPv4Address);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.field_id =
htons(PFIX_IE_ingressInterface);
- pflowif->sc_tmpl.ipv6_tmpl.if_index_in.len = htons(4);
- pflowif->sc_tmpl.ipv6_tmpl.if_index_out.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.field_id =
htons(PFIX_IE_egressInterface);
- pflowif->sc_tmpl.ipv6_tmpl.if_index_out.len = htons(4);
- pflowif->sc_tmpl.ipv6_tmpl.packets.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.field_id =
htons(PFIX_IE_packetDeltaCount);
- pflowif->sc_tmpl.ipv6_tmpl.packets.len = htons(8);
- pflowif->sc_tmpl.ipv6_tmpl.octets.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.field_id =
htons(PFIX_IE_octetDeltaCount);
- pflowif->sc_tmpl.ipv6_tmpl.octets.len = htons(8);
- /* keep in sync with SIOCSETPFLOW */
- pflowif->sc_tmpl.ipv6_tmpl.start.field_id =
- htons(pflowif->sc_version == PFLOW_PROTO_9?
- PFIX_IE_flowStartSysUpTime:PFIX_IE_flowStartSeconds);
- pflowif->sc_tmpl.ipv6_tmpl.start.len = htons(4);
- /* keep in sync with SIOCSETPFLOW */
- pflowif->sc_tmpl.ipv6_tmpl.finish.field_id =
- htons(pflowif->sc_version == PFLOW_PROTO_9?
- PFIX_IE_flowEndSysUpTime:PFIX_IE_flowEndSeconds);
- pflowif->sc_tmpl.ipv6_tmpl.finish.len = htons(4);
- pflowif->sc_tmpl.ipv6_tmpl.src_port.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.field_id =
+ htons(PFIX_IE_flowStartMilliseconds);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.field_id =
+ htons(PFIX_IE_flowEndMilliseconds);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.field_id =
htons(PFIX_IE_sourceTransportPort);
- pflowif->sc_tmpl.ipv6_tmpl.src_port.len = htons(2);
- pflowif->sc_tmpl.ipv6_tmpl.dest_port.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.field_id =
htons(PFIX_IE_destinationTransportPort);
- pflowif->sc_tmpl.ipv6_tmpl.dest_port.len = htons(2);
- pflowif->sc_tmpl.ipv6_tmpl.tos.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.field_id =
htons(PFIX_IE_ipClassOfService);
- pflowif->sc_tmpl.ipv6_tmpl.tos.len = htons(1);
- pflowif->sc_tmpl.ipv6_tmpl.protocol.field_id =
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.len = htons(1);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.field_id =
htons(PFIX_IE_protocolIdentifier);
- pflowif->sc_tmpl.ipv6_tmpl.protocol.len = htons(1);
+ pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.len = htons(1);
+
+ /* ipfix IPv6 template */
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.tmpl_id =
+ htons(PFLOW_IPFIX_TMPL_IPV6_ID);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.field_count =
+ htons(PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.field_id =
+ htons(PFIX_IE_sourceIPv6Address);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.len = htons(16);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.field_id =
+ htons(PFIX_IE_destinationIPv6Address);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.len = htons(16);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.field_id =
+ htons(PFIX_IE_ingressInterface);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.field_id =
+ htons(PFIX_IE_egressInterface);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.len = htons(4);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.field_id =
+ htons(PFIX_IE_packetDeltaCount);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.field_id =
+ htons(PFIX_IE_octetDeltaCount);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.field_id =
+ htons(PFIX_IE_flowStartMilliseconds);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.field_id =
+ htons(PFIX_IE_flowEndMilliseconds);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.len = htons(8);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.field_id =
+ htons(PFIX_IE_sourceTransportPort);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.field_id =
+ htons(PFIX_IE_destinationTransportPort);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.len = htons(2);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.field_id =
+ htons(PFIX_IE_ipClassOfService);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.len = htons(1);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.field_id =
+ htons(PFIX_IE_protocolIdentifier);
+ pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.len = htons(1);
ifp = &pflowif->sc_if;
snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit);
@@ -334,8 +433,11 @@ pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_flags |= IFF_RUNNING;
sc->sc_gcounter=pflowstats.pflow_flows;
/* send templates on startup */
- if (sc->sc_version == PFLOW_PROTO_9
- || sc->sc_version == PFLOW_PROTO_10) {
+ if (sc->sc_version == PFLOW_PROTO_9) {
+ s = splnet();
+ pflow_sendout_v9_tmpl(sc);
+ splx(s);
+ } else if (sc->sc_version == PFLOW_PROTO_10) {
s = splnet();
pflow_sendout_ipfix_tmpl(sc);
splx(s);
@@ -401,32 +503,10 @@ pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
pflow_setmtu(sc, ETHERMTU);
pflow_init_timeouts(sc);
- switch (sc->sc_version) {
- case PFLOW_PROTO_9:
- sc->sc_tmpl.set_header.set_id =
- htons(PFLOW_V9_TMPL_SET_ID);
- sc->sc_tmpl.ipv4_tmpl.start.field_id =
- sc->sc_tmpl.ipv6_tmpl.start.field_id =
- htons(PFIX_IE_flowStartSysUpTime);
- sc->sc_tmpl.ipv4_tmpl.finish.field_id =
- sc->sc_tmpl.ipv6_tmpl.finish.field_id =
- htons(PFIX_IE_flowEndSysUpTime);
+ if (sc->sc_version == PFLOW_PROTO_9)
+ pflow_sendout_v9_tmpl(sc);
+ else if (sc->sc_version == PFLOW_PROTO_10)
pflow_sendout_ipfix_tmpl(sc);
- break;
- case PFLOW_PROTO_10:
- sc->sc_tmpl.set_header.set_id =
- htons(PFLOW_V10_TMPL_SET_ID);
- sc->sc_tmpl.ipv4_tmpl.start.field_id =
- sc->sc_tmpl.ipv6_tmpl.start.field_id =
- htons(PFIX_IE_flowStartSeconds);
- sc->sc_tmpl.ipv4_tmpl.finish.field_id =
- sc->sc_tmpl.ipv6_tmpl.finish.field_id =
- htons(PFIX_IE_flowEndSeconds);
- pflow_sendout_ipfix_tmpl(sc);
- break;
- default:
- break;
- }
splx(s);
@@ -477,18 +557,29 @@ pflow_init_timeouts(struct pflow_softc *sc)
int
pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz)
{
- sc->sc_maxcount4 = (mtu - hdrsz -
- sizeof(struct udpiphdr)) / sizeof(struct pflow_flow4);
+ if (sc->sc_version == PFLOW_PROTO_9) {
+ sc->sc_maxcount4 = (mtu - hdrsz -
+ sizeof(struct udpiphdr)) / sizeof(struct pflow_v9_flow4);
+ sc->sc_maxcount6 = (mtu - hdrsz -
+ sizeof(struct udpiphdr)) / sizeof(struct pflow_v9_flow6);
+ } else {
+ 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);
+ }
if (sc->sc_maxcount4 > PFLOW_MAXFLOWS)
sc->sc_maxcount4 = PFLOW_MAXFLOWS;
- sc->sc_maxcount6 = (mtu - hdrsz -
- sizeof(struct udpiphdr)) / sizeof(struct pflow_flow6);
if (sc->sc_maxcount6 > PFLOW_MAXFLOWS)
sc->sc_maxcount6 = PFLOW_MAXFLOWS;
-
- return (hdrsz + sizeof(struct udpiphdr) +
- MIN(sc->sc_maxcount4 * sizeof(struct pflow_flow4),
- sc->sc_maxcount6 * sizeof(struct pflow_flow6)));
+ if (sc->sc_version == PFLOW_PROTO_9)
+ return (hdrsz + sizeof(struct udpiphdr) +
+ MIN(sc->sc_maxcount4 * sizeof(struct pflow_v9_flow4),
+ sc->sc_maxcount6 * sizeof(struct pflow_v9_flow6)));
+ else
+ return (hdrsz + sizeof(struct udpiphdr) +
+ MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4),
+ sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6)));
}
void
@@ -611,7 +702,7 @@ copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
}
void
-copy_flow4_data(struct pflow_flow4 *flow1, struct pflow_flow4 *flow2,
+copy_flow_v9_4_data(struct pflow_v9_flow4 *flow1, struct pflow_v9_flow4 *flow2,
struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc,
int src, int dst)
{
@@ -630,36 +721,24 @@ copy_flow4_data(struct pflow_flow4 *flow1, struct pflow_flow4 *flow2,
flow1->flow_octets = htobe64(st->bytes[0]);
flow2->flow_octets = htobe64(st->bytes[1]);
- switch (sc->sc_version) {
- case PFLOW_PROTO_9:
- /*
- * Pretend the flow was created or expired when the machine came
- * up when creation is in the future of the last time a package
- * was seen or was created / expired before this machine came up
- * due to pfsync.
- */
- flow1->flow_start = flow2->flow_start = st->creation < 0 ||
- st->creation > st->expire ? htonl(0) : htonl(st->creation *
- 1000);
- flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
- htonl(0) : htonl(st->expire * 1000);
- break;
- case PFLOW_PROTO_10:
- flow1->flow_start = flow2->flow_start = htonl(time_second -
- (time_uptime - st->creation));
- flow1->flow_finish = flow2->flow_finish = htonl(time_second -
- (time_uptime - st->expire));
- break;
- default: /* NOTREACHED */
- break;
- }
+ /*
+ * Pretend the flow was created or expired when the machine came
+ * up when creation is in the future of the last time a package
+ * was seen or was created / expired before this machine came up
+ * due to pfsync.
+ */
+ flow1->flow_start = flow2->flow_start = st->creation < 0 ||
+ st->creation > st->expire ? htonl(0) : htonl(st->creation *
+ 1000);
+ flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
+ htonl(0) : htonl(st->expire * 1000);
flow1->protocol = flow2->protocol = sk->proto;
flow1->tos = flow2->tos = st->rule.ptr->tos;
}
void
-copy_flow6_data(struct pflow_flow6 *flow1, struct pflow_flow6 *flow2,
+copy_flow_v9_6_data(struct pflow_v9_flow6 *flow1, struct pflow_v9_flow6 *flow2,
struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc,
int src, int dst)
{
@@ -680,29 +759,93 @@ copy_flow6_data(struct pflow_flow6 *flow1, struct pflow_flow6 *flow2,
flow1->flow_octets = htobe64(st->bytes[0]);
flow2->flow_octets = htobe64(st->bytes[1]);
- switch (sc->sc_version) {
- case PFLOW_PROTO_9:
- /*
- * Pretend the flow was created or expired when the machine came
- * up when creation is in the future of the last time a package
- * was seen or was created / expired before this machine came up
- * due to pfsync.
- */
- flow1->flow_start = flow2->flow_start = st->creation < 0 ||
- st->creation > st->expire ? htonl(0) : htonl(st->creation *
- 1000);
- flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
- htonl(0) : htonl(st->expire * 1000);
- break;
- case PFLOW_PROTO_10:
- flow1->flow_start = flow2->flow_start = htonl(time_second -
- (time_uptime - st->creation));
- flow1->flow_finish = flow2->flow_finish = htonl(time_second -
- (time_uptime - st->expire));
- break;
- default: /* NOTREACHED */
- break;
- }
+ /*
+ * Pretend the flow was created or expired when the machine came
+ * up when creation is in the future of the last time a package
+ * was seen or was created / expired before this machine came up
+ * due to pfsync.
+ */
+ flow1->flow_start = flow2->flow_start = st->creation < 0 ||
+ st->creation > st->expire ? htonl(0) : htonl(st->creation *
+ 1000);
+ flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
+ htonl(0) : htonl(st->expire * 1000);
+
+ flow1->protocol = flow2->protocol = sk->proto;
+ flow1->tos = flow2->tos = st->rule.ptr->tos;
+}
+
+void
+copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
+ struct pflow_ipfix_flow4 *flow2, struct pf_state *st,
+ struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
+{
+ flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
+ flow1->src_port = flow2->dest_port = sk->port[src];
+ flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
+ flow1->dest_port = flow2->src_port = sk->port[dst];
+
+ flow1->if_index_in = htonl(st->if_index_in);
+ flow1->if_index_out = htonl(st->if_index_out);
+ flow2->if_index_in = htonl(st->if_index_out);
+ flow2->if_index_out = htonl(st->if_index_in);
+
+ flow1->flow_packets = htobe64(st->packets[0]);
+ flow2->flow_packets = htobe64(st->packets[1]);
+ flow1->flow_octets = htobe64(st->bytes[0]);
+ flow2->flow_octets = htobe64(st->bytes[1]);
+
+ /*
+ * Pretend the flow was created when the machine came up when creation
+ * is in the future of the last time a package was seen due to pfsync.
+ */
+ if (st->creation > st->expire)
+ flow1->flow_start = flow2->flow_start = htobe64((time_second -
+ time_uptime)*1000);
+ else
+ flow1->flow_start = flow2->flow_start = htobe64((time_second -
+ (time_uptime - st->creation))*1000);
+ flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
+ (time_uptime - st->expire))*1000);
+
+ flow1->protocol = flow2->protocol = sk->proto;
+ flow1->tos = flow2->tos = st->rule.ptr->tos;
+}
+
+void
+copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
+ struct pflow_ipfix_flow6 *flow2, struct pf_state *st,
+ struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
+{
+ bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip));
+ bcopy(&sk->addr[src].v6, &flow2->dest_ip, sizeof(flow2->dest_ip));
+ flow1->src_port = flow2->dest_port = sk->port[src];
+ bcopy(&sk->addr[dst].v6, &flow1->dest_ip, sizeof(flow1->dest_ip));
+ bcopy(&sk->addr[dst].v6, &flow2->src_ip, sizeof(flow2->src_ip));
+ flow1->dest_port = flow2->src_port = sk->port[dst];
+
+ flow1->if_index_in = htonl(st->if_index_in);
+ flow1->if_index_out = htonl(st->if_index_out);
+ flow2->if_index_in = htonl(st->if_index_out);
+ flow2->if_index_out = htonl(st->if_index_in);
+
+ flow1->flow_packets = htobe64(st->packets[0]);
+ flow2->flow_packets = htobe64(st->packets[1]);
+ flow1->flow_octets = htobe64(st->bytes[0]);
+ flow2->flow_octets = htobe64(st->bytes[1]);
+
+ /*
+ * Pretend the flow was created when the machine came up when creation
+ * is in the future of the last time a package was seen due to pfsync.
+ */
+ if (st->creation > st->expire)
+ flow1->flow_start = flow2->flow_start = htobe64((time_second -
+ time_uptime)*1000);
+ else
+ flow1->flow_start = flow2->flow_start = htobe64((time_second -
+ (time_uptime - st->creation))*1000);
+ flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
+ (time_uptime - st->expire))*1000);
flow1->protocol = flow2->protocol = sk->proto;
flow1->tos = flow2->tos = st->rule.ptr->tos;
@@ -748,7 +891,9 @@ export_pflow_if(struct pf_state *st, struct pf_state_key *sk,
if (!(ifp->if_flags & IFF_RUNNING))
return (0);
- if (sc->sc_version == PFLOW_PROTO_9 || sc->sc_version == PFLOW_PROTO_10)
+ if (sc->sc_version == PFLOW_PROTO_9)
+ return (pflow_pack_flow_v9(st, sk, sc));
+ if (sc->sc_version == PFLOW_PROTO_10)
return (pflow_pack_flow_ipfix(st, sk, sc));
/* PFLOW_PROTO_5 */
@@ -816,14 +961,14 @@ copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc)
}
int
-copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc)
+copy_flow_v9_4_to_m(struct pflow_v9_flow4 *flow, struct pflow_softc *sc)
{
int s, ret = 0;
s = splnet();
if (sc->sc_mbuf == NULL) {
if ((sc->sc_mbuf =
- pflow_get_mbuf(sc, PFLOW_TMPL_IPV4_ID)) == NULL) {
+ pflow_get_mbuf(sc, PFLOW_V9_TMPL_IPV4_ID)) == NULL) {
splx(s);
return (ENOBUFS);
}
@@ -831,8 +976,69 @@ copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc)
timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
}
m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN +
- (sc->sc_count4 * sizeof(struct pflow_flow4)),
- sizeof(struct pflow_flow4), flow, M_NOWAIT);
+ (sc->sc_count4 * sizeof(struct pflow_v9_flow4)),
+ sizeof(struct pflow_v9_flow4), flow, M_NOWAIT);
+
+ if (pflowstats.pflow_flows == sc->sc_gcounter)
+ pflowstats.pflow_flows++;
+ sc->sc_gcounter++;
+ sc->sc_count4++;
+
+ if (sc->sc_count4 >= sc->sc_maxcount4)
+ ret = pflow_sendout_v9(sc, AF_INET);
+ splx(s);
+ return(ret);
+}
+
+int
+copy_flow_v9_6_to_m(struct pflow_v9_flow6 *flow, struct pflow_softc *sc)
+{
+ int s, ret = 0;
+
+ s = splnet();
+ if (sc->sc_mbuf6 == NULL) {
+ if ((sc->sc_mbuf6 =
+ pflow_get_mbuf(sc, PFLOW_V9_TMPL_IPV6_ID)) == NULL) {
+ splx(s);
+ return (ENOBUFS);
+ }
+ sc->sc_count6 = 0;
+ timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT);
+ }
+ m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN +
+ (sc->sc_count6 * sizeof(struct pflow_v9_flow6)),
+ sizeof(struct pflow_v9_flow6), flow, M_NOWAIT);
+
+ if (pflowstats.pflow_flows == sc->sc_gcounter)
+ pflowstats.pflow_flows++;
+ sc->sc_gcounter++;
+ sc->sc_count6++;
+
+ if (sc->sc_count6 >= sc->sc_maxcount6)
+ ret = pflow_sendout_v9(sc, AF_INET6);
+
+ splx(s);
+ return(ret);
+}
+
+int
+copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc)
+{
+ int s, ret = 0;
+
+ s = splnet();
+ if (sc->sc_mbuf == NULL) {
+ if ((sc->sc_mbuf =
+ pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID)) == NULL) {
+ splx(s);
+ return (ENOBUFS);
+ }
+ sc->sc_count4 = 0;
+ timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
+ }
+ m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN +
+ (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)),
+ sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT);
if (pflowstats.pflow_flows == sc->sc_gcounter)
pflowstats.pflow_flows++;
@@ -846,14 +1052,14 @@ copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc)
}
int
-copy_flow6_to_m(struct pflow_flow6 *flow, struct pflow_softc *sc)
+copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
{
int s, ret = 0;
s = splnet();
if (sc->sc_mbuf6 == NULL) {
if ((sc->sc_mbuf6 =
- pflow_get_mbuf(sc, PFLOW_TMPL_IPV6_ID)) == NULL) {
+ pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID)) == NULL) {
splx(s);
return (ENOBUFS);
}
@@ -861,8 +1067,8 @@ copy_flow6_to_m(struct pflow_flow6 *flow, struct pflow_softc *sc)
timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT);
}
m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN +
- (sc->sc_count6 * sizeof(struct pflow_flow6)),
- sizeof(struct pflow_flow6), flow, M_NOWAIT);
+ (sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)),
+ sizeof(struct pflow_ipfix_flow6), flow, M_NOWAIT);
if (pflowstats.pflow_flows == sc->sc_gcounter)
pflowstats.pflow_flows++;
@@ -902,40 +1108,87 @@ pflow_pack_flow(struct pf_state *st, struct pf_state_key *sk,
}
int
-pflow_pack_flow_ipfix(struct pf_state *st, struct pf_state_key *sk,
+pflow_pack_flow_v9(struct pf_state *st, struct pf_state_key *sk,
struct pflow_softc *sc)
{
- struct pflow_flow4 flow4_1, flow4_2;
- struct pflow_flow6 flow6_1, flow6_2;
+ struct pflow_v9_flow4 flow4_1, flow4_2;
+ struct pflow_v9_flow6 flow6_1, flow6_2;
int ret = 0;
if (sk->af == AF_INET) {
bzero(&flow4_1, sizeof(flow4_1));
bzero(&flow4_2, sizeof(flow4_2));
if (st->direction == PF_OUT)
- copy_flow4_data(&flow4_1, &flow4_2, st, sk, sc, 1, 0);
+ copy_flow_v9_4_data(&flow4_1, &flow4_2, st, sk, sc, 1,
+ 0);
else
- copy_flow4_data(&flow4_1, &flow4_2, st, sk, sc, 0, 1);
+ copy_flow_v9_4_data(&flow4_1, &flow4_2, st, sk, sc, 0,
+ 1);
if (st->bytes[0] != 0) /* first flow from state */
- ret = copy_flow4_to_m(&flow4_1, sc);
+ ret = copy_flow_v9_4_to_m(&flow4_1, sc);
if (st->bytes[1] != 0) /* second flow from state */
- ret = copy_flow4_to_m(&flow4_2, sc);
+ ret = copy_flow_v9_4_to_m(&flow4_2, sc);
} else if (sk->af == AF_INET6) {
bzero(&flow6_1, sizeof(flow6_1));
bzero(&flow6_2, sizeof(flow6_2));
if (st->direction == PF_OUT)
- copy_flow6_data(&flow6_1, &flow6_2, st, sk, sc, 1, 0);
+ copy_flow_v9_6_data(&flow6_1, &flow6_2, st, sk, sc, 1,
+ 0);
else
- copy_flow6_data(&flow6_1, &flow6_2, st, sk, sc, 0, 1);
+ copy_flow_v9_6_data(&flow6_1, &flow6_2, st, sk, sc, 0,
+ 1);
if (st->bytes[0] != 0) /* first flow from state */
- ret = copy_flow6_to_m(&flow6_1, sc);
+ ret = copy_flow_v9_6_to_m(&flow6_1, sc);
if (st->bytes[1] != 0) /* second flow from state */
- ret = copy_flow6_to_m(&flow6_2, sc);
+ ret = copy_flow_v9_6_to_m(&flow6_2, sc);
+ }
+ return (ret);
+}
+
+int
+pflow_pack_flow_ipfix(struct pf_state *st, struct pf_state_key *sk,
+ struct pflow_softc *sc)
+{
+ struct pflow_ipfix_flow4 flow4_1, flow4_2;
+ struct pflow_ipfix_flow6 flow6_1, flow6_2;
+ int ret = 0;
+ if (sk->af == AF_INET) {
+ bzero(&flow4_1, sizeof(flow4_1));
+ bzero(&flow4_2, sizeof(flow4_2));
+
+ if (st->direction == PF_OUT)
+ copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
+ 1, 0);
+ else
+ copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
+ 0, 1);
+
+ 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 */
+ ret = copy_flow_ipfix_4_to_m(&flow4_2, sc);
+ } else if (sk->af == AF_INET6) {
+ bzero(&flow6_1, sizeof(flow6_1));
+ bzero(&flow6_2, sizeof(flow6_2));
+
+ if (st->direction == PF_OUT)
+ copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
+ 1, 0);
+ else
+ copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
+ 0, 1);
+
+ if (st->bytes[0] != 0) /* first flow from state */
+ ret = copy_flow_ipfix_6_to_m(&flow6_1, sc);
+
+ if (st->bytes[1] != 0) /* second flow from state */
+ ret = copy_flow_ipfix_6_to_m(&flow6_2, sc);
}
return (ret);
}
@@ -952,9 +1205,11 @@ pflow_timeout(void *v)
pflow_sendout_v5(sc);
break;
case PFLOW_PROTO_9:
- /* ... fall through ... */
+ pflow_sendout_v9(sc, AF_INET);
+ break;
case PFLOW_PROTO_10:
pflow_sendout_ipfix(sc, AF_INET);
+ break;
default: /* NOTREACHED */
break;
}
@@ -968,7 +1223,16 @@ pflow_timeout6(void *v)
int s;
s = splnet();
- pflow_sendout_ipfix(sc, AF_INET6);
+ switch (sc->sc_version) {
+ case PFLOW_PROTO_9:
+ pflow_sendout_v9(sc, AF_INET6);
+ break;
+ case PFLOW_PROTO_10:
+ pflow_sendout_ipfix(sc, AF_INET6);
+ break;
+ default: /* NOTREACHED */
+ break;
+ }
splx(s);
}
@@ -979,7 +1243,10 @@ pflow_timeout_tmpl(void *v)
int s;
s = splnet();
- pflow_sendout_ipfix_tmpl(sc);
+ if (sc->sc_version == PFLOW_PROTO_9)
+ pflow_sendout_v9_tmpl(sc);
+ else if (sc->sc_version == PFLOW_PROTO_10)
+ pflow_sendout_ipfix_tmpl(sc);
splx(s);
}
@@ -992,6 +1259,9 @@ pflow_flush(struct pflow_softc *sc)
pflow_sendout_v5(sc);
break;
case PFLOW_PROTO_9:
+ pflow_sendout_v9(sc, AF_INET);
+ pflow_sendout_v9(sc, AF_INET6);
+ break;
case PFLOW_PROTO_10:
pflow_sendout_ipfix(sc, AF_INET);
pflow_sendout_ipfix(sc, AF_INET6);
@@ -1030,7 +1300,7 @@ pflow_sendout_v5(struct pflow_softc *sc)
h->uptime_ms = htonl(time_uptime * 1000);
getnanotime(&tv);
- h->time_sec = htonl(tv.tv_sec);
+ h->time_sec = htonl(tv.tv_sec); /* XXX 2038 */
h->time_nanosec = htonl(tv.tv_nsec);
return (pflow_sendout_mbuf(sc, m));
@@ -1038,11 +1308,10 @@ pflow_sendout_v5(struct pflow_softc *sc)
/* This must be called in splnet() */
int
-pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
+pflow_sendout_v9(struct pflow_softc *sc, sa_family_t af)
{
struct mbuf *m;
struct pflow_v9_header *h9;
- struct pflow_v10_header *h10;
struct pflow_set_header *set_hdr;
struct ifnet *ifp = &sc->sc_if;
int set_length;
@@ -1054,6 +1323,8 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
if (m == NULL)
return (0);
sc->sc_mbuf = NULL;
+ set_length = sizeof(struct pflow_set_header)
+ + sc->sc_count4 * sizeof(struct pflow_v9_flow4);
break;
case AF_INET6:
m = sc->sc_mbuf6;
@@ -1061,6 +1332,8 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
if (m == NULL)
return (0);
sc->sc_mbuf6 = NULL;
+ set_length = sizeof(struct pflow_set_header)
+ + sc->sc_count6 * sizeof(struct pflow_v9_flow6);
break;
default: /* NOTREACHED */
break;
@@ -1073,64 +1346,127 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
pflowstats.pflow_packets++;
set_hdr = mtod(m, struct pflow_set_header *);
+ set_hdr->set_length = htons(set_length);
+
+ /* populate pflow_header */
+ M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
+ if (m == NULL) {
+ pflowstats.pflow_onomem++;
+ return (ENOBUFS);
+ }
+ h9 = mtod(m, struct pflow_v9_header *);
+ h9->version = htons(PFLOW_PROTO_9);
+ h9->count = htons(1);
+ h9->uptime_ms = htonl(time_uptime * 1000);
+ h9->time_sec = htonl(time_second); /* XXX 2038 */
+ h9->flow_sequence = htonl(sc->sc_gcounter);
+ h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
+ return (pflow_sendout_mbuf(sc, m));
+}
+
+/* This must be called in splnet() */
+int
+pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
+{
+ struct mbuf *m;
+ struct pflow_v10_header *h10;
+ struct pflow_set_header *set_hdr;
+ struct ifnet *ifp = &sc->sc_if;
+ int set_length;
+
switch (af) {
case AF_INET:
+ m = sc->sc_mbuf;
+ timeout_del(&sc->sc_tmo);
+ if (m == NULL)
+ return (0);
+ sc->sc_mbuf = NULL;
set_length = sizeof(struct pflow_set_header)
- + sc->sc_count4 * sizeof(struct pflow_flow4);
+ + sc->sc_count4 * sizeof(struct pflow_ipfix_flow4);
break;
case AF_INET6:
+ m = sc->sc_mbuf6;
+ timeout_del(&sc->sc_tmo6);
+ if (m == NULL)
+ return (0);
+ sc->sc_mbuf6 = NULL;
set_length = sizeof(struct pflow_set_header)
- + sc->sc_count6 * sizeof(struct pflow_flow6);
+ + sc->sc_count6 * sizeof(struct pflow_ipfix_flow6);
break;
default: /* NOTREACHED */
break;
}
+
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ m_freem(m);
+ return (0);
+ }
+
+ pflowstats.pflow_packets++;
+ set_hdr = mtod(m, struct pflow_set_header *);
set_hdr->set_length = htons(set_length);
- switch (sc->sc_version) {
- case PFLOW_PROTO_9:
- /* populate pflow_header */
- M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
- if (m == NULL) {
- pflowstats.pflow_onomem++;
- return (ENOBUFS);
- }
- h9 = mtod(m, struct pflow_v9_header *);
- h9->version = htons(PFLOW_PROTO_9);
- h9->count = htons(1);
- h9->uptime_ms = htonl(time_uptime * 1000);
- h9->time_sec = htonl(time_second);
- /* XXX correct mod 2^32 semantics? */
- h9->flow_sequence = htonl(sc->sc_gcounter);
- h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
- break;
- case PFLOW_PROTO_10:
- /* populate pflow_header */
- M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
- if (m == NULL) {
- pflowstats.pflow_onomem++;
- return (ENOBUFS);
- }
- h10 = mtod(m, struct pflow_v10_header *);
- h10->version = htons(PFLOW_PROTO_10);
- h10->length = htons(PFLOW_V10_HDRLEN + set_length);
- h10->time_sec = htonl(time_second);
- /* XXX correct mod 2^32 semantics? */
- h10->flow_sequence = htonl(sc->sc_gcounter);
- h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
- break;
- default: /* NOTREACHED */
- break;
+ /* populate pflow_header */
+ M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
+ if (m == NULL) {
+ pflowstats.pflow_onomem++;
+ return (ENOBUFS);
}
+ h10 = mtod(m, struct pflow_v10_header *);
+ h10->version = htons(PFLOW_PROTO_10);
+ h10->length = htons(PFLOW_IPFIX_HDRLEN + set_length);
+ h10->time_sec = htonl(time_second); /* XXX 2038 */
+ h10->flow_sequence = htonl(sc->sc_gcounter);
+ h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
return (pflow_sendout_mbuf(sc, m));
}
/* This must be called in splnet() */
int
-pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
+pflow_sendout_v9_tmpl(struct pflow_softc *sc)
{
struct mbuf *m;
struct pflow_v9_header *h9;
+ struct ifnet *ifp = &sc->sc_if;
+
+ timeout_del(&sc->sc_tmo_tmpl);
+
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ return (0);
+ }
+ m = pflow_get_mbuf(NULL, 0);
+ if (m == NULL)
+ return (0);
+ if (m_copyback(m, 0, sizeof(struct pflow_v9_tmpl),
+ &sc->sc_tmpl_v9, M_NOWAIT)) {
+ m_freem(m);
+ return (0);
+ }
+ pflowstats.pflow_packets++;
+
+ /* populate pflow_header */
+ M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
+ if (m == NULL) {
+ pflowstats.pflow_onomem++;
+ return (ENOBUFS);
+ }
+ h9 = mtod(m, struct pflow_v9_header *);
+ h9->version = htons(PFLOW_PROTO_9);
+ h9->count = htons(1);
+ h9->uptime_ms = htonl(time_uptime * 1000);
+ h9->time_sec = htonl(time_second); /* XXX 2038 */
+ h9->flow_sequence = htonl(sc->sc_gcounter);
+ h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
+
+ timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
+ return (pflow_sendout_mbuf(sc, m));
+}
+
+/* This must be called in splnet() */
+int
+pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
+{
+ struct mbuf *m;
struct pflow_v10_header *h10;
struct ifnet *ifp = &sc->sc_if;
@@ -1142,48 +1478,27 @@ pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
m = pflow_get_mbuf(NULL, 0);
if (m == NULL)
return (0);
- if (m_copyback(m, 0, sizeof(struct pflow_tmpl),
- &sc->sc_tmpl, M_NOWAIT)) {
+ if (m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl),
+ &sc->sc_tmpl_ipfix, M_NOWAIT)) {
m_freem(m);
return (0);
}
pflowstats.pflow_packets++;
- switch (sc->sc_version) {
- case PFLOW_PROTO_9:
- /* populate pflow_header */
- M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
- if (m == NULL) {
- pflowstats.pflow_onomem++;
- return (ENOBUFS);
- }
- h9 = mtod(m, struct pflow_v9_header *);
- h9->version = htons(PFLOW_PROTO_9);
- h9->count = htons(1);
- h9->uptime_ms = htonl(time_uptime * 1000);
- h9->time_sec = htonl(time_second);
- /* XXX correct mod 2^32 semantics? */
- h9->flow_sequence = htonl(sc->sc_gcounter);
- h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
- break;
- case PFLOW_PROTO_10:
- /* populate pflow_header */
- M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
- if (m == NULL) {
- pflowstats.pflow_onomem++;
- return (ENOBUFS);
- }
- h10 = mtod(m, struct pflow_v10_header *);
- h10->version = htons(PFLOW_PROTO_10);
- h10->length = htons(PFLOW_V10_HDRLEN
- + sizeof(struct pflow_tmpl));
- h10->time_sec = htonl(time_second);
- /* XXX correct mod 2^32 semantics? */
- h10->flow_sequence = htonl(sc->sc_gcounter);
- h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
- break;
- default: /* NOTREACHED */
- break;
+
+ /* populate pflow_header */
+ M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
+ if (m == NULL) {
+ pflowstats.pflow_onomem++;
+ return (ENOBUFS);
}
+ h10 = mtod(m, struct pflow_v10_header *);
+ h10->version = htons(PFLOW_PROTO_10);
+ h10->length = htons(PFLOW_IPFIX_HDRLEN + sizeof(struct
+ pflow_ipfix_tmpl));
+ h10->time_sec = htonl(time_second); /* XXX 2038 */
+ h10->flow_sequence = htonl(sc->sc_gcounter);
+ h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
+
timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
return (pflow_sendout_mbuf(sc, m));
}
diff --git a/sys/net/if_pflow.h b/sys/net/if_pflow.h
index 250ff7e47ef..1676ec8d016 100644
--- a/sys/net/if_pflow.h
+++ b/sys/net/if_pflow.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflow.h,v 1.8 2013/05/03 15:33:47 florian Exp $ */
+/* $OpenBSD: if_pflow.h,v 1.9 2013/08/13 08:44:05 florian Exp $ */
/*
* Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
@@ -30,7 +30,7 @@
#define PFLOW_TMPL_TIMEOUT 30 /* rfc 5101 10.3.6 (p.40) recommends 600 */
#define PFLOW_V9_TMPL_SET_ID 0
-#define PFLOW_V10_TMPL_SET_ID 2
+#define PFLOW_IPFIX_TMPL_SET_ID 2
/* RFC 5102 Information Element Identifiers */
@@ -48,8 +48,8 @@
#define PFIX_IE_flowStartSysUpTime 22
#define PFIX_IE_sourceIPv6Address 27
#define PFIX_IE_destinationIPv6Address 28
-#define PFIX_IE_flowStartSeconds 150
-#define PFIX_IE_flowEndSeconds 151
+#define PFIX_IE_flowStartMilliseconds 152
+#define PFIX_IE_flowEndMilliseconds 153
struct pflow_flow {
u_int32_t src_ip;
@@ -93,8 +93,8 @@ struct pflow_tmpl_fspec {
u_int16_t len;
} __packed;
-/* update pflow_clone_create() when changing pflow_tmpl_ipv4 */
-struct pflow_tmpl_ipv4 {
+/* update pflow_clone_create() when changing pflow_v9_tmpl_ipv4 */
+struct pflow_v9_tmpl_ipv4 {
struct pflow_tmpl_hdr h;
struct pflow_tmpl_fspec src_ip;
struct pflow_tmpl_fspec dest_ip;
@@ -108,12 +108,12 @@ struct pflow_tmpl_ipv4 {
struct pflow_tmpl_fspec dest_port;
struct pflow_tmpl_fspec tos;
struct pflow_tmpl_fspec protocol;
-#define PFLOW_TMPL_IPV4_FIELD_COUNT 12
-#define PFLOW_TMPL_IPV4_ID 256
+#define PFLOW_V9_TMPL_IPV4_FIELD_COUNT 12
+#define PFLOW_V9_TMPL_IPV4_ID 256
} __packed;
-/* update pflow_clone_create() when changing pflow_tmpl_v6 */
-struct pflow_tmpl_ipv6 {
+/* update pflow_clone_create() when changing pflow_v9_tmpl_v6 */
+struct pflow_v9_tmpl_ipv6 {
struct pflow_tmpl_hdr h;
struct pflow_tmpl_fspec src_ip;
struct pflow_tmpl_fspec dest_ip;
@@ -127,17 +127,62 @@ struct pflow_tmpl_ipv6 {
struct pflow_tmpl_fspec dest_port;
struct pflow_tmpl_fspec tos;
struct pflow_tmpl_fspec protocol;
-#define PFLOW_TMPL_IPV6_FIELD_COUNT 12
-#define PFLOW_TMPL_IPV6_ID 257
+#define PFLOW_V9_TMPL_IPV6_FIELD_COUNT 12
+#define PFLOW_V9_TMPL_IPV6_ID 257
} __packed;
-struct pflow_tmpl {
+struct pflow_v9_tmpl {
struct pflow_set_header set_header;
- struct pflow_tmpl_ipv4 ipv4_tmpl;
- struct pflow_tmpl_ipv6 ipv6_tmpl;
+ struct pflow_v9_tmpl_ipv4 ipv4_tmpl;
+ struct pflow_v9_tmpl_ipv6 ipv6_tmpl;
} __packed;
-struct pflow_flow4 {
+
+/* update pflow_clone_create() when changing pflow_ipfix_tmpl_ipv4 */
+struct pflow_ipfix_tmpl_ipv4 {
+ struct pflow_tmpl_hdr h;
+ struct pflow_tmpl_fspec src_ip;
+ struct pflow_tmpl_fspec dest_ip;
+ struct pflow_tmpl_fspec if_index_in;
+ struct pflow_tmpl_fspec if_index_out;
+ struct pflow_tmpl_fspec packets;
+ struct pflow_tmpl_fspec octets;
+ struct pflow_tmpl_fspec start;
+ struct pflow_tmpl_fspec finish;
+ struct pflow_tmpl_fspec src_port;
+ struct pflow_tmpl_fspec dest_port;
+ struct pflow_tmpl_fspec tos;
+ struct pflow_tmpl_fspec protocol;
+#define PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT 12
+#define PFLOW_IPFIX_TMPL_IPV4_ID 256
+} __packed;
+
+/* update pflow_clone_create() when changing pflow_ipfix_tmpl_v6 */
+struct pflow_ipfix_tmpl_ipv6 {
+ struct pflow_tmpl_hdr h;
+ struct pflow_tmpl_fspec src_ip;
+ struct pflow_tmpl_fspec dest_ip;
+ struct pflow_tmpl_fspec if_index_in;
+ struct pflow_tmpl_fspec if_index_out;
+ struct pflow_tmpl_fspec packets;
+ struct pflow_tmpl_fspec octets;
+ struct pflow_tmpl_fspec start;
+ struct pflow_tmpl_fspec finish;
+ struct pflow_tmpl_fspec src_port;
+ struct pflow_tmpl_fspec dest_port;
+ struct pflow_tmpl_fspec tos;
+ struct pflow_tmpl_fspec protocol;
+#define PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT 12
+#define PFLOW_IPFIX_TMPL_IPV6_ID 257
+} __packed;
+
+struct pflow_ipfix_tmpl {
+ struct pflow_set_header set_header;
+ struct pflow_ipfix_tmpl_ipv4 ipv4_tmpl;
+ struct pflow_ipfix_tmpl_ipv6 ipv6_tmpl;
+} __packed;
+
+struct pflow_v9_flow4 {
u_int32_t src_ip; /* sourceIPv4Address*/
u_int32_t dest_ip; /* destinationIPv4Address */
u_int32_t if_index_in; /* ingressInterface */
@@ -153,18 +198,47 @@ struct pflow_flow4 {
/* XXX padding needed? */
} __packed;
-struct pflow_flow6 {
+struct pflow_v9_flow6 {
+ struct in6_addr src_ip; /* sourceIPv6Address */
+ struct in6_addr dest_ip; /* destinationIPv6Address */
+ u_int32_t if_index_in; /* ingressInterface */
+ u_int32_t if_index_out; /* egressInterface */
+ u_int64_t flow_packets; /* packetDeltaCount */
+ u_int64_t flow_octets; /* octetDeltaCount */
+ u_int32_t flow_start; /* flowStartSysUpTime */
+ u_int32_t flow_finish; /* flowEndSysUpTime */
+ u_int16_t src_port; /* sourceTransportPort */
+ u_int16_t dest_port; /* destinationTransportPort */
+ u_int8_t tos; /* ipClassOfService */
+ u_int8_t protocol; /* protocolIdentifier */
+ /* XXX padding needed? */
+} __packed;
+
+struct pflow_ipfix_flow4 {
+ u_int32_t src_ip; /* sourceIPv4Address*/
+ u_int32_t dest_ip; /* destinationIPv4Address */
+ u_int32_t if_index_in; /* ingressInterface */
+ u_int32_t if_index_out; /* egressInterface */
+ u_int64_t flow_packets; /* packetDeltaCount */
+ u_int64_t flow_octets; /* octetDeltaCount */
+ int64_t flow_start; /* flowStartMilliseconds */
+ int64_t flow_finish; /* flowEndMilliseconds */
+ u_int16_t src_port; /* sourceTransportPort */
+ u_int16_t dest_port; /* destinationTransportPort */
+ u_int8_t tos; /* ipClassOfService */
+ u_int8_t protocol; /* protocolIdentifier */
+ /* XXX padding needed? */
+} __packed;
+
+struct pflow_ipfix_flow6 {
struct in6_addr src_ip; /* sourceIPv6Address */
struct in6_addr dest_ip; /* destinationIPv6Address */
u_int32_t if_index_in; /* ingressInterface */
u_int32_t if_index_out; /* egressInterface */
u_int64_t flow_packets; /* packetDeltaCount */
u_int64_t flow_octets; /* octetDeltaCount */
- u_int32_t flow_start; /*
- * flowStartSysUpTime /
- * flowStartSeconds
- */
- u_int32_t flow_finish; /* flowEndSysUpTime / flowEndSeconds */
+ int64_t flow_start; /* flowStartMilliseconds */
+ int64_t flow_finish; /* flowEndMilliseconds */
u_int16_t src_port; /* sourceTransportPort */
u_int16_t dest_port; /* destinationTransportPort */
u_int8_t tos; /* ipClassOfService */
@@ -196,7 +270,8 @@ struct pflow_softc {
struct in_addr sc_receiver_ip;
u_int16_t sc_receiver_port;
u_char sc_send_templates;
- struct pflow_tmpl sc_tmpl;
+ struct pflow_v9_tmpl sc_tmpl_v9;
+ struct pflow_ipfix_tmpl sc_tmpl_ipfix;
u_int8_t sc_version;
struct mbuf *sc_mbuf; /* current cumulative mbuf */
struct mbuf *sc_mbuf6; /* current cumulative mbuf */
@@ -230,7 +305,7 @@ struct pflow_v10_header {
u_int32_t observation_dom;
} __packed;
-#define PFLOW_V10_HDRLEN sizeof(struct pflow_v10_header)
+#define PFLOW_IPFIX_HDRLEN sizeof(struct pflow_v10_header)
struct pflow_v9_header {
u_int16_t version;