xref: /openbsd/sys/net/if_pflow.c (revision 898184e3)
1 /*	$OpenBSD: if_pflow.c,v 1.24 2013/02/05 11:58:39 florian 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/types.h>
23 #include <sys/malloc.h>
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/mbuf.h>
27 #include <sys/socket.h>
28 #include <sys/ioctl.h>
29 #include <sys/kernel.h>
30 #include <sys/proc.h>
31 #include <sys/sysctl.h>
32 #include <dev/rndvar.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 #ifdef INET
43 #include <netinet/in.h>
44 #include <netinet/in_var.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/ip.h>
47 #include <netinet/ip_var.h>
48 #include <netinet/udp.h>
49 #include <netinet/udp_var.h>
50 #include <netinet/in_pcb.h>
51 #endif /* INET */
52 
53 #include <net/pfvar.h>
54 #include <net/if_pflow.h>
55 
56 #include "bpfilter.h"
57 #include "pflow.h"
58 
59 #define PFLOW_MINMTU	\
60     (sizeof(struct pflow_header) + sizeof(struct pflow_flow))
61 
62 #ifdef PFLOWDEBUG
63 #define DPRINTF(x)	do { printf x ; } while (0)
64 #else
65 #define DPRINTF(x)
66 #endif
67 
68 SLIST_HEAD(, pflow_softc) pflowif_list;
69 struct pflowstats	 pflowstats;
70 
71 void	pflowattach(int);
72 int	pflow_clone_create(struct if_clone *, int);
73 int	pflow_clone_destroy(struct ifnet *);
74 void	pflow_init_timeouts(struct pflow_softc *);
75 int	pflow_calc_mtu(struct pflow_softc *, int, int);
76 void	pflow_setmtu(struct pflow_softc *, int);
77 int	pflowoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
78 	    struct rtentry *);
79 int	pflowioctl(struct ifnet *, u_long, caddr_t);
80 void	pflowstart(struct ifnet *);
81 
82 struct mbuf	*pflow_get_mbuf(struct pflow_softc *, u_int16_t);
83 void	pflow_flush(struct pflow_softc *);
84 int	pflow_sendout_v5(struct pflow_softc *);
85 int	pflow_sendout_ipfix(struct pflow_softc *, sa_family_t);
86 int	pflow_sendout_ipfix_tmpl(struct pflow_softc *);
87 int	pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
88 void	pflow_timeout(void *);
89 void	pflow_timeout6(void *);
90 void	pflow_timeout_tmpl(void *);
91 void	copy_flow_data(struct pflow_flow *, struct pflow_flow *,
92 	struct pf_state *, int, int);
93 void	copy_flow4_data(struct pflow_flow4 *, struct pflow_flow4 *,
94 	struct pf_state *, struct pflow_softc *, int, int);
95 void	copy_flow6_data(struct pflow_flow6 *, struct pflow_flow6 *,
96 	struct pf_state *, struct pflow_softc *, int, int);
97 int	pflow_pack_flow(struct pf_state *, struct pflow_softc *);
98 int	pflow_pack_flow_ipfix(struct pf_state *, struct pflow_softc *);
99 int	pflow_get_dynport(void);
100 int	export_pflow_if(struct pf_state*, struct pflow_softc *);
101 int	copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc);
102 int	copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc);
103 int	copy_flow6_to_m(struct pflow_flow6 *flow, struct pflow_softc *sc);
104 
105 struct if_clone	pflow_cloner =
106     IF_CLONE_INITIALIZER("pflow", pflow_clone_create,
107     pflow_clone_destroy);
108 
109 /* from in_pcb.c */
110 extern int ipport_hifirstauto;
111 extern int ipport_hilastauto;
112 
113 /* from udp_usrreq.c */
114 extern int udpcksum;
115 
116 void
117 pflowattach(int npflow)
118 {
119 	SLIST_INIT(&pflowif_list);
120 	if_clone_attach(&pflow_cloner);
121 }
122 
123 int
124 pflow_clone_create(struct if_clone *ifc, int unit)
125 {
126 	struct ifnet		*ifp;
127 	struct pflow_softc	*pflowif;
128 
129 	if ((pflowif = malloc(sizeof(*pflowif),
130 	    M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
131 		return (ENOMEM);
132 
133 	pflowif->sc_imo.imo_membership = malloc(
134 	    (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS,
135 	    M_WAITOK|M_ZERO);
136 	pflowif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
137 	pflowif->sc_receiver_ip.s_addr = 0;
138 	pflowif->sc_receiver_port = 0;
139 	pflowif->sc_sender_ip.s_addr = INADDR_ANY;
140 	pflowif->sc_sender_port = pflow_get_dynport();
141 	pflowif->sc_version = PFLOW_PROTO_DEFAULT;
142 	bzero(&pflowif->sc_tmpl,sizeof(pflowif->sc_tmpl));
143 	pflowif->sc_tmpl.set_header.set_id =
144 	    htons(pflowif->sc_version == PFLOW_PROTO_9?
145 	    PFLOW_V9_TMPL_SET_ID:PFLOW_V10_TMPL_SET_ID);
146 	pflowif->sc_tmpl.set_header.set_length =
147 	    htons(sizeof(struct pflow_tmpl));
148 
149 	/* v9/v10 IPv4 template */
150 	pflowif->sc_tmpl.ipv4_tmpl.h.tmpl_id = htons(PFLOW_TMPL_IPV4_ID);
151 	pflowif->sc_tmpl.ipv4_tmpl.h.field_count
152 	    = htons(PFLOW_TMPL_IPV4_FIELD_COUNT);
153 	pflowif->sc_tmpl.ipv4_tmpl.src_ip.field_id =
154 	    htons(PFIX_IE_sourceIPv4Address);
155 	pflowif->sc_tmpl.ipv4_tmpl.src_ip.len = htons(4);
156 	pflowif->sc_tmpl.ipv4_tmpl.dest_ip.field_id =
157 	    htons(PFIX_IE_destinationIPv4Address);
158 	pflowif->sc_tmpl.ipv4_tmpl.dest_ip.len = htons(4);
159 	pflowif->sc_tmpl.ipv4_tmpl.packets.field_id =
160 	    htons(PFIX_IE_packetDeltaCount);
161 	pflowif->sc_tmpl.ipv4_tmpl.packets.len = htons(8);
162 	pflowif->sc_tmpl.ipv4_tmpl.octets.field_id =
163 	    htons(PFIX_IE_octetDeltaCount);
164 	pflowif->sc_tmpl.ipv4_tmpl.octets.len = htons(8);
165 	/* keep in sync with SIOCSETPFLOW */
166 	pflowif->sc_tmpl.ipv4_tmpl.start.field_id =
167 	    htons(pflowif->sc_version == PFLOW_PROTO_9?
168 	    PFIX_IE_flowStartSysUpTime:PFIX_IE_flowStartSeconds);
169 	pflowif->sc_tmpl.ipv4_tmpl.start.len = htons(4);
170 	/* keep in sync with SIOCSETPFLOW */
171 	pflowif->sc_tmpl.ipv4_tmpl.finish.field_id =
172 	    htons(pflowif->sc_version == PFLOW_PROTO_9?
173 	    PFIX_IE_flowEndSysUpTime:PFIX_IE_flowEndSeconds);
174 	pflowif->sc_tmpl.ipv4_tmpl.finish.len = htons(4);
175 	pflowif->sc_tmpl.ipv4_tmpl.src_port.field_id =
176 	    htons(PFIX_IE_sourceTransportPort);
177 	pflowif->sc_tmpl.ipv4_tmpl.src_port.len = htons(2);
178 	pflowif->sc_tmpl.ipv4_tmpl.dest_port.field_id =
179 	    htons(PFIX_IE_destinationTransportPort);
180 	pflowif->sc_tmpl.ipv4_tmpl.dest_port.len = htons(2);
181 	pflowif->sc_tmpl.ipv4_tmpl.tos.field_id =
182 	    htons(PFIX_IE_ipClassOfService);
183 	pflowif->sc_tmpl.ipv4_tmpl.tos.len = htons(1);
184 	pflowif->sc_tmpl.ipv4_tmpl.protocol.field_id =
185 	    htons(PFIX_IE_protocolIdentifier);
186 	pflowif->sc_tmpl.ipv4_tmpl.protocol.len = htons(1);
187 
188 	/* v9/v10 IPv6 template */
189 	pflowif->sc_tmpl.ipv6_tmpl.h.tmpl_id = htons(PFLOW_TMPL_IPV6_ID);
190 	pflowif->sc_tmpl.ipv6_tmpl.h.field_count =
191 	    htons(PFLOW_TMPL_IPV6_FIELD_COUNT);
192 	pflowif->sc_tmpl.ipv6_tmpl.src_ip.field_id =
193 	    htons(PFIX_IE_sourceIPv6Address);
194 	pflowif->sc_tmpl.ipv6_tmpl.src_ip.len = htons(16);
195 	pflowif->sc_tmpl.ipv6_tmpl.dest_ip.field_id =
196 	    htons(PFIX_IE_destinationIPv6Address);
197 	pflowif->sc_tmpl.ipv6_tmpl.dest_ip.len = htons(16);
198 	pflowif->sc_tmpl.ipv6_tmpl.packets.field_id =
199 	    htons(PFIX_IE_packetDeltaCount);
200 	pflowif->sc_tmpl.ipv6_tmpl.packets.len = htons(8);
201 	pflowif->sc_tmpl.ipv6_tmpl.octets.field_id =
202 	    htons(PFIX_IE_octetDeltaCount);
203 	pflowif->sc_tmpl.ipv6_tmpl.octets.len = htons(8);
204 	/* keep in sync with SIOCSETPFLOW */
205 	pflowif->sc_tmpl.ipv6_tmpl.start.field_id =
206 	    htons(pflowif->sc_version == PFLOW_PROTO_9?
207 	    PFIX_IE_flowStartSysUpTime:PFIX_IE_flowStartSeconds);
208 	pflowif->sc_tmpl.ipv6_tmpl.start.len = htons(4);
209 	/* keep in sync with SIOCSETPFLOW */
210 	pflowif->sc_tmpl.ipv6_tmpl.finish.field_id =
211 	    htons(pflowif->sc_version == PFLOW_PROTO_9?
212 	    PFIX_IE_flowEndSysUpTime:PFIX_IE_flowEndSeconds);
213 	pflowif->sc_tmpl.ipv6_tmpl.finish.len = htons(4);
214 	pflowif->sc_tmpl.ipv6_tmpl.src_port.field_id =
215 	    htons(PFIX_IE_sourceTransportPort);
216 	pflowif->sc_tmpl.ipv6_tmpl.src_port.len = htons(2);
217 	pflowif->sc_tmpl.ipv6_tmpl.dest_port.field_id =
218 	    htons(PFIX_IE_destinationTransportPort);
219 	pflowif->sc_tmpl.ipv6_tmpl.dest_port.len = htons(2);
220 	pflowif->sc_tmpl.ipv6_tmpl.tos.field_id =
221 	    htons(PFIX_IE_ipClassOfService);
222 	pflowif->sc_tmpl.ipv6_tmpl.tos.len = htons(1);
223 	pflowif->sc_tmpl.ipv6_tmpl.protocol.field_id =
224 	    htons(PFIX_IE_protocolIdentifier);
225 	pflowif->sc_tmpl.ipv6_tmpl.protocol.len = htons(1);
226 
227 	ifp = &pflowif->sc_if;
228 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit);
229 	ifp->if_softc = pflowif;
230 	ifp->if_ioctl = pflowioctl;
231 	ifp->if_output = pflowoutput;
232 	ifp->if_start = pflowstart;
233 	ifp->if_type = IFT_PFLOW;
234 	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
235 	ifp->if_hdrlen = PFLOW_HDRLEN;
236 	ifp->if_flags = IFF_UP;
237 	ifp->if_flags &= ~IFF_RUNNING;	/* not running, need receiver */
238 	pflow_setmtu(pflowif, ETHERMTU);
239 	pflow_init_timeouts(pflowif);
240 	if_attach(ifp);
241 	if_alloc_sadl(ifp);
242 
243 #if NBPFILTER > 0
244 	bpfattach(&pflowif->sc_if.if_bpf, ifp, DLT_RAW, 0);
245 #endif
246 
247 	/* Insert into list of pflows */
248 	SLIST_INSERT_HEAD(&pflowif_list, pflowif, sc_next);
249 	return (0);
250 }
251 
252 int
253 pflow_clone_destroy(struct ifnet *ifp)
254 {
255 	struct pflow_softc	*sc = ifp->if_softc;
256 	int			 s;
257 
258 	s = splnet();
259 	pflow_flush(sc);
260 	if_detach(ifp);
261 	SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
262 	free(sc->sc_imo.imo_membership, M_IPMOPTS);
263 	free(sc, M_DEVBUF);
264 	splx(s);
265 	return (0);
266 }
267 
268 /*
269  * Start output on the pflow interface.
270  */
271 void
272 pflowstart(struct ifnet *ifp)
273 {
274 	struct mbuf	*m;
275 	int		 s;
276 
277 	for (;;) {
278 		s = splnet();
279 		IF_DROP(&ifp->if_snd);
280 		IF_DEQUEUE(&ifp->if_snd, m);
281 		splx(s);
282 
283 		if (m == NULL)
284 			return;
285 		m_freem(m);
286 	}
287 }
288 
289 int
290 pflowoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
291 	struct rtentry *rt)
292 {
293 	m_freem(m);
294 	return (0);
295 }
296 
297 /* ARGSUSED */
298 int
299 pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
300 {
301 	struct proc		*p = curproc;
302 	struct pflow_softc	*sc = ifp->if_softc;
303 	struct ifreq		*ifr = (struct ifreq *)data;
304 	struct pflowreq		 pflowr;
305 	int			 s, error;
306 
307 	switch (cmd) {
308 	case SIOCSIFADDR:
309 	case SIOCAIFADDR:
310 	case SIOCSIFDSTADDR:
311 	case SIOCSIFFLAGS:
312 		if ((ifp->if_flags & IFF_UP) &&
313 		    sc->sc_receiver_ip.s_addr != 0 &&
314 		    sc->sc_receiver_port != 0) {
315 			ifp->if_flags |= IFF_RUNNING;
316 			sc->sc_gcounter=pflowstats.pflow_flows;
317 			/* send templates on startup */
318 			if (sc->sc_version == PFLOW_PROTO_9
319 			    || sc->sc_version == PFLOW_PROTO_10) {
320 				s = splnet();
321 				pflow_sendout_ipfix_tmpl(sc);
322 				splx(s);
323 			}
324 		} else
325 			ifp->if_flags &= ~IFF_RUNNING;
326 		break;
327 	case SIOCSIFMTU:
328 		if (ifr->ifr_mtu < PFLOW_MINMTU)
329 			return (EINVAL);
330 		if (ifr->ifr_mtu > MCLBYTES)
331 			ifr->ifr_mtu = MCLBYTES;
332 		s = splnet();
333 		if (ifr->ifr_mtu < ifp->if_mtu)
334 			pflow_flush(sc);
335 		pflow_setmtu(sc, ifr->ifr_mtu);
336 		splx(s);
337 		break;
338 
339 	case SIOCGETPFLOW:
340 		bzero(&pflowr, sizeof(pflowr));
341 
342 		pflowr.sender_ip = sc->sc_sender_ip;
343 		pflowr.receiver_ip = sc->sc_receiver_ip;
344 		pflowr.receiver_port = sc->sc_receiver_port;
345 		pflowr.version = sc->sc_version;
346 
347 		if ((error = copyout(&pflowr, ifr->ifr_data,
348 		    sizeof(pflowr))))
349 			return (error);
350 		break;
351 
352 	case SIOCSETPFLOW:
353 		if ((error = suser(p, 0)) != 0)
354 			return (error);
355 		if ((error = copyin(ifr->ifr_data, &pflowr,
356 		    sizeof(pflowr))))
357 			return (error);
358 		if (pflowr.addrmask & PFLOW_MASK_VERSION) {
359 			switch(pflowr.version) {
360 			case PFLOW_PROTO_5:
361 			case PFLOW_PROTO_9:
362 			case PFLOW_PROTO_10:
363 				break;
364 			default:
365 				return(EINVAL);
366 			}
367 		}
368 		s = splnet();
369 
370 		pflow_flush(sc);
371 
372 		if (pflowr.addrmask & PFLOW_MASK_DSTIP)
373 			sc->sc_receiver_ip = pflowr.receiver_ip;
374 		if (pflowr.addrmask & PFLOW_MASK_DSTPRT)
375 			sc->sc_receiver_port = pflowr.receiver_port;
376 		if (pflowr.addrmask & PFLOW_MASK_SRCIP)
377 			sc->sc_sender_ip.s_addr = pflowr.sender_ip.s_addr;
378 		/* error check is above */
379 		if (pflowr.addrmask & PFLOW_MASK_VERSION)
380 			sc->sc_version = pflowr.version;
381 
382 		pflow_setmtu(sc, ETHERMTU);
383 		pflow_init_timeouts(sc);
384 
385 		switch (sc->sc_version) {
386 		case PFLOW_PROTO_9:
387 			sc->sc_tmpl.set_header.set_id =
388 			    htons(PFLOW_V9_TMPL_SET_ID);
389 			sc->sc_tmpl.ipv4_tmpl.start.field_id =
390 			    sc->sc_tmpl.ipv6_tmpl.start.field_id =
391 			    htons(PFIX_IE_flowStartSysUpTime);
392 			sc->sc_tmpl.ipv4_tmpl.finish.field_id =
393 			    sc->sc_tmpl.ipv6_tmpl.finish.field_id =
394 			    htons(PFIX_IE_flowEndSysUpTime);
395 			pflow_sendout_ipfix_tmpl(sc);
396 			break;
397 		case PFLOW_PROTO_10:
398 			sc->sc_tmpl.set_header.set_id =
399 			    htons(PFLOW_V10_TMPL_SET_ID);
400 			sc->sc_tmpl.ipv4_tmpl.start.field_id =
401 			    sc->sc_tmpl.ipv6_tmpl.start.field_id =
402 			    htons(PFIX_IE_flowStartSeconds);
403 			sc->sc_tmpl.ipv4_tmpl.finish.field_id =
404 			    sc->sc_tmpl.ipv6_tmpl.finish.field_id =
405 			    htons(PFIX_IE_flowEndSeconds);
406 			pflow_sendout_ipfix_tmpl(sc);
407 			break;
408 		default:
409 			break;
410 		}
411 
412 		splx(s);
413 
414 		if ((ifp->if_flags & IFF_UP) &&
415 		    sc->sc_receiver_ip.s_addr != 0 &&
416 		    sc->sc_receiver_port != 0) {
417 			ifp->if_flags |= IFF_RUNNING;
418 			sc->sc_gcounter=pflowstats.pflow_flows;
419 		} else
420 			ifp->if_flags &= ~IFF_RUNNING;
421 
422 		break;
423 
424 	default:
425 		return (ENOTTY);
426 	}
427 	return (0);
428 }
429 
430 void
431 pflow_init_timeouts(struct pflow_softc *sc)
432 {
433 	switch (sc->sc_version) {
434 	case PFLOW_PROTO_5:
435 		if (timeout_initialized(&sc->sc_tmo6))
436 			timeout_del(&sc->sc_tmo6);
437 		if (timeout_initialized(&sc->sc_tmo_tmpl))
438 			timeout_del(&sc->sc_tmo_tmpl);
439 		if (!timeout_initialized(&sc->sc_tmo))
440 			timeout_set(&sc->sc_tmo, pflow_timeout, sc);
441 		break;
442 	case PFLOW_PROTO_9:
443 	case PFLOW_PROTO_10:
444 		if (!timeout_initialized(&sc->sc_tmo_tmpl))
445 			timeout_set(&sc->sc_tmo_tmpl, pflow_timeout_tmpl, sc);
446 		if (!timeout_initialized(&sc->sc_tmo))
447 			timeout_set(&sc->sc_tmo, pflow_timeout, sc);
448 		if (!timeout_initialized(&sc->sc_tmo6))
449 			timeout_set(&sc->sc_tmo6, pflow_timeout6, sc);
450 
451 		timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
452 		break;
453 	default: /* NOTREACHED */
454 		break;
455 	}
456 }
457 
458 int
459 pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz)
460 {
461 	sc->sc_maxcount4 = (mtu - hdrsz -
462 	    sizeof(struct udpiphdr)) / sizeof(struct pflow_flow4);
463 	if (sc->sc_maxcount4 > PFLOW_MAXFLOWS)
464 		sc->sc_maxcount4 = PFLOW_MAXFLOWS;
465 	sc->sc_maxcount6 = (mtu - hdrsz -
466 	    sizeof(struct udpiphdr)) / sizeof(struct pflow_flow6);
467 	if (sc->sc_maxcount6 > PFLOW_MAXFLOWS)
468 		sc->sc_maxcount6 = PFLOW_MAXFLOWS;
469 
470 	return (hdrsz + sizeof(struct udpiphdr) +
471 	    MIN(sc->sc_maxcount4 * sizeof(struct pflow_flow4),
472 	    sc->sc_maxcount6 * sizeof(struct pflow_flow6)));
473 }
474 
475 void
476 pflow_setmtu(struct pflow_softc *sc, int mtu_req)
477 {
478 	int	mtu;
479 
480 	if (sc->sc_pflow_ifp && sc->sc_pflow_ifp->if_mtu < mtu_req)
481 		mtu = sc->sc_pflow_ifp->if_mtu;
482 	else
483 		mtu = mtu_req;
484 
485 	switch (sc->sc_version) {
486 	case PFLOW_PROTO_5:
487 		sc->sc_maxcount = (mtu - sizeof(struct pflow_header) -
488 		    sizeof(struct udpiphdr)) / sizeof(struct pflow_flow);
489 		if (sc->sc_maxcount > PFLOW_MAXFLOWS)
490 		    sc->sc_maxcount = PFLOW_MAXFLOWS;
491 		sc->sc_if.if_mtu = sizeof(struct pflow_header) +
492 		    sizeof(struct udpiphdr) +
493 		    sc->sc_maxcount * sizeof(struct pflow_flow);
494 		break;
495 	case PFLOW_PROTO_9:
496 		sc->sc_if.if_mtu =
497 		    pflow_calc_mtu(sc, mtu, sizeof(struct pflow_v9_header));
498 		break;
499 	case PFLOW_PROTO_10:
500 		sc->sc_if.if_mtu =
501 		    pflow_calc_mtu(sc, mtu, sizeof(struct pflow_v10_header));
502 		break;
503 	default: /* NOTREACHED */
504 		break;
505 	}
506 }
507 
508 struct mbuf *
509 pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id)
510 {
511 	struct pflow_set_header	 set_hdr;
512 	struct pflow_header	 h;
513 	struct mbuf		*m;
514 
515 	MGETHDR(m, M_DONTWAIT, MT_DATA);
516 	if (m == NULL) {
517 		pflowstats.pflow_onomem++;
518 		return (NULL);
519 	}
520 
521 	MCLGET(m, M_DONTWAIT);
522 	if ((m->m_flags & M_EXT) == 0) {
523 		m_free(m);
524 		pflowstats.pflow_onomem++;
525 		return (NULL);
526 	}
527 
528 	m->m_len = m->m_pkthdr.len = 0;
529 	m->m_pkthdr.rcvif = NULL;
530 
531 	if (sc == NULL)		/* get only a new empty mbuf */
532 		return (m);
533 
534 	if (sc->sc_version == PFLOW_PROTO_5) {
535 		/* populate pflow_header */
536 		h.reserved1 = 0;
537 		h.reserved2 = 0;
538 		h.count = 0;
539 		h.version = htons(PFLOW_PROTO_5);
540 		h.flow_sequence = htonl(sc->sc_gcounter);
541 		h.engine_type = PFLOW_ENGINE_TYPE;
542 		h.engine_id = PFLOW_ENGINE_ID;
543 		m_copyback(m, 0, PFLOW_HDRLEN, &h, M_NOWAIT);
544 
545 		sc->sc_count = 0;
546 		timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
547 	} else {
548 		/* populate pflow_set_header */
549 		set_hdr.set_length = 0;
550 		set_hdr.set_id = htons(set_id);
551 		m_copyback(m, 0, PFLOW_SET_HDRLEN, &set_hdr, M_NOWAIT);
552 	}
553 
554 	return (m);
555 }
556 
557 void
558 copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
559     struct pf_state *st, int src, int dst)
560 {
561 	struct pf_state_key	*sk = st->key[PF_SK_WIRE];
562 
563 	flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
564 	flow1->src_port = flow2->dest_port = sk->port[src];
565 	flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
566 	flow1->dest_port = flow2->src_port = sk->port[dst];
567 
568 	flow1->dest_as = flow2->src_as =
569 	    flow1->src_as = flow2->dest_as = 0;
570 	flow1->if_index_out = flow2->if_index_in =
571 	    flow1->if_index_in = flow2->if_index_out = 0;
572 	flow1->dest_mask = flow2->src_mask =
573 	    flow1->src_mask = flow2->dest_mask = 0;
574 
575 	flow1->flow_packets = htonl(st->packets[0]);
576 	flow2->flow_packets = htonl(st->packets[1]);
577 	flow1->flow_octets = htonl(st->bytes[0]);
578 	flow2->flow_octets = htonl(st->bytes[1]);
579 
580 	/*
581 	 * Pretend the flow was created or expired when the machine came up
582 	 * when creation is in the future of the last time a package was seen
583 	 * or was created / expired before this machine came up due to pfsync.
584 	 */
585 	flow1->flow_start = flow2->flow_start = st->creation < 0 ||
586 	    st->creation > st->expire ? htonl(0) : htonl(st->creation * 1000);
587 	flow1->flow_finish = flow2->flow_finish = st->expire < 0 ? htonl(0) :
588 	    htonl(st->expire * 1000);
589 	flow1->tcp_flags = flow2->tcp_flags = 0;
590 	flow1->protocol = flow2->protocol = sk->proto;
591 	flow1->tos = flow2->tos = st->rule.ptr->tos;
592 }
593 
594 void
595 copy_flow4_data(struct pflow_flow4 *flow1, struct pflow_flow4 *flow2,
596     struct pf_state *st, struct pflow_softc *sc, int src, int dst)
597 {
598 	struct pf_state_key	*sk = st->key[PF_SK_WIRE];
599 
600 	flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
601 	flow1->src_port = flow2->dest_port = sk->port[src];
602 	flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
603 	flow1->dest_port = flow2->src_port = sk->port[dst];
604 
605 	flow1->flow_packets = htobe64(st->packets[0]);
606 	flow2->flow_packets = htobe64(st->packets[1]);
607 	flow1->flow_octets = htobe64(st->bytes[0]);
608 	flow2->flow_octets = htobe64(st->bytes[1]);
609 
610 	switch (sc->sc_version) {
611 	case PFLOW_PROTO_9:
612 		/*
613 		 * Pretend the flow was created or expired when the machine came
614 		 * up when creation is in the future of the last time a package
615 		 * was seen or was created / expired before this machine came up
616 		 * due to pfsync.
617 		 */
618 		flow1->flow_start = flow2->flow_start = st->creation < 0 ||
619 		    st->creation > st->expire ? htonl(0) : htonl(st->creation *
620 		    1000);
621 		flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
622 		    htonl(0) : htonl(st->expire * 1000);
623 		break;
624 	case PFLOW_PROTO_10:
625 		flow1->flow_start = flow2->flow_start = htonl(time_second -
626 		    (time_uptime - st->creation));
627 		flow1->flow_finish = flow2->flow_finish = htonl(time_second -
628 		    (time_uptime - st->expire));
629 		break;
630 	default: /* NOTREACHED */
631 		break;
632 	}
633 
634 	flow1->protocol = flow2->protocol = sk->proto;
635 	flow1->tos = flow2->tos = st->rule.ptr->tos;
636 }
637 
638 void
639 copy_flow6_data(struct pflow_flow6 *flow1, struct pflow_flow6 *flow2,
640     struct pf_state *st, struct pflow_softc *sc, int src, int dst)
641 {
642 	struct pf_state_key	*sk = st->key[PF_SK_WIRE];
643 	bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip));
644 	bcopy(&sk->addr[src].v6, &flow2->dest_ip, sizeof(flow2->dest_ip));
645 	flow1->src_port = flow2->dest_port = sk->port[src];
646 	bcopy(&sk->addr[dst].v6, &flow1->dest_ip, sizeof(flow1->dest_ip));
647 	bcopy(&sk->addr[dst].v6, &flow2->src_ip, sizeof(flow2->src_ip));
648 	flow1->dest_port = flow2->src_port = sk->port[dst];
649 
650 	flow1->flow_packets = htobe64(st->packets[0]);
651 	flow2->flow_packets = htobe64(st->packets[1]);
652 	flow1->flow_octets = htobe64(st->bytes[0]);
653 	flow2->flow_octets = htobe64(st->bytes[1]);
654 
655 	switch (sc->sc_version) {
656 	case PFLOW_PROTO_9:
657 		/*
658 		 * Pretend the flow was created or expired when the machine came
659 		 * up when creation is in the future of the last time a package
660 		 * was seen or was created / expired before this machine came up
661 		 * due to pfsync.
662 		 */
663 		flow1->flow_start = flow2->flow_start = st->creation < 0 ||
664 		    st->creation > st->expire ? htonl(0) : htonl(st->creation *
665 		    1000);
666 		flow1->flow_finish = flow2->flow_finish = st->expire < 0 ?
667 		    htonl(0) : htonl(st->expire * 1000);
668 		break;
669 	case PFLOW_PROTO_10:
670 		flow1->flow_start = flow2->flow_start = htonl(time_second -
671 		    (time_uptime - st->creation));
672 		flow1->flow_finish = flow2->flow_finish = htonl(time_second -
673 		    (time_uptime - st->expire));
674 		break;
675 	default: /* NOTREACHED */
676 		break;
677 	}
678 
679 	flow1->protocol = flow2->protocol = sk->proto;
680 	flow1->tos = flow2->tos = st->rule.ptr->tos;
681 }
682 
683 int
684 export_pflow(struct pf_state *st)
685 {
686 	struct pflow_softc	*sc = NULL;
687 	struct pf_state_key	*sk = st->key[PF_SK_WIRE];
688 
689 	SLIST_FOREACH(sc, &pflowif_list, sc_next) {
690 		switch (sc->sc_version) {
691 		case PFLOW_PROTO_5:
692 			if( sk->af == AF_INET )
693 				export_pflow_if(st, sc);
694 			break;
695 		case PFLOW_PROTO_9:
696 			/* ... fall through ... */
697 		case PFLOW_PROTO_10:
698 			if( sk->af == AF_INET || sk->af == AF_INET6 )
699 				export_pflow_if(st, sc);
700 			break;
701 		default: /* NOTREACHED */
702 			break;
703 		}
704 	}
705 
706 	return (0);
707 }
708 
709 int
710 export_pflow_if(struct pf_state *st, struct pflow_softc *sc)
711 {
712 	struct pf_state		 pfs_copy;
713 	struct ifnet		*ifp = &sc->sc_if;
714 	u_int64_t		 bytes[2];
715 	int			 ret = 0;
716 
717 	if (!(ifp->if_flags & IFF_RUNNING))
718 		return (0);
719 
720 	if (sc->sc_version == PFLOW_PROTO_9 || sc->sc_version == PFLOW_PROTO_10)
721 		return (pflow_pack_flow_ipfix(st, sc));
722 
723 	/* PFLOW_PROTO_5 */
724 	if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES)
725 	    && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES))
726 		return (pflow_pack_flow(st, sc));
727 
728 	/* flow > PFLOW_MAXBYTES need special handling */
729 	bcopy(st, &pfs_copy, sizeof(pfs_copy));
730 	bytes[0] = pfs_copy.bytes[0];
731 	bytes[1] = pfs_copy.bytes[1];
732 
733 	while (bytes[0] > PFLOW_MAXBYTES) {
734 		pfs_copy.bytes[0] = PFLOW_MAXBYTES;
735 		pfs_copy.bytes[1] = 0;
736 
737 		if ((ret = pflow_pack_flow(&pfs_copy, sc)) != 0)
738 			return (ret);
739 		if ((bytes[0] - PFLOW_MAXBYTES) > 0)
740 			bytes[0] -= PFLOW_MAXBYTES;
741 	}
742 
743 	while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) {
744 		pfs_copy.bytes[1] = PFLOW_MAXBYTES;
745 		pfs_copy.bytes[0] = 0;
746 
747 		if ((ret = pflow_pack_flow(&pfs_copy, sc)) != 0)
748 			return (ret);
749 		if ((bytes[1] - PFLOW_MAXBYTES) > 0)
750 			bytes[1] -= PFLOW_MAXBYTES;
751 	}
752 
753 	pfs_copy.bytes[0] = bytes[0];
754 	pfs_copy.bytes[1] = bytes[1];
755 
756 	return (pflow_pack_flow(&pfs_copy, sc));
757 }
758 
759 int
760 copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc)
761 {
762 	int		s, ret = 0;
763 
764 	s = splnet();
765 	if (sc->sc_mbuf == NULL) {
766 		if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0)) == NULL) {
767 			splx(s);
768 			return (ENOBUFS);
769 		}
770 	}
771 	m_copyback(sc->sc_mbuf, PFLOW_HDRLEN +
772 	    (sc->sc_count * sizeof(struct pflow_flow)),
773 	    sizeof(struct pflow_flow), flow, M_NOWAIT);
774 
775 	if (pflowstats.pflow_flows == sc->sc_gcounter)
776 		pflowstats.pflow_flows++;
777 	sc->sc_gcounter++;
778 	sc->sc_count++;
779 
780 	if (sc->sc_count >= sc->sc_maxcount)
781 		ret = pflow_sendout_v5(sc);
782 
783 	splx(s);
784 	return(ret);
785 }
786 
787 int
788 copy_flow4_to_m(struct pflow_flow4 *flow, struct pflow_softc *sc)
789 {
790 	int		s, ret = 0;
791 
792 	s = splnet();
793 	if (sc->sc_mbuf == NULL) {
794 		if ((sc->sc_mbuf =
795 		    pflow_get_mbuf(sc, PFLOW_TMPL_IPV4_ID)) == NULL) {
796 			splx(s);
797 			return (ENOBUFS);
798 		}
799 		sc->sc_count4 = 0;
800 		timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
801 	}
802 	m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN +
803 	    (sc->sc_count4 * sizeof(struct pflow_flow4)),
804 	    sizeof(struct pflow_flow4), flow, M_NOWAIT);
805 
806 	if (pflowstats.pflow_flows == sc->sc_gcounter)
807 		pflowstats.pflow_flows++;
808 	sc->sc_gcounter++;
809 	sc->sc_count4++;
810 
811 	if (sc->sc_count4 >= sc->sc_maxcount4)
812 		ret = pflow_sendout_ipfix(sc, AF_INET);
813 	splx(s);
814 	return(ret);
815 }
816 
817 int
818 copy_flow6_to_m(struct pflow_flow6 *flow, struct pflow_softc *sc)
819 {
820 	int		s, ret = 0;
821 
822 	s = splnet();
823 	if (sc->sc_mbuf6 == NULL) {
824 		if ((sc->sc_mbuf6 =
825 		    pflow_get_mbuf(sc, PFLOW_TMPL_IPV6_ID)) == NULL) {
826 			splx(s);
827 			return (ENOBUFS);
828 		}
829 		sc->sc_count6 = 0;
830 		timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT);
831 	}
832 	m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN +
833 	    (sc->sc_count6 * sizeof(struct pflow_flow6)),
834 	    sizeof(struct pflow_flow6), flow, M_NOWAIT);
835 
836 	if (pflowstats.pflow_flows == sc->sc_gcounter)
837 		pflowstats.pflow_flows++;
838 	sc->sc_gcounter++;
839 	sc->sc_count6++;
840 
841 	if (sc->sc_count6 >= sc->sc_maxcount6)
842 		ret = pflow_sendout_ipfix(sc, AF_INET6);
843 
844 	splx(s);
845 	return(ret);
846 }
847 
848 int
849 pflow_pack_flow(struct pf_state *st, struct pflow_softc *sc)
850 {
851 	struct pflow_flow	 flow1;
852 	struct pflow_flow	 flow2;
853 	int			 ret = 0;
854 
855 	bzero(&flow1, sizeof(flow1));
856 	bzero(&flow2, sizeof(flow2));
857 
858 	if (st->direction == PF_OUT)
859 		copy_flow_data(&flow1, &flow2, st, 1, 0);
860 	else
861 		copy_flow_data(&flow1, &flow2, st, 0, 1);
862 
863 	if (st->bytes[0] != 0) /* first flow from state */
864 		ret = copy_flow_to_m(&flow1, sc);
865 
866 	if (st->bytes[1] != 0) /* second flow from state */
867 		ret = copy_flow_to_m(&flow2, sc);
868 
869 	return (ret);
870 }
871 
872 int
873 pflow_pack_flow_ipfix(struct pf_state *st, struct pflow_softc *sc)
874 {
875 	struct pf_state_key	*sk = st->key[PF_SK_WIRE];
876 	struct pflow_flow4	 flow4_1, flow4_2;
877 	struct pflow_flow6	 flow6_1, flow6_2;
878 	int			 ret = 0;
879 	if (sk->af == AF_INET) {
880 		bzero(&flow4_1, sizeof(flow4_1));
881 		bzero(&flow4_2, sizeof(flow4_2));
882 
883 		if (st->direction == PF_OUT)
884 			copy_flow4_data(&flow4_1, &flow4_2, st, sc, 1, 0);
885 		else
886 			copy_flow4_data(&flow4_1, &flow4_2, st, sc, 0, 1);
887 
888 		if (st->bytes[0] != 0) /* first flow from state */
889 			ret = copy_flow4_to_m(&flow4_1, sc);
890 
891 		if (st->bytes[1] != 0) /* second flow from state */
892 			ret = copy_flow4_to_m(&flow4_2, sc);
893 	} else if (sk->af == AF_INET6) {
894 		bzero(&flow6_1, sizeof(flow6_1));
895 		bzero(&flow6_2, sizeof(flow6_2));
896 
897 		if (st->direction == PF_OUT)
898 			copy_flow6_data(&flow6_1, &flow6_2, st, sc, 1, 0);
899 		else
900 			copy_flow6_data(&flow6_1, &flow6_2, st, sc, 0, 1);
901 
902 		if (st->bytes[0] != 0) /* first flow from state */
903 			ret = copy_flow6_to_m(&flow6_1, sc);
904 
905 		if (st->bytes[1] != 0) /* second flow from state */
906 			ret = copy_flow6_to_m(&flow6_2, sc);
907 	}
908 	return (ret);
909 }
910 
911 void
912 pflow_timeout(void *v)
913 {
914 	struct pflow_softc	*sc = v;
915 	int			 s;
916 
917 	s = splnet();
918 	switch (sc->sc_version) {
919 	case PFLOW_PROTO_5:
920 		pflow_sendout_v5(sc);
921 		break;
922 	case PFLOW_PROTO_9:
923 		/* ... fall through ... */
924 	case PFLOW_PROTO_10:
925 		pflow_sendout_ipfix(sc, AF_INET);
926 	default: /* NOTREACHED */
927 		break;
928 	}
929 	splx(s);
930 }
931 
932 void
933 pflow_timeout6(void *v)
934 {
935 	struct pflow_softc	*sc = v;
936 	int			 s;
937 
938 	s = splnet();
939 	pflow_sendout_ipfix(sc, AF_INET6);
940 	splx(s);
941 }
942 
943 void
944 pflow_timeout_tmpl(void *v)
945 {
946 	struct pflow_softc	*sc = v;
947 	int			 s;
948 
949 	s = splnet();
950 	pflow_sendout_ipfix_tmpl(sc);
951 	splx(s);
952 }
953 
954 /* This must be called in splnet() */
955 void
956 pflow_flush(struct pflow_softc *sc)
957 {
958 	switch (sc->sc_version) {
959 	case PFLOW_PROTO_5:
960 		pflow_sendout_v5(sc);
961 		break;
962 	case PFLOW_PROTO_9:
963 	case PFLOW_PROTO_10:
964 		pflow_sendout_ipfix(sc, AF_INET);
965 		pflow_sendout_ipfix(sc, AF_INET6);
966 		break;
967 	default: /* NOTREACHED */
968 		break;
969 	}
970 }
971 
972 
973 /* This must be called in splnet() */
974 int
975 pflow_sendout_v5(struct pflow_softc *sc)
976 {
977 	struct mbuf		*m = sc->sc_mbuf;
978 	struct pflow_header	*h;
979 	struct ifnet		*ifp = &sc->sc_if;
980 	struct timespec		tv;
981 
982 	timeout_del(&sc->sc_tmo);
983 
984 	if (m == NULL)
985 		return (0);
986 
987 	sc->sc_mbuf = NULL;
988 	if (!(ifp->if_flags & IFF_RUNNING)) {
989 		m_freem(m);
990 		return (0);
991 	}
992 
993 	pflowstats.pflow_packets++;
994 	h = mtod(m, struct pflow_header *);
995 	h->count = htons(sc->sc_count);
996 
997 	/* populate pflow_header */
998 	h->uptime_ms = htonl(time_uptime * 1000);
999 
1000 	getnanotime(&tv);
1001 	h->time_sec = htonl(tv.tv_sec);
1002 	h->time_nanosec = htonl(tv.tv_nsec);
1003 
1004 	return (pflow_sendout_mbuf(sc, m));
1005 }
1006 
1007 /* This must be called in splnet() */
1008 int
1009 pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
1010 {
1011 	struct mbuf			*m;
1012 	struct pflow_v9_header		*h9;
1013 	struct pflow_v10_header		*h10;
1014 	struct pflow_set_header		*set_hdr;
1015 	struct ifnet			*ifp = &sc->sc_if;
1016 	int				 set_length;
1017 
1018 	switch (af) {
1019 	case AF_INET:
1020 		m = sc->sc_mbuf;
1021 		timeout_del(&sc->sc_tmo);
1022 		if (m == NULL)
1023 			return (0);
1024 		sc->sc_mbuf = NULL;
1025 		break;
1026 	case AF_INET6:
1027 		m = sc->sc_mbuf6;
1028 		timeout_del(&sc->sc_tmo6);
1029 		if (m == NULL)
1030 			return (0);
1031 		sc->sc_mbuf6 = NULL;
1032 		break;
1033 	default: /* NOTREACHED */
1034 		break;
1035 	}
1036 
1037 	if (!(ifp->if_flags & IFF_RUNNING)) {
1038 		m_freem(m);
1039 		return (0);
1040 	}
1041 
1042 	pflowstats.pflow_packets++;
1043 	set_hdr = mtod(m, struct pflow_set_header *);
1044 	switch (af) {
1045 	case AF_INET:
1046 		set_length = sizeof(struct pflow_set_header)
1047 		    + sc->sc_count4 * sizeof(struct pflow_flow4);
1048 		break;
1049 	case AF_INET6:
1050 		set_length = sizeof(struct pflow_set_header)
1051 		    + sc->sc_count6 * sizeof(struct pflow_flow6);
1052 		break;
1053 	default: /* NOTREACHED */
1054 		break;
1055 	}
1056 	set_hdr->set_length = htons(set_length);
1057 
1058 	switch (sc->sc_version) {
1059 	case PFLOW_PROTO_9:
1060 		/* populate pflow_header */
1061 		M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
1062 		if (m == NULL) {
1063 			pflowstats.pflow_onomem++;
1064 			return (ENOBUFS);
1065 		}
1066 		h9 = mtod(m, struct pflow_v9_header *);
1067 		h9->version = htons(PFLOW_PROTO_9);
1068 		h9->count = htons(1);
1069 		h9->uptime_ms = htonl(time_uptime * 1000);
1070 		h9->time_sec = htonl(time_second);
1071 		/* XXX correct mod 2^32 semantics? */
1072 		h9->flow_sequence = htonl(sc->sc_gcounter);
1073 		h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1074 		break;
1075 	case PFLOW_PROTO_10:
1076 		/* populate pflow_header */
1077 		M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
1078 		if (m == NULL) {
1079 			pflowstats.pflow_onomem++;
1080 			return (ENOBUFS);
1081 		}
1082 		h10 = mtod(m, struct pflow_v10_header *);
1083 		h10->version = htons(PFLOW_PROTO_10);
1084 		h10->length = htons(PFLOW_V10_HDRLEN + set_length);
1085 		h10->time_sec = htonl(time_second);
1086 		/* XXX correct mod 2^32 semantics? */
1087 		h10->flow_sequence = htonl(sc->sc_gcounter);
1088 		h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1089 		break;
1090 	default: /* NOTREACHED */
1091 		break;
1092 	}
1093 	return (pflow_sendout_mbuf(sc, m));
1094 }
1095 
1096 /* This must be called in splnet() */
1097 int
1098 pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
1099 {
1100 	struct mbuf			*m;
1101 	struct pflow_v9_header		*h9;
1102 	struct pflow_v10_header		*h10;
1103 	struct ifnet			*ifp = &sc->sc_if;
1104 
1105 	timeout_del(&sc->sc_tmo_tmpl);
1106 
1107 	if (!(ifp->if_flags & IFF_RUNNING)) {
1108 		return (0);
1109 	}
1110 	m = pflow_get_mbuf(NULL, 0);
1111 	if (m == NULL)
1112 		return (0);
1113 	if (m_copyback(m, 0, sizeof(struct pflow_tmpl),
1114 	    &sc->sc_tmpl, M_NOWAIT)) {
1115 		m_freem(m);
1116 		return (0);
1117 	}
1118 	pflowstats.pflow_packets++;
1119 	switch (sc->sc_version) {
1120 	case PFLOW_PROTO_9:
1121 		/* populate pflow_header */
1122 		M_PREPEND(m, sizeof(struct pflow_v9_header), M_DONTWAIT);
1123 		if (m == NULL) {
1124 			pflowstats.pflow_onomem++;
1125 			return (ENOBUFS);
1126 		}
1127 		h9 = mtod(m, struct pflow_v9_header *);
1128 		h9->version = htons(PFLOW_PROTO_9);
1129 		h9->count = htons(1);
1130 	        h9->uptime_ms = htonl(time_uptime * 1000);
1131 		h9->time_sec = htonl(time_second);
1132 		/* XXX correct mod 2^32 semantics? */
1133 		h9->flow_sequence = htonl(sc->sc_gcounter);
1134 		h9->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1135 		break;
1136 	case PFLOW_PROTO_10:
1137 		/* populate pflow_header */
1138 		M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
1139 		if (m == NULL) {
1140 			pflowstats.pflow_onomem++;
1141 			return (ENOBUFS);
1142 		}
1143 		h10 = mtod(m, struct pflow_v10_header *);
1144 		h10->version = htons(PFLOW_PROTO_10);
1145 		h10->length = htons(PFLOW_V10_HDRLEN
1146 		    + sizeof(struct pflow_tmpl));
1147 		h10->time_sec = htonl(time_second);
1148 		/* XXX correct mod 2^32 semantics? */
1149 		h10->flow_sequence = htonl(sc->sc_gcounter);
1150 		h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
1151 		break;
1152 	default: /* NOTREACHED */
1153 		break;
1154 	}
1155 	timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
1156 	return (pflow_sendout_mbuf(sc, m));
1157 }
1158 
1159 int
1160 pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m)
1161 {
1162 	struct udpiphdr	*ui;
1163 	u_int16_t	 len = m->m_pkthdr.len;
1164 #if NBPFILTER > 0
1165 	struct ifnet	*ifp = &sc->sc_if;
1166 #endif
1167 	struct ip	*ip;
1168 	int		 err;
1169 
1170 	/* UDP Header*/
1171 	M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1172 	if (m == NULL) {
1173 		pflowstats.pflow_onomem++;
1174 		return (ENOBUFS);
1175 	}
1176 
1177 	ui = mtod(m, struct udpiphdr *);
1178 	ui->ui_pr = IPPROTO_UDP;
1179 	ui->ui_src = sc->sc_sender_ip;
1180 	ui->ui_sport = sc->sc_sender_port;
1181 	ui->ui_dst = sc->sc_receiver_ip;
1182 	ui->ui_dport = sc->sc_receiver_port;
1183 	ui->ui_ulen = htons(sizeof(struct udphdr) + len);
1184 
1185 	ip = (struct ip *)ui;
1186 	ip->ip_v = IPVERSION;
1187 	ip->ip_hl = sizeof(struct ip) >> 2;
1188 	ip->ip_id = htons(ip_randomid());
1189 	ip->ip_off = htons(IP_DF);
1190 	ip->ip_tos = IPTOS_LOWDELAY;
1191 	ip->ip_ttl = IPDEFTTL;
1192 	ip->ip_len = htons(sizeof(struct udpiphdr) + len);
1193 
1194 	/*
1195 	 * Compute the pseudo-header checksum; defer further checksumming
1196 	 * until ip_output() or hardware (if it exists).
1197 	 */
1198 	if (udpcksum) {
1199 		m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1200 		ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
1201 		    ui->ui_dst.s_addr, htons(len + sizeof(struct udphdr) +
1202 		    IPPROTO_UDP));
1203 	} else
1204 		ui->ui_sum = 0;
1205 
1206 #if NBPFILTER > 0
1207 	if (ifp->if_bpf) {
1208 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
1209 		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1210 	}
1211 #endif
1212 
1213 	sc->sc_if.if_opackets++;
1214 	sc->sc_if.if_obytes += m->m_pkthdr.len;
1215 
1216 	if ((err = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))) {
1217 		pflowstats.pflow_oerrors++;
1218 		sc->sc_if.if_oerrors++;
1219 	}
1220 	return (err);
1221 }
1222 
1223 int
1224 pflow_get_dynport(void)
1225 {
1226 	u_int16_t	tmp, low, high, cut;
1227 
1228 	low = ipport_hifirstauto;     /* sysctl */
1229 	high = ipport_hilastauto;
1230 
1231 	cut = arc4random_uniform(1 + high - low) + low;
1232 
1233 	for (tmp = cut; tmp <= high; ++(tmp)) {
1234 		if (!in_baddynamic(tmp, IPPROTO_UDP))
1235 			return (htons(tmp));
1236 	}
1237 
1238 	for (tmp = cut - 1; tmp >= low; --(tmp)) {
1239 		if (!in_baddynamic(tmp, IPPROTO_UDP))
1240 			return (htons(tmp));
1241 	}
1242 
1243 	return (htons(ipport_hilastauto)); /* XXX */
1244 }
1245 
1246 int
1247 pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1248     void *newp, size_t newlen)
1249 {
1250 	if (namelen != 1)
1251 		return (ENOTDIR);
1252 
1253 	switch (name[0]) {
1254 	case NET_PFLOW_STATS:
1255 		if (newp != NULL)
1256 			return (EPERM);
1257 		return (sysctl_struct(oldp, oldlenp, newp, newlen,
1258 		    &pflowstats, sizeof(pflowstats)));
1259 	default:
1260 		return (EOPNOTSUPP);
1261 	}
1262 	return (0);
1263 }
1264