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