xref: /openbsd-src/sys/net/if_pflow.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: if_pflow.c,v 1.86 2018/01/09 15:24:24 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 Florian Obser <florian@narrans.de>
5  * Copyright (c) 2011 Sebastian Benoit <benoit-lists@fb12.de>
6  * Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
7  * Copyright (c) 2008 Joerg Goltermann <jg@osn.de>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
18  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/param.h>
23 #include <sys/malloc.h>
24 #include <sys/systm.h>
25 #include <sys/mbuf.h>
26 #include <sys/socket.h>
27 #include <sys/timeout.h>
28 #include <sys/ioctl.h>
29 #include <sys/kernel.h>
30 #include <sys/socket.h>
31 #include <sys/socketvar.h>
32 #include <sys/sysctl.h>
33 
34 #include <net/if.h>
35 #include <net/if_types.h>
36 #include <net/bpf.h>
37 #include <net/route.h>
38 #include <netinet/in.h>
39 #include <netinet/if_ether.h>
40 #include <netinet/tcp.h>
41 
42 #include <netinet/ip.h>
43 #include <netinet/ip_var.h>
44 #include <netinet/udp.h>
45 #include <netinet/udp_var.h>
46 #include <netinet/in_pcb.h>
47 
48 #include <net/pfvar.h>
49 #include <net/if_pflow.h>
50 
51 #include "bpfilter.h"
52 #include "pflow.h"
53 
54 #define PFLOW_MINMTU	\
55     (sizeof(struct pflow_header) + sizeof(struct pflow_flow))
56 
57 #ifdef PFLOWDEBUG
58 #define DPRINTF(x)	do { printf x ; } while (0)
59 #else
60 #define DPRINTF(x)
61 #endif
62 
63 SLIST_HEAD(, pflow_softc) pflowif_list;
64 struct pflowstats	 pflowstats;
65 
66 void	pflowattach(int);
67 int	pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
68 	struct rtentry *rt);
69 void	pflow_output_process(void *);
70 int	pflow_clone_create(struct if_clone *, int);
71 int	pflow_clone_destroy(struct ifnet *);
72 int	pflow_set(struct pflow_softc *, struct pflowreq *);
73 void	pflow_init_timeouts(struct pflow_softc *);
74 int	pflow_calc_mtu(struct pflow_softc *, int, int);
75 void	pflow_setmtu(struct pflow_softc *, int);
76 int	pflowvalidsockaddr(const struct sockaddr *, int);
77 int	pflowioctl(struct ifnet *, u_long, caddr_t);
78 
79 struct mbuf	*pflow_get_mbuf(struct pflow_softc *, u_int16_t);
80 void	pflow_flush(struct pflow_softc *);
81 int	pflow_sendout_v5(struct pflow_softc *);
82 int	pflow_sendout_ipfix(struct pflow_softc *, sa_family_t);
83 int	pflow_sendout_ipfix_tmpl(struct pflow_softc *);
84 int	pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
85 void	pflow_timeout(void *);
86 void	pflow_timeout6(void *);
87 void	pflow_timeout_tmpl(void *);
88 void	copy_flow_data(struct pflow_flow *, struct pflow_flow *,
89 	struct pf_state *, struct pf_state_key *, int, int);
90 void	copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *,
91 	struct pflow_ipfix_flow4 *, struct pf_state *, struct pf_state_key *,
92 	struct pflow_softc *, int, int);
93 void	copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *,
94 	struct pflow_ipfix_flow6 *, struct pf_state *, struct pf_state_key *,
95 	struct pflow_softc *, int, int);
96 int	pflow_pack_flow(struct pf_state *, struct pf_state_key *,
97 	struct pflow_softc *);
98 int	pflow_pack_flow_ipfix(struct pf_state *, struct pf_state_key *,
99 	struct pflow_softc *);
100 int	export_pflow_if(struct pf_state*, struct pf_state_key *,
101 	struct pflow_softc *);
102 int	copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc);
103 int	copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow,
104 	struct pflow_softc *sc);
105 int	copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow,
106 	struct pflow_softc *sc);
107 
108 struct if_clone	pflow_cloner =
109     IF_CLONE_INITIALIZER("pflow", pflow_clone_create,
110     pflow_clone_destroy);
111 
112 void
113 pflowattach(int npflow)
114 {
115 	SLIST_INIT(&pflowif_list);
116 	if_clone_attach(&pflow_cloner);
117 }
118 
119 int
120 pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
121 	struct rtentry *rt)
122 {
123 	m_freem(m);	/* drop packet */
124 	return (EAFNOSUPPORT);
125 }
126 
127 void
128 pflow_output_process(void *arg)
129 {
130 	struct mbuf_list ml;
131 	struct pflow_softc *sc = arg;
132 	struct mbuf *m;
133 
134 	mq_delist(&sc->sc_outputqueue, &ml);
135 	KERNEL_LOCK();
136 	while ((m = ml_dequeue(&ml)) != NULL) {
137 		pflow_sendout_mbuf(sc, m);
138 	}
139 	KERNEL_UNLOCK();
140 }
141 
142 int
143 pflow_clone_create(struct if_clone *ifc, int unit)
144 {
145 	struct ifnet		*ifp;
146 	struct pflow_softc	*pflowif;
147 
148 	pflowif = malloc(sizeof(*pflowif), M_DEVBUF, M_WAITOK|M_ZERO);
149 	MGET(pflowif->send_nam, M_WAIT, MT_SONAME);
150 	pflowif->sc_version = PFLOW_PROTO_DEFAULT;
151 
152 	/* ipfix template init */
153 	bzero(&pflowif->sc_tmpl_ipfix,sizeof(pflowif->sc_tmpl_ipfix));
154 	pflowif->sc_tmpl_ipfix.set_header.set_id =
155 	    htons(PFLOW_IPFIX_TMPL_SET_ID);
156 	pflowif->sc_tmpl_ipfix.set_header.set_length =
157 	    htons(sizeof(struct pflow_ipfix_tmpl));
158 
159 	/* ipfix IPv4 template */
160 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.tmpl_id =
161 	    htons(PFLOW_IPFIX_TMPL_IPV4_ID);
162 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.field_count
163 	    = htons(PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT);
164 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.field_id =
165 	    htons(PFIX_IE_sourceIPv4Address);
166 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.len = htons(4);
167 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.field_id =
168 	    htons(PFIX_IE_destinationIPv4Address);
169 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.len = htons(4);
170 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.field_id =
171 	    htons(PFIX_IE_ingressInterface);
172 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.len = htons(4);
173 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.field_id =
174 	    htons(PFIX_IE_egressInterface);
175 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.len = htons(4);
176 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.field_id =
177 	    htons(PFIX_IE_packetDeltaCount);
178 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.len = htons(8);
179 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.field_id =
180 	    htons(PFIX_IE_octetDeltaCount);
181 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.len = htons(8);
182 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.field_id =
183 	    htons(PFIX_IE_flowStartMilliseconds);
184 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.len = htons(8);
185 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.field_id =
186 	    htons(PFIX_IE_flowEndMilliseconds);
187 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.len = htons(8);
188 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.field_id =
189 	    htons(PFIX_IE_sourceTransportPort);
190 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.len = htons(2);
191 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.field_id =
192 	    htons(PFIX_IE_destinationTransportPort);
193 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.len = htons(2);
194 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.field_id =
195 	    htons(PFIX_IE_ipClassOfService);
196 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.len = htons(1);
197 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.field_id =
198 	    htons(PFIX_IE_protocolIdentifier);
199 	pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.len = htons(1);
200 
201 	/* ipfix IPv6 template */
202 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.tmpl_id =
203 	    htons(PFLOW_IPFIX_TMPL_IPV6_ID);
204 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.field_count =
205 	    htons(PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT);
206 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.field_id =
207 	    htons(PFIX_IE_sourceIPv6Address);
208 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.len = htons(16);
209 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.field_id =
210 	    htons(PFIX_IE_destinationIPv6Address);
211 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.len = htons(16);
212 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.field_id =
213 	    htons(PFIX_IE_ingressInterface);
214 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.len = htons(4);
215 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.field_id =
216 	    htons(PFIX_IE_egressInterface);
217 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.len = htons(4);
218 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.field_id =
219 	    htons(PFIX_IE_packetDeltaCount);
220 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.len = htons(8);
221 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.field_id =
222 	    htons(PFIX_IE_octetDeltaCount);
223 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.len = htons(8);
224 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.field_id =
225 	    htons(PFIX_IE_flowStartMilliseconds);
226 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.len = htons(8);
227 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.field_id =
228 	    htons(PFIX_IE_flowEndMilliseconds);
229 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.len = htons(8);
230 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.field_id =
231 	    htons(PFIX_IE_sourceTransportPort);
232 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.len = htons(2);
233 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.field_id =
234 	    htons(PFIX_IE_destinationTransportPort);
235 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.len = htons(2);
236 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.field_id =
237 	    htons(PFIX_IE_ipClassOfService);
238 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.len = htons(1);
239 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.field_id =
240 	    htons(PFIX_IE_protocolIdentifier);
241 	pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.len = htons(1);
242 
243 	ifp = &pflowif->sc_if;
244 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit);
245 	ifp->if_softc = pflowif;
246 	ifp->if_ioctl = pflowioctl;
247 	ifp->if_output = pflow_output;
248 	ifp->if_start = NULL;
249 	ifp->if_xflags = IFXF_CLONED;
250 	ifp->if_type = IFT_PFLOW;
251 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
252 	ifp->if_hdrlen = PFLOW_HDRLEN;
253 	ifp->if_flags = IFF_UP;
254 	ifp->if_flags &= ~IFF_RUNNING;	/* not running, need receiver */
255 	mq_init(&pflowif->sc_outputqueue, 8192, IPL_SOFTNET);
256 	pflow_setmtu(pflowif, ETHERMTU);
257 	pflow_init_timeouts(pflowif);
258 	if_attach(ifp);
259 	if_alloc_sadl(ifp);
260 
261 	task_set(&pflowif->sc_outputtask, pflow_output_process, pflowif);
262 
263 	/* Insert into list of pflows */
264 	NET_LOCK();
265 	SLIST_INSERT_HEAD(&pflowif_list, pflowif, sc_next);
266 	NET_UNLOCK();
267 	return (0);
268 }
269 
270 int
271 pflow_clone_destroy(struct ifnet *ifp)
272 {
273 	struct pflow_softc	*sc = ifp->if_softc;
274 	int			 error;
275 
276 	error = 0;
277 
278 	if (timeout_initialized(&sc->sc_tmo))
279 		timeout_del(&sc->sc_tmo);
280 	if (timeout_initialized(&sc->sc_tmo6))
281 		timeout_del(&sc->sc_tmo6);
282 	if (timeout_initialized(&sc->sc_tmo_tmpl))
283 		timeout_del(&sc->sc_tmo_tmpl);
284 	pflow_flush(sc);
285 	task_del(net_tq(ifp->if_index), &sc->sc_outputtask);
286 	mq_purge(&sc->sc_outputqueue);
287 	m_freem(sc->send_nam);
288 	if (sc->so != NULL) {
289 		error = soclose(sc->so);
290 		sc->so = NULL;
291 	}
292 	if (sc->sc_flowdst != NULL)
293 		free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len);
294 	if (sc->sc_flowsrc != NULL)
295 		free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len);
296 	if_detach(ifp);
297 	NET_LOCK();
298 	SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
299 	NET_UNLOCK();
300 	free(sc, M_DEVBUF, sizeof(*sc));
301 	return (error);
302 }
303 
304 int
305 pflowvalidsockaddr(const struct sockaddr *sa, int ignore_port)
306 {
307 	struct sockaddr_in6	*sin6;
308 	struct sockaddr_in	*sin;
309 
310 	if (sa == NULL)
311 		return (0);
312 	switch(sa->sa_family) {
313 	case AF_INET:
314 		sin = (struct sockaddr_in*) sa;
315 		return (sin->sin_addr.s_addr != INADDR_ANY &&
316 		    (ignore_port || sin->sin_port != 0));
317 	case AF_INET6:
318 		sin6 = (struct sockaddr_in6*) sa;
319 		return (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
320 		    (ignore_port || sin6->sin6_port != 0));
321 	default:
322 		return (0);
323 	}
324 }
325 
326 int
327 pflow_set(struct pflow_softc *sc, struct pflowreq *pflowr)
328 {
329 	struct proc		*p = curproc;
330 	struct socket		*so;
331 	struct sockaddr		*sa;
332 	int			 error = 0;
333 
334 	if (pflowr->addrmask & PFLOW_MASK_VERSION) {
335 		switch(pflowr->version) {
336 		case PFLOW_PROTO_5:
337 		case PFLOW_PROTO_10:
338 			break;
339 		default:
340 			return(EINVAL);
341 		}
342 	}
343 
344 	pflow_flush(sc);
345 
346 	if (pflowr->addrmask & PFLOW_MASK_DSTIP) {
347 		if (sc->sc_flowdst != NULL &&
348 		    sc->sc_flowdst->sa_family != pflowr->flowdst.ss_family) {
349 			free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len);
350 			sc->sc_flowdst = NULL;
351 			if (sc->so != NULL) {
352 				soclose(sc->so);
353 				sc->so = NULL;
354 			}
355 		}
356 
357 		switch (pflowr->flowdst.ss_family) {
358 		case AF_INET:
359 			if (sc->sc_flowdst == NULL) {
360 				if ((sc->sc_flowdst = malloc(
361 				    sizeof(struct sockaddr_in),
362 				    M_DEVBUF,  M_NOWAIT)) == NULL)
363 					return (ENOMEM);
364 			}
365 			memcpy(sc->sc_flowdst, &pflowr->flowdst,
366 			    sizeof(struct sockaddr_in));
367 			sc->sc_flowdst->sa_len = sizeof(struct
368 			    sockaddr_in);
369 			break;
370 		case AF_INET6:
371 			if (sc->sc_flowdst == NULL) {
372 				if ((sc->sc_flowdst = malloc(
373 				    sizeof(struct sockaddr_in6),
374 				    M_DEVBUF, M_NOWAIT)) == NULL)
375 					return (ENOMEM);
376 			}
377 			memcpy(sc->sc_flowdst, &pflowr->flowdst,
378 			    sizeof(struct sockaddr_in6));
379 			sc->sc_flowdst->sa_len = sizeof(struct
380 			    sockaddr_in6);
381 			break;
382 		default:
383 			break;
384 		}
385 
386 		if (sc->sc_flowdst != NULL) {
387 			sc->send_nam->m_len = sc->sc_flowdst->sa_len;
388 			sa = mtod(sc->send_nam, struct sockaddr *);
389 			memcpy(sa, sc->sc_flowdst, sc->sc_flowdst->sa_len);
390 		}
391 	}
392 
393 	if (pflowr->addrmask & PFLOW_MASK_SRCIP) {
394 		if (sc->sc_flowsrc != NULL)
395 			free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len);
396 		sc->sc_flowsrc = NULL;
397 		if (sc->so != NULL) {
398 			soclose(sc->so);
399 			sc->so = NULL;
400 		}
401 		switch(pflowr->flowsrc.ss_family) {
402 		case AF_INET:
403 			if ((sc->sc_flowsrc = malloc(
404 			    sizeof(struct sockaddr_in),
405 			    M_DEVBUF, M_NOWAIT)) == NULL)
406 				return (ENOMEM);
407 			memcpy(sc->sc_flowsrc, &pflowr->flowsrc,
408 			    sizeof(struct sockaddr_in));
409 			sc->sc_flowsrc->sa_len = sizeof(struct
410 			    sockaddr_in);
411 			break;
412 		case AF_INET6:
413 			if ((sc->sc_flowsrc = malloc(
414 			    sizeof(struct sockaddr_in6),
415 			    M_DEVBUF, M_NOWAIT)) == NULL)
416 				return (ENOMEM);
417 			memcpy(sc->sc_flowsrc, &pflowr->flowsrc,
418 			    sizeof(struct sockaddr_in6));
419 			sc->sc_flowsrc->sa_len = sizeof(struct
420 			    sockaddr_in6);
421 			break;
422 		default:
423 			break;
424 		}
425 	}
426 
427 	if (sc->so == NULL) {
428 		if (pflowvalidsockaddr(sc->sc_flowdst, 0)) {
429 			error = socreate(sc->sc_flowdst->sa_family,
430 			    &so, SOCK_DGRAM, 0);
431 			if (error)
432 				return (error);
433 			if (pflowvalidsockaddr(sc->sc_flowsrc, 1)) {
434 				struct mbuf *m;
435 				int s;
436 
437 				MGET(m, M_WAIT, MT_SONAME);
438 				m->m_len = sc->sc_flowsrc->sa_len;
439 				sa = mtod(m, struct sockaddr *);
440 				memcpy(sa, sc->sc_flowsrc,
441 				    sc->sc_flowsrc->sa_len);
442 
443 				s = solock(so);
444 				error = sobind(so, m, p);
445 				sounlock(s);
446 				m_freem(m);
447 				if (error) {
448 					soclose(so);
449 					return (error);
450 				}
451 			}
452 			sc->so = so;
453 		}
454 	} else if (!pflowvalidsockaddr(sc->sc_flowdst, 0)) {
455 		soclose(sc->so);
456 		sc->so = NULL;
457 	}
458 
459 	/* error check is above */
460 	if (pflowr->addrmask & PFLOW_MASK_VERSION)
461 		sc->sc_version = pflowr->version;
462 
463 	pflow_setmtu(sc, ETHERMTU);
464 	pflow_init_timeouts(sc);
465 
466 	return (0);
467 }
468 
469 int
470 pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
471 {
472 	struct proc		*p = curproc;
473 	struct pflow_softc	*sc = ifp->if_softc;
474 	struct ifreq		*ifr = (struct ifreq *)data;
475 	struct pflowreq		 pflowr;
476 	int			 error;
477 
478 	switch (cmd) {
479 	case SIOCSIFADDR:
480 	case SIOCSIFDSTADDR:
481 	case SIOCSIFFLAGS:
482 		if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
483 			ifp->if_flags |= IFF_RUNNING;
484 			sc->sc_gcounter=pflowstats.pflow_flows;
485 			/* send templates on startup */
486 			if (sc->sc_version == PFLOW_PROTO_10)
487 				pflow_sendout_ipfix_tmpl(sc);
488 		} else
489 			ifp->if_flags &= ~IFF_RUNNING;
490 		break;
491 	case SIOCSIFMTU:
492 		if (ifr->ifr_mtu < PFLOW_MINMTU)
493 			return (EINVAL);
494 		if (ifr->ifr_mtu > MCLBYTES)
495 			ifr->ifr_mtu = MCLBYTES;
496 		if (ifr->ifr_mtu < ifp->if_mtu)
497 			pflow_flush(sc);
498 		pflow_setmtu(sc, ifr->ifr_mtu);
499 		break;
500 
501 	case SIOCGETPFLOW:
502 		bzero(&pflowr, sizeof(pflowr));
503 
504 		if (sc->sc_flowsrc != NULL)
505 			memcpy(&pflowr.flowsrc, sc->sc_flowsrc,
506 			    sc->sc_flowsrc->sa_len);
507 		if (sc->sc_flowdst != NULL)
508 			memcpy(&pflowr.flowdst, sc->sc_flowdst,
509 			    sc->sc_flowdst->sa_len);
510 		pflowr.version = sc->sc_version;
511 
512 		if ((error = copyout(&pflowr, ifr->ifr_data,
513 		    sizeof(pflowr))))
514 			return (error);
515 		break;
516 
517 	case SIOCSETPFLOW:
518 		if ((error = suser(p, 0)) != 0)
519 			return (error);
520 		if ((error = copyin(ifr->ifr_data, &pflowr,
521 		    sizeof(pflowr))))
522 			return (error);
523 
524 		/* XXXSMP breaks atomicity */
525 		NET_UNLOCK();
526 		error = pflow_set(sc, &pflowr);
527 		NET_LOCK();
528 		if (error != 0)
529 			return (error);
530 
531 		if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
532 			ifp->if_flags |= IFF_RUNNING;
533 			sc->sc_gcounter=pflowstats.pflow_flows;
534 			if (sc->sc_version == PFLOW_PROTO_10)
535 				pflow_sendout_ipfix_tmpl(sc);
536 		} else
537 			ifp->if_flags &= ~IFF_RUNNING;
538 
539 		break;
540 
541 	default:
542 		return (ENOTTY);
543 	}
544 	return (0);
545 }
546 
547 void
548 pflow_init_timeouts(struct pflow_softc *sc)
549 {
550 	switch (sc->sc_version) {
551 	case PFLOW_PROTO_5:
552 		if (timeout_initialized(&sc->sc_tmo6))
553 			timeout_del(&sc->sc_tmo6);
554 		if (timeout_initialized(&sc->sc_tmo_tmpl))
555 			timeout_del(&sc->sc_tmo_tmpl);
556 		if (!timeout_initialized(&sc->sc_tmo))
557 			timeout_set_proc(&sc->sc_tmo, pflow_timeout, sc);
558 		break;
559 	case PFLOW_PROTO_10:
560 		if (!timeout_initialized(&sc->sc_tmo_tmpl))
561 			timeout_set_proc(&sc->sc_tmo_tmpl, pflow_timeout_tmpl,
562 			    sc);
563 		if (!timeout_initialized(&sc->sc_tmo))
564 			timeout_set_proc(&sc->sc_tmo, pflow_timeout, sc);
565 		if (!timeout_initialized(&sc->sc_tmo6))
566 			timeout_set_proc(&sc->sc_tmo6, pflow_timeout6, sc);
567 
568 		timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
569 		break;
570 	default: /* NOTREACHED */
571 		break;
572 	}
573 }
574 
575 int
576 pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz)
577 {
578 
579 	sc->sc_maxcount4 = (mtu - hdrsz -
580 	    sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow4);
581 	sc->sc_maxcount6 = (mtu - hdrsz -
582 	    sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow6);
583 	if (sc->sc_maxcount4 > PFLOW_MAXFLOWS)
584 		sc->sc_maxcount4 = PFLOW_MAXFLOWS;
585 	if (sc->sc_maxcount6 > PFLOW_MAXFLOWS)
586 		sc->sc_maxcount6 = PFLOW_MAXFLOWS;
587 	return (hdrsz + sizeof(struct udpiphdr) +
588 	    MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4),
589 	    sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6)));
590 }
591 
592 void
593 pflow_setmtu(struct pflow_softc *sc, int mtu_req)
594 {
595 	int	mtu;
596 
597 	if (sc->sc_pflow_ifp && sc->sc_pflow_ifp->if_mtu < mtu_req)
598 		mtu = sc->sc_pflow_ifp->if_mtu;
599 	else
600 		mtu = mtu_req;
601 
602 	switch (sc->sc_version) {
603 	case PFLOW_PROTO_5:
604 		sc->sc_maxcount = (mtu - sizeof(struct pflow_header) -
605 		    sizeof(struct udpiphdr)) / sizeof(struct pflow_flow);
606 		if (sc->sc_maxcount > PFLOW_MAXFLOWS)
607 		    sc->sc_maxcount = PFLOW_MAXFLOWS;
608 		sc->sc_if.if_mtu = sizeof(struct pflow_header) +
609 		    sizeof(struct udpiphdr) +
610 		    sc->sc_maxcount * sizeof(struct pflow_flow);
611 		break;
612 	case PFLOW_PROTO_10:
613 		sc->sc_if.if_mtu =
614 		    pflow_calc_mtu(sc, mtu, sizeof(struct pflow_v10_header));
615 		break;
616 	default: /* NOTREACHED */
617 		break;
618 	}
619 }
620 
621 struct mbuf *
622 pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id)
623 {
624 	struct pflow_set_header	 set_hdr;
625 	struct pflow_header	 h;
626 	struct mbuf		*m;
627 
628 	MGETHDR(m, M_DONTWAIT, MT_DATA);
629 	if (m == NULL) {
630 		pflowstats.pflow_onomem++;
631 		return (NULL);
632 	}
633 
634 	MCLGET(m, M_DONTWAIT);
635 	if ((m->m_flags & M_EXT) == 0) {
636 		m_free(m);
637 		pflowstats.pflow_onomem++;
638 		return (NULL);
639 	}
640 
641 	m->m_len = m->m_pkthdr.len = 0;
642 	m->m_pkthdr.ph_ifidx = 0;
643 
644 	if (sc == NULL)		/* get only a new empty mbuf */
645 		return (m);
646 
647 	if (sc->sc_version == PFLOW_PROTO_5) {
648 		/* populate pflow_header */
649 		h.reserved1 = 0;
650 		h.reserved2 = 0;
651 		h.count = 0;
652 		h.version = htons(PFLOW_PROTO_5);
653 		h.flow_sequence = htonl(sc->sc_gcounter);
654 		h.engine_type = PFLOW_ENGINE_TYPE;
655 		h.engine_id = PFLOW_ENGINE_ID;
656 		m_copyback(m, 0, PFLOW_HDRLEN, &h, M_NOWAIT);
657 
658 		sc->sc_count = 0;
659 		timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
660 	} else {
661 		/* populate pflow_set_header */
662 		set_hdr.set_length = 0;
663 		set_hdr.set_id = htons(set_id);
664 		m_copyback(m, 0, PFLOW_SET_HDRLEN, &set_hdr, M_NOWAIT);
665 	}
666 
667 	return (m);
668 }
669 
670 void
671 copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
672     struct pf_state *st, struct pf_state_key *sk, int src, int dst)
673 {
674 	flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
675 	flow1->src_port = flow2->dest_port = sk->port[src];
676 	flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
677 	flow1->dest_port = flow2->src_port = sk->port[dst];
678 
679 	flow1->dest_as = flow2->src_as =
680 	    flow1->src_as = flow2->dest_as = 0;
681 	flow1->if_index_in = htons(st->if_index_in);
682 	flow1->if_index_out = htons(st->if_index_out);
683 	flow2->if_index_in = htons(st->if_index_out);
684 	flow2->if_index_out = htons(st->if_index_in);
685 	flow1->dest_mask = flow2->src_mask =
686 	    flow1->src_mask = flow2->dest_mask = 0;
687 
688 	flow1->flow_packets = htonl(st->packets[0]);
689 	flow2->flow_packets = htonl(st->packets[1]);
690 	flow1->flow_octets = htonl(st->bytes[0]);
691 	flow2->flow_octets = htonl(st->bytes[1]);
692 
693 	/*
694 	 * Pretend the flow was created or expired when the machine came up
695 	 * when creation is in the future of the last time a package was seen
696 	 * or was created / expired before this machine came up due to pfsync.
697 	 */
698 	flow1->flow_start = flow2->flow_start = st->creation < 0 ||
699 	    st->creation > st->expire ? htonl(0) : htonl(st->creation * 1000);
700 	flow1->flow_finish = flow2->flow_finish = st->expire < 0 ? htonl(0) :
701 	    htonl(st->expire * 1000);
702 	flow1->tcp_flags = flow2->tcp_flags = 0;
703 	flow1->protocol = flow2->protocol = sk->proto;
704 	flow1->tos = flow2->tos = st->rule.ptr->tos;
705 }
706 
707 void
708 copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
709     struct pflow_ipfix_flow4 *flow2, struct pf_state *st,
710     struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
711 {
712 	flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
713 	flow1->src_port = flow2->dest_port = sk->port[src];
714 	flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
715 	flow1->dest_port = flow2->src_port = sk->port[dst];
716 
717 	flow1->if_index_in = htonl(st->if_index_in);
718 	flow1->if_index_out = htonl(st->if_index_out);
719 	flow2->if_index_in = htonl(st->if_index_out);
720 	flow2->if_index_out = htonl(st->if_index_in);
721 
722 	flow1->flow_packets = htobe64(st->packets[0]);
723 	flow2->flow_packets = htobe64(st->packets[1]);
724 	flow1->flow_octets = htobe64(st->bytes[0]);
725 	flow2->flow_octets = htobe64(st->bytes[1]);
726 
727 	/*
728 	 * Pretend the flow was created when the machine came up when creation
729 	 * is in the future of the last time a package was seen due to pfsync.
730 	 */
731 	if (st->creation > st->expire)
732 		flow1->flow_start = flow2->flow_start = htobe64((time_second -
733 		    time_uptime)*1000);
734 	else
735 		flow1->flow_start = flow2->flow_start = htobe64((time_second -
736 		    (time_uptime - st->creation))*1000);
737 	flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
738 	    (time_uptime - st->expire))*1000);
739 
740 	flow1->protocol = flow2->protocol = sk->proto;
741 	flow1->tos = flow2->tos = st->rule.ptr->tos;
742 }
743 
744 void
745 copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
746     struct pflow_ipfix_flow6 *flow2, struct pf_state *st,
747     struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
748 {
749 	bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip));
750 	bcopy(&sk->addr[src].v6, &flow2->dest_ip, sizeof(flow2->dest_ip));
751 	flow1->src_port = flow2->dest_port = sk->port[src];
752 	bcopy(&sk->addr[dst].v6, &flow1->dest_ip, sizeof(flow1->dest_ip));
753 	bcopy(&sk->addr[dst].v6, &flow2->src_ip, sizeof(flow2->src_ip));
754 	flow1->dest_port = flow2->src_port = sk->port[dst];
755 
756 	flow1->if_index_in = htonl(st->if_index_in);
757 	flow1->if_index_out = htonl(st->if_index_out);
758 	flow2->if_index_in = htonl(st->if_index_out);
759 	flow2->if_index_out = htonl(st->if_index_in);
760 
761 	flow1->flow_packets = htobe64(st->packets[0]);
762 	flow2->flow_packets = htobe64(st->packets[1]);
763 	flow1->flow_octets = htobe64(st->bytes[0]);
764 	flow2->flow_octets = htobe64(st->bytes[1]);
765 
766 	/*
767 	 * Pretend the flow was created when the machine came up when creation
768 	 * is in the future of the last time a package was seen due to pfsync.
769 	 */
770 	if (st->creation > st->expire)
771 		flow1->flow_start = flow2->flow_start = htobe64((time_second -
772 		    time_uptime)*1000);
773 	else
774 		flow1->flow_start = flow2->flow_start = htobe64((time_second -
775 		    (time_uptime - st->creation))*1000);
776 	flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
777 	    (time_uptime - st->expire))*1000);
778 
779 	flow1->protocol = flow2->protocol = sk->proto;
780 	flow1->tos = flow2->tos = st->rule.ptr->tos;
781 }
782 
783 int
784 export_pflow(struct pf_state *st)
785 {
786 	struct pflow_softc	*sc = NULL;
787 	struct pf_state_key	*sk;
788 
789 	sk = st->key[st->direction == PF_IN ? PF_SK_WIRE : PF_SK_STACK];
790 
791 	SLIST_FOREACH(sc, &pflowif_list, sc_next) {
792 		switch (sc->sc_version) {
793 		case PFLOW_PROTO_5:
794 			if( sk->af == AF_INET )
795 				export_pflow_if(st, sk, sc);
796 			break;
797 		case PFLOW_PROTO_10:
798 			if( sk->af == AF_INET || sk->af == AF_INET6 )
799 				export_pflow_if(st, sk, sc);
800 			break;
801 		default: /* NOTREACHED */
802 			break;
803 		}
804 	}
805 
806 	return (0);
807 }
808 
809 int
810 export_pflow_if(struct pf_state *st, struct pf_state_key *sk,
811     struct pflow_softc *sc)
812 {
813 	struct pf_state		 pfs_copy;
814 	struct ifnet		*ifp = &sc->sc_if;
815 	u_int64_t		 bytes[2];
816 	int			 ret = 0;
817 
818 	if (!(ifp->if_flags & IFF_RUNNING))
819 		return (0);
820 
821 	if (sc->sc_version == PFLOW_PROTO_10)
822 		return (pflow_pack_flow_ipfix(st, sk, sc));
823 
824 	/* PFLOW_PROTO_5 */
825 	if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES)
826 	    && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES))
827 		return (pflow_pack_flow(st, sk, sc));
828 
829 	/* flow > PFLOW_MAXBYTES need special handling */
830 	bcopy(st, &pfs_copy, sizeof(pfs_copy));
831 	bytes[0] = pfs_copy.bytes[0];
832 	bytes[1] = pfs_copy.bytes[1];
833 
834 	while (bytes[0] > PFLOW_MAXBYTES) {
835 		pfs_copy.bytes[0] = PFLOW_MAXBYTES;
836 		pfs_copy.bytes[1] = 0;
837 
838 		if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0)
839 			return (ret);
840 		if ((bytes[0] - PFLOW_MAXBYTES) > 0)
841 			bytes[0] -= PFLOW_MAXBYTES;
842 	}
843 
844 	while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) {
845 		pfs_copy.bytes[1] = PFLOW_MAXBYTES;
846 		pfs_copy.bytes[0] = 0;
847 
848 		if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0)
849 			return (ret);
850 		if ((bytes[1] - PFLOW_MAXBYTES) > 0)
851 			bytes[1] -= PFLOW_MAXBYTES;
852 	}
853 
854 	pfs_copy.bytes[0] = bytes[0];
855 	pfs_copy.bytes[1] = bytes[1];
856 
857 	return (pflow_pack_flow(&pfs_copy, sk, sc));
858 }
859 
860 int
861 copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc)
862 {
863 	int		ret = 0;
864 
865 	if (sc->sc_mbuf == NULL) {
866 		if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0)) == NULL)
867 			return (ENOBUFS);
868 	}
869 	m_copyback(sc->sc_mbuf, PFLOW_HDRLEN +
870 	    (sc->sc_count * sizeof(struct pflow_flow)),
871 	    sizeof(struct pflow_flow), flow, M_NOWAIT);
872 
873 	if (pflowstats.pflow_flows == sc->sc_gcounter)
874 		pflowstats.pflow_flows++;
875 	sc->sc_gcounter++;
876 	sc->sc_count++;
877 
878 	if (sc->sc_count >= sc->sc_maxcount)
879 		ret = pflow_sendout_v5(sc);
880 
881 	return(ret);
882 }
883 
884 int
885 copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc)
886 {
887 	int		ret = 0;
888 
889 	if (sc->sc_mbuf == NULL) {
890 		if ((sc->sc_mbuf =
891 		    pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID)) == NULL) {
892 			return (ENOBUFS);
893 		}
894 		sc->sc_count4 = 0;
895 		timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
896 	}
897 	m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN +
898 	    (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)),
899 	    sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT);
900 
901 	if (pflowstats.pflow_flows == sc->sc_gcounter)
902 		pflowstats.pflow_flows++;
903 	sc->sc_gcounter++;
904 	sc->sc_count4++;
905 
906 	if (sc->sc_count4 >= sc->sc_maxcount4)
907 		ret = pflow_sendout_ipfix(sc, AF_INET);
908 	return(ret);
909 }
910 
911 int
912 copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
913 {
914 	int		ret = 0;
915 
916 	if (sc->sc_mbuf6 == NULL) {
917 		if ((sc->sc_mbuf6 =
918 		    pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID)) == NULL) {
919 			return (ENOBUFS);
920 		}
921 		sc->sc_count6 = 0;
922 		timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT);
923 	}
924 	m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN +
925 	    (sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)),
926 	    sizeof(struct pflow_ipfix_flow6), flow, M_NOWAIT);
927 
928 	if (pflowstats.pflow_flows == sc->sc_gcounter)
929 		pflowstats.pflow_flows++;
930 	sc->sc_gcounter++;
931 	sc->sc_count6++;
932 
933 	if (sc->sc_count6 >= sc->sc_maxcount6)
934 		ret = pflow_sendout_ipfix(sc, AF_INET6);
935 
936 	return(ret);
937 }
938 
939 int
940 pflow_pack_flow(struct pf_state *st, struct pf_state_key *sk,
941     struct pflow_softc *sc)
942 {
943 	struct pflow_flow	 flow1;
944 	struct pflow_flow	 flow2;
945 	int			 ret = 0;
946 
947 	bzero(&flow1, sizeof(flow1));
948 	bzero(&flow2, sizeof(flow2));
949 
950 	if (st->direction == PF_OUT)
951 		copy_flow_data(&flow1, &flow2, st, sk, 1, 0);
952 	else
953 		copy_flow_data(&flow1, &flow2, st, sk, 0, 1);
954 
955 	if (st->bytes[0] != 0) /* first flow from state */
956 		ret = copy_flow_to_m(&flow1, sc);
957 
958 	if (st->bytes[1] != 0) /* second flow from state */
959 		ret = copy_flow_to_m(&flow2, sc);
960 
961 	return (ret);
962 }
963 
964 int
965 pflow_pack_flow_ipfix(struct pf_state *st, struct pf_state_key *sk,
966     struct pflow_softc *sc)
967 {
968 	struct pflow_ipfix_flow4	 flow4_1, flow4_2;
969 	struct pflow_ipfix_flow6	 flow6_1, flow6_2;
970 	int				 ret = 0;
971 	if (sk->af == AF_INET) {
972 		bzero(&flow4_1, sizeof(flow4_1));
973 		bzero(&flow4_2, sizeof(flow4_2));
974 
975 		if (st->direction == PF_OUT)
976 			copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
977 			    1, 0);
978 		else
979 			copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
980 			    0, 1);
981 
982 		if (st->bytes[0] != 0) /* first flow from state */
983 			ret = copy_flow_ipfix_4_to_m(&flow4_1, sc);
984 
985 		if (st->bytes[1] != 0) /* second flow from state */
986 			ret = copy_flow_ipfix_4_to_m(&flow4_2, sc);
987 	} else if (sk->af == AF_INET6) {
988 		bzero(&flow6_1, sizeof(flow6_1));
989 		bzero(&flow6_2, sizeof(flow6_2));
990 
991 		if (st->direction == PF_OUT)
992 			copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
993 			    1, 0);
994 		else
995 			copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
996 			    0, 1);
997 
998 		if (st->bytes[0] != 0) /* first flow from state */
999 			ret = copy_flow_ipfix_6_to_m(&flow6_1, sc);
1000 
1001 		if (st->bytes[1] != 0) /* second flow from state */
1002 			ret = copy_flow_ipfix_6_to_m(&flow6_2, sc);
1003 	}
1004 	return (ret);
1005 }
1006 
1007 void
1008 pflow_timeout(void *v)
1009 {
1010 	struct pflow_softc	*sc = v;
1011 
1012 	switch (sc->sc_version) {
1013 	case PFLOW_PROTO_5:
1014 		pflow_sendout_v5(sc);
1015 		break;
1016 	case PFLOW_PROTO_10:
1017 		pflow_sendout_ipfix(sc, AF_INET);
1018 		break;
1019 	default: /* NOTREACHED */
1020 		break;
1021 	}
1022 }
1023 
1024 void
1025 pflow_timeout6(void *v)
1026 {
1027 	struct pflow_softc	*sc = v;
1028 
1029 	pflow_sendout_ipfix(sc, AF_INET6);
1030 }
1031 
1032 void
1033 pflow_timeout_tmpl(void *v)
1034 {
1035 	struct pflow_softc	*sc = v;
1036 
1037 	pflow_sendout_ipfix_tmpl(sc);
1038 }
1039 
1040 void
1041 pflow_flush(struct pflow_softc *sc)
1042 {
1043 	switch (sc->sc_version) {
1044 	case PFLOW_PROTO_5:
1045 		pflow_sendout_v5(sc);
1046 		break;
1047 	case PFLOW_PROTO_10:
1048 		pflow_sendout_ipfix(sc, AF_INET);
1049 		pflow_sendout_ipfix(sc, AF_INET6);
1050 		break;
1051 	default: /* NOTREACHED */
1052 		break;
1053 	}
1054 }
1055 
1056 int
1057 pflow_sendout_v5(struct pflow_softc *sc)
1058 {
1059 	struct mbuf		*m = sc->sc_mbuf;
1060 	struct pflow_header	*h;
1061 	struct ifnet		*ifp = &sc->sc_if;
1062 	struct timespec		tv;
1063 
1064 	timeout_del(&sc->sc_tmo);
1065 
1066 	if (m == NULL)
1067 		return (0);
1068 
1069 	sc->sc_mbuf = NULL;
1070 	if (!(ifp->if_flags & IFF_RUNNING)) {
1071 		m_freem(m);
1072 		return (0);
1073 	}
1074 
1075 	pflowstats.pflow_packets++;
1076 	h = mtod(m, struct pflow_header *);
1077 	h->count = htons(sc->sc_count);
1078 
1079 	/* populate pflow_header */
1080 	h->uptime_ms = htonl(time_uptime * 1000);
1081 
1082 	getnanotime(&tv);
1083 	h->time_sec = htonl(tv.tv_sec);			/* XXX 2038 */
1084 	h->time_nanosec = htonl(tv.tv_nsec);
1085 	if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
1086 		task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
1087 	return (0);
1088 }
1089 
1090 int
1091 pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
1092 {
1093 	struct mbuf			*m;
1094 	struct pflow_v10_header		*h10;
1095 	struct pflow_set_header		*set_hdr;
1096 	struct ifnet			*ifp = &sc->sc_if;
1097 	u_int32_t			 count;
1098 	int				 set_length;
1099 
1100 	switch (af) {
1101 	case AF_INET:
1102 		m = sc->sc_mbuf;
1103 		timeout_del(&sc->sc_tmo);
1104 		if (m == NULL)
1105 			return (0);
1106 		sc->sc_mbuf = NULL;
1107 		count = sc->sc_count4;
1108 		set_length = sizeof(struct pflow_set_header)
1109 		    + sc->sc_count4 * sizeof(struct pflow_ipfix_flow4);
1110 		break;
1111 	case AF_INET6:
1112 		m = sc->sc_mbuf6;
1113 		timeout_del(&sc->sc_tmo6);
1114 		if (m == NULL)
1115 			return (0);
1116 		sc->sc_mbuf6 = NULL;
1117 		count = sc->sc_count6;
1118 		set_length = sizeof(struct pflow_set_header)
1119 		    + sc->sc_count6 * sizeof(struct pflow_ipfix_flow6);
1120 		break;
1121 	default:
1122 		unhandled_af(af);
1123 	}
1124 
1125 	if (!(ifp->if_flags & IFF_RUNNING)) {
1126 		m_freem(m);
1127 		return (0);
1128 	}
1129 
1130 	pflowstats.pflow_packets++;
1131 	set_hdr = mtod(m, struct pflow_set_header *);
1132 	set_hdr->set_length = htons(set_length);
1133 
1134 	/* populate pflow_header */
1135 	M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
1136 	if (m == NULL) {
1137 		pflowstats.pflow_onomem++;
1138 		return (ENOBUFS);
1139 	}
1140 	h10 = mtod(m, struct pflow_v10_header *);
1141 	h10->version = htons(PFLOW_PROTO_10);
1142 	h10->length = htons(PFLOW_IPFIX_HDRLEN + set_length);
1143 	h10->time_sec = htonl(time_second);		/* XXX 2038 */
1144 	h10->flow_sequence = htonl(sc->sc_sequence);
1145 	sc->sc_sequence += count;
1146 	h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1147 	if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
1148 		task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
1149 	return (0);
1150 }
1151 
1152 int
1153 pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
1154 {
1155 	struct mbuf			*m;
1156 	struct pflow_v10_header		*h10;
1157 	struct ifnet			*ifp = &sc->sc_if;
1158 
1159 	timeout_del(&sc->sc_tmo_tmpl);
1160 
1161 	if (!(ifp->if_flags & IFF_RUNNING)) {
1162 		return (0);
1163 	}
1164 	m = pflow_get_mbuf(NULL, 0);
1165 	if (m == NULL)
1166 		return (0);
1167 	if (m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl),
1168 	    &sc->sc_tmpl_ipfix, M_NOWAIT)) {
1169 		m_freem(m);
1170 		return (0);
1171 	}
1172 	pflowstats.pflow_packets++;
1173 
1174 	/* populate pflow_header */
1175 	M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
1176 	if (m == NULL) {
1177 		pflowstats.pflow_onomem++;
1178 		return (ENOBUFS);
1179 	}
1180 	h10 = mtod(m, struct pflow_v10_header *);
1181 	h10->version = htons(PFLOW_PROTO_10);
1182 	h10->length = htons(PFLOW_IPFIX_HDRLEN + sizeof(struct
1183 	    pflow_ipfix_tmpl));
1184 	h10->time_sec = htonl(time_second);		/* XXX 2038 */
1185 	h10->flow_sequence = htonl(sc->sc_sequence);
1186 	h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1187 
1188 	timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
1189 	if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
1190 		task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
1191 	return (0);
1192 }
1193 
1194 int
1195 pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m)
1196 {
1197 	sc->sc_if.if_opackets++;
1198 	sc->sc_if.if_obytes += m->m_pkthdr.len;
1199 
1200 	if (sc->so == NULL) {
1201 		m_freem(m);
1202 		return (EINVAL);
1203 	}
1204 	return (sosend(sc->so, sc->send_nam, NULL, m, NULL, 0));
1205 }
1206 
1207 int
1208 pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1209     void *newp, size_t newlen)
1210 {
1211 	if (namelen != 1)
1212 		return (ENOTDIR);
1213 
1214 	switch (name[0]) {
1215 	case NET_PFLOW_STATS:
1216 		if (newp != NULL)
1217 			return (EPERM);
1218 		return (sysctl_struct(oldp, oldlenp, newp, newlen,
1219 		    &pflowstats, sizeof(pflowstats)));
1220 	default:
1221 		return (EOPNOTSUPP);
1222 	}
1223 	return (0);
1224 }
1225