The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_pflow.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.