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