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