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