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