if_pflow.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. /* $OpenBSD: if_pflow.c,v 1.55 2015/07/21 03:03:10 florian Exp $ */
  2. /*
  3. * Copyright (c) 2011 Florian Obser <florian@narrans.de>
  4. * Copyright (c) 2011 Sebastian Benoit <benoit-lists@fb12.de>
  5. * Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
  6. * Copyright (c) 2008 Joerg Goltermann <jg@osn.de>
  7. *
  8. * Permission to use, copy, modify, and distribute this software for any
  9. * purpose with or without fee is hereby granted, provided that the above
  10. * copyright notice and this permission notice appear in all copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
  17. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  18. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19. */
  20. #include <sys/types.h>
  21. #include <sys/malloc.h>
  22. #include <sys/param.h>
  23. #include <sys/systm.h>
  24. #include <sys/mbuf.h>
  25. #include <sys/socket.h>
  26. #include <sys/timeout.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/kernel.h>
  29. #include <sys/socket.h>
  30. #include <sys/socketvar.h>
  31. #include <sys/sysctl.h>
  32. #include <net/if.h>
  33. #include <net/if_types.h>
  34. #include <net/bpf.h>
  35. #include <net/route.h>
  36. #include <netinet/in.h>
  37. #include <netinet/if_ether.h>
  38. #include <netinet/tcp.h>
  39. #include <netinet/ip.h>
  40. #include <netinet/ip_var.h>
  41. #include <netinet/udp.h>
  42. #include <netinet/udp_var.h>
  43. #include <netinet/in_pcb.h>
  44. #include <net/pfvar.h>
  45. #include <net/if_pflow.h>
  46. #include "bpfilter.h"
  47. #include "pflow.h"
  48. #define PFLOW_MINMTU \
  49. (sizeof(struct pflow_header) + sizeof(struct pflow_flow))
  50. #ifdef PFLOWDEBUG
  51. #define DPRINTF(x) do { printf x ; } while (0)
  52. #else
  53. #define DPRINTF(x)
  54. #endif
  55. SLIST_HEAD(, pflow_softc) pflowif_list;
  56. struct pflowstats pflowstats;
  57. void pflowattach(int);
  58. int pflow_clone_create(struct if_clone *, int);
  59. int pflow_clone_destroy(struct ifnet *);
  60. void pflow_init_timeouts(struct pflow_softc *);
  61. int pflow_calc_mtu(struct pflow_softc *, int, int);
  62. void pflow_setmtu(struct pflow_softc *, int);
  63. int pflowioctl(struct ifnet *, u_long, caddr_t);
  64. struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t);
  65. void pflow_flush(struct pflow_softc *);
  66. int pflow_sendout_v5(struct pflow_softc *);
  67. int pflow_sendout_ipfix(struct pflow_softc *, sa_family_t);
  68. int pflow_sendout_ipfix_tmpl(struct pflow_softc *);
  69. int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *);
  70. void pflow_timeout(void *);
  71. void pflow_timeout6(void *);
  72. void pflow_timeout_tmpl(void *);
  73. void copy_flow_data(struct pflow_flow *, struct pflow_flow *,
  74. struct pf_state *, struct pf_state_key *, int, int);
  75. void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *,
  76. struct pflow_ipfix_flow4 *, struct pf_state *, struct pf_state_key *,
  77. struct pflow_softc *, int, int);
  78. void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *,
  79. struct pflow_ipfix_flow6 *, struct pf_state *, struct pf_state_key *,
  80. struct pflow_softc *, int, int);
  81. int pflow_pack_flow(struct pf_state *, struct pf_state_key *,
  82. struct pflow_softc *);
  83. int pflow_pack_flow_ipfix(struct pf_state *, struct pf_state_key *,
  84. struct pflow_softc *);
  85. int export_pflow_if(struct pf_state*, struct pf_state_key *,
  86. struct pflow_softc *);
  87. int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc);
  88. int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow,
  89. struct pflow_softc *sc);
  90. int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow,
  91. struct pflow_softc *sc);
  92. struct if_clone pflow_cloner =
  93. IF_CLONE_INITIALIZER("pflow", pflow_clone_create,
  94. pflow_clone_destroy);
  95. void
  96. pflowattach(int npflow)
  97. {
  98. SLIST_INIT(&pflowif_list);
  99. if_clone_attach(&pflow_cloner);
  100. }
  101. int
  102. pflow_clone_create(struct if_clone *ifc, int unit)
  103. {
  104. struct ifnet *ifp;
  105. struct pflow_softc *pflowif;
  106. struct socket *so;
  107. struct sockaddr_in *sin;
  108. struct mbuf *m;
  109. int error;
  110. error = socreate(AF_INET, &so, SOCK_DGRAM, 0);
  111. if (error)
  112. return (error);
  113. MGET(m, M_WAIT, MT_SONAME);
  114. sin = mtod(m, struct sockaddr_in *);
  115. memset(sin, 0 , sizeof(*sin));
  116. sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
  117. sin->sin_family = AF_INET;
  118. sin->sin_addr.s_addr = INADDR_ANY;
  119. sin->sin_port = htons(0);
  120. error = sobind(so, m, curproc);
  121. m_freem(m);
  122. if (error) {
  123. soclose(so);
  124. return (error);
  125. }
  126. if ((pflowif = malloc(sizeof(*pflowif),
  127. M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
  128. soclose(so);
  129. return (ENOMEM);
  130. }
  131. pflowif->so = so;
  132. MGET(pflowif->send_nam, M_WAIT, MT_SONAME);
  133. sin = mtod(pflowif->send_nam, struct sockaddr_in *);
  134. memset(sin, 0 , sizeof(*sin));
  135. sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
  136. sin->sin_family = AF_INET;
  137. sin->sin_addr.s_addr = INADDR_ANY;
  138. sin->sin_port = 0;
  139. pflowif->sc_receiver_ip.s_addr = INADDR_ANY;
  140. pflowif->sc_receiver_port = 0;
  141. pflowif->sc_sender_ip.s_addr = INADDR_ANY;
  142. pflowif->sc_version = PFLOW_PROTO_DEFAULT;
  143. /* ipfix template init */
  144. bzero(&pflowif->sc_tmpl_ipfix,sizeof(pflowif->sc_tmpl_ipfix));
  145. pflowif->sc_tmpl_ipfix.set_header.set_id =
  146. htons(PFLOW_IPFIX_TMPL_SET_ID);
  147. pflowif->sc_tmpl_ipfix.set_header.set_length =
  148. htons(sizeof(struct pflow_ipfix_tmpl));
  149. /* ipfix IPv4 template */
  150. pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.tmpl_id =
  151. htons(PFLOW_IPFIX_TMPL_IPV4_ID);
  152. pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.field_count
  153. = htons(PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT);
  154. pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.field_id =
  155. htons(PFIX_IE_sourceIPv4Address);
  156. pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.len = htons(4);
  157. pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.field_id =
  158. htons(PFIX_IE_destinationIPv4Address);
  159. pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.len = htons(4);
  160. pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.field_id =
  161. htons(PFIX_IE_ingressInterface);
  162. pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.len = htons(4);
  163. pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.field_id =
  164. htons(PFIX_IE_egressInterface);
  165. pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.len = htons(4);
  166. pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.field_id =
  167. htons(PFIX_IE_packetDeltaCount);
  168. pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.len = htons(8);
  169. pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.field_id =
  170. htons(PFIX_IE_octetDeltaCount);
  171. pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.len = htons(8);
  172. pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.field_id =
  173. htons(PFIX_IE_flowStartMilliseconds);
  174. pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.len = htons(8);
  175. pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.field_id =
  176. htons(PFIX_IE_flowEndMilliseconds);
  177. pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.len = htons(8);
  178. pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.field_id =
  179. htons(PFIX_IE_sourceTransportPort);
  180. pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.len = htons(2);
  181. pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.field_id =
  182. htons(PFIX_IE_destinationTransportPort);
  183. pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.len = htons(2);
  184. pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.field_id =
  185. htons(PFIX_IE_ipClassOfService);
  186. pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.len = htons(1);
  187. pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.field_id =
  188. htons(PFIX_IE_protocolIdentifier);
  189. pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.len = htons(1);
  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. 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 = NULL;
  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. /* Insert into list of pflows */
  247. SLIST_INSERT_HEAD(&pflowif_list, pflowif, sc_next);
  248. return (0);
  249. }
  250. int
  251. pflow_clone_destroy(struct ifnet *ifp)
  252. {
  253. struct pflow_softc *sc = ifp->if_softc;
  254. int s, error;
  255. error = 0;
  256. s = splnet();
  257. m_freem(sc->send_nam);
  258. if (timeout_initialized(&sc->sc_tmo))
  259. timeout_del(&sc->sc_tmo);
  260. if (timeout_initialized(&sc->sc_tmo6))
  261. timeout_del(&sc->sc_tmo6);
  262. if (timeout_initialized(&sc->sc_tmo_tmpl))
  263. timeout_del(&sc->sc_tmo_tmpl);
  264. pflow_flush(sc);
  265. if (sc->so != NULL) {
  266. error = soclose(sc->so);
  267. sc->so = NULL;
  268. }
  269. if_detach(ifp);
  270. SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
  271. free(sc, M_DEVBUF, 0);
  272. splx(s);
  273. return (error);
  274. }
  275. int
  276. pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  277. {
  278. struct proc *p = curproc;
  279. struct pflow_softc *sc = ifp->if_softc;
  280. struct ifreq *ifr = (struct ifreq *)data;
  281. struct pflowreq pflowr;
  282. struct socket *so;
  283. struct sockaddr_in *sin;
  284. struct mbuf *m;
  285. int s, error;
  286. switch (cmd) {
  287. case SIOCSIFADDR:
  288. case SIOCAIFADDR:
  289. case SIOCSIFDSTADDR:
  290. case SIOCSIFFLAGS:
  291. if ((ifp->if_flags & IFF_UP) &&
  292. sc->sc_receiver_ip.s_addr != INADDR_ANY &&
  293. sc->sc_receiver_port != 0 && sc->so != NULL) {
  294. ifp->if_flags |= IFF_RUNNING;
  295. sc->sc_gcounter=pflowstats.pflow_flows;
  296. /* send templates on startup */
  297. if (sc->sc_version == PFLOW_PROTO_10) {
  298. s = splnet();
  299. pflow_sendout_ipfix_tmpl(sc);
  300. splx(s);
  301. }
  302. } else
  303. ifp->if_flags &= ~IFF_RUNNING;
  304. break;
  305. case SIOCSIFMTU:
  306. if (ifr->ifr_mtu < PFLOW_MINMTU)
  307. return (EINVAL);
  308. if (ifr->ifr_mtu > MCLBYTES)
  309. ifr->ifr_mtu = MCLBYTES;
  310. s = splnet();
  311. if (ifr->ifr_mtu < ifp->if_mtu)
  312. pflow_flush(sc);
  313. pflow_setmtu(sc, ifr->ifr_mtu);
  314. splx(s);
  315. break;
  316. case SIOCGETPFLOW:
  317. bzero(&pflowr, sizeof(pflowr));
  318. pflowr.sender_ip = sc->sc_sender_ip;
  319. pflowr.receiver_ip = sc->sc_receiver_ip;
  320. pflowr.receiver_port = sc->sc_receiver_port;
  321. pflowr.version = sc->sc_version;
  322. if ((error = copyout(&pflowr, ifr->ifr_data,
  323. sizeof(pflowr))))
  324. return (error);
  325. break;
  326. case SIOCSETPFLOW:
  327. if ((error = suser(p, 0)) != 0)
  328. return (error);
  329. if ((error = copyin(ifr->ifr_data, &pflowr,
  330. sizeof(pflowr))))
  331. return (error);
  332. if (pflowr.addrmask & PFLOW_MASK_VERSION) {
  333. switch(pflowr.version) {
  334. case PFLOW_PROTO_5:
  335. case PFLOW_PROTO_10:
  336. break;
  337. default:
  338. return(EINVAL);
  339. }
  340. }
  341. s = splnet();
  342. pflow_flush(sc);
  343. if (pflowr.addrmask & PFLOW_MASK_DSTIP) {
  344. sc->sc_receiver_ip.s_addr = pflowr.receiver_ip.s_addr;
  345. sin = mtod(sc->send_nam, struct sockaddr_in *);
  346. sin->sin_addr.s_addr = sc->sc_receiver_ip.s_addr;
  347. }
  348. if (pflowr.addrmask & PFLOW_MASK_DSTPRT) {
  349. sc->sc_receiver_port = pflowr.receiver_port;
  350. sin = mtod(sc->send_nam, struct sockaddr_in *);
  351. sin->sin_port = pflowr.receiver_port;
  352. }
  353. if (pflowr.addrmask & PFLOW_MASK_SRCIP) {
  354. error = socreate(AF_INET, &so, SOCK_DGRAM, 0);
  355. if (error) {
  356. splx(s);
  357. return (error);
  358. }
  359. MGET(m, M_WAIT, MT_SONAME);
  360. sin = mtod(m, struct sockaddr_in *);
  361. memset(sin, 0 , sizeof(*sin));
  362. sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
  363. sin->sin_family = AF_INET;
  364. sin->sin_addr.s_addr = pflowr.sender_ip.s_addr;
  365. sin->sin_port = 0;
  366. error = sobind(so, m, p);
  367. m_freem(m);
  368. if (error) {
  369. soclose(so);
  370. splx(s);
  371. return (error);
  372. }
  373. sc->sc_sender_ip.s_addr = pflowr.sender_ip.s_addr;
  374. soclose(sc->so);
  375. sc->so = so;
  376. }
  377. /* error check is above */
  378. if (pflowr.addrmask & PFLOW_MASK_VERSION)
  379. sc->sc_version = pflowr.version;
  380. pflow_setmtu(sc, ETHERMTU);
  381. pflow_init_timeouts(sc);
  382. splx(s);
  383. if ((ifp->if_flags & IFF_UP) &&
  384. sc->sc_receiver_ip.s_addr != INADDR_ANY &&
  385. sc->sc_receiver_port != 0 && sc->so != NULL) {
  386. ifp->if_flags |= IFF_RUNNING;
  387. sc->sc_gcounter=pflowstats.pflow_flows;
  388. if (sc->sc_version == PFLOW_PROTO_10) {
  389. s = splnet();
  390. pflow_sendout_ipfix_tmpl(sc);
  391. splx(s);
  392. }
  393. } else
  394. ifp->if_flags &= ~IFF_RUNNING;
  395. break;
  396. default:
  397. return (ENOTTY);
  398. }
  399. return (0);
  400. }
  401. void
  402. pflow_init_timeouts(struct pflow_softc *sc)
  403. {
  404. switch (sc->sc_version) {
  405. case PFLOW_PROTO_5:
  406. if (timeout_initialized(&sc->sc_tmo6))
  407. timeout_del(&sc->sc_tmo6);
  408. if (timeout_initialized(&sc->sc_tmo_tmpl))
  409. timeout_del(&sc->sc_tmo_tmpl);
  410. if (!timeout_initialized(&sc->sc_tmo))
  411. timeout_set(&sc->sc_tmo, pflow_timeout, sc);
  412. break;
  413. case PFLOW_PROTO_10:
  414. if (!timeout_initialized(&sc->sc_tmo_tmpl))
  415. timeout_set(&sc->sc_tmo_tmpl, pflow_timeout_tmpl, sc);
  416. if (!timeout_initialized(&sc->sc_tmo))
  417. timeout_set(&sc->sc_tmo, pflow_timeout, sc);
  418. if (!timeout_initialized(&sc->sc_tmo6))
  419. timeout_set(&sc->sc_tmo6, pflow_timeout6, sc);
  420. timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
  421. break;
  422. default: /* NOTREACHED */
  423. break;
  424. }
  425. }
  426. int
  427. pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz)
  428. {
  429. sc->sc_maxcount4 = (mtu - hdrsz -
  430. sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow4);
  431. sc->sc_maxcount6 = (mtu - hdrsz -
  432. sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow6);
  433. if (sc->sc_maxcount4 > PFLOW_MAXFLOWS)
  434. sc->sc_maxcount4 = PFLOW_MAXFLOWS;
  435. if (sc->sc_maxcount6 > PFLOW_MAXFLOWS)
  436. sc->sc_maxcount6 = PFLOW_MAXFLOWS;
  437. return (hdrsz + sizeof(struct udpiphdr) +
  438. MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4),
  439. sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6)));
  440. }
  441. void
  442. pflow_setmtu(struct pflow_softc *sc, int mtu_req)
  443. {
  444. int mtu;
  445. if (sc->sc_pflow_ifp && sc->sc_pflow_ifp->if_mtu < mtu_req)
  446. mtu = sc->sc_pflow_ifp->if_mtu;
  447. else
  448. mtu = mtu_req;
  449. switch (sc->sc_version) {
  450. case PFLOW_PROTO_5:
  451. sc->sc_maxcount = (mtu - sizeof(struct pflow_header) -
  452. sizeof(struct udpiphdr)) / sizeof(struct pflow_flow);
  453. if (sc->sc_maxcount > PFLOW_MAXFLOWS)
  454. sc->sc_maxcount = PFLOW_MAXFLOWS;
  455. sc->sc_if.if_mtu = sizeof(struct pflow_header) +
  456. sizeof(struct udpiphdr) +
  457. sc->sc_maxcount * sizeof(struct pflow_flow);
  458. break;
  459. case PFLOW_PROTO_10:
  460. sc->sc_if.if_mtu =
  461. pflow_calc_mtu(sc, mtu, sizeof(struct pflow_v10_header));
  462. break;
  463. default: /* NOTREACHED */
  464. break;
  465. }
  466. }
  467. struct mbuf *
  468. pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id)
  469. {
  470. struct pflow_set_header set_hdr;
  471. struct pflow_header h;
  472. struct mbuf *m;
  473. MGETHDR(m, M_DONTWAIT, MT_DATA);
  474. if (m == NULL) {
  475. pflowstats.pflow_onomem++;
  476. return (NULL);
  477. }
  478. MCLGET(m, M_DONTWAIT);
  479. if ((m->m_flags & M_EXT) == 0) {
  480. m_free(m);
  481. pflowstats.pflow_onomem++;
  482. return (NULL);
  483. }
  484. m->m_len = m->m_pkthdr.len = 0;
  485. m->m_pkthdr.ph_ifidx = 0;
  486. if (sc == NULL) /* get only a new empty mbuf */
  487. return (m);
  488. if (sc->sc_version == PFLOW_PROTO_5) {
  489. /* populate pflow_header */
  490. h.reserved1 = 0;
  491. h.reserved2 = 0;
  492. h.count = 0;
  493. h.version = htons(PFLOW_PROTO_5);
  494. h.flow_sequence = htonl(sc->sc_gcounter);
  495. h.engine_type = PFLOW_ENGINE_TYPE;
  496. h.engine_id = PFLOW_ENGINE_ID;
  497. m_copyback(m, 0, PFLOW_HDRLEN, &h, M_NOWAIT);
  498. sc->sc_count = 0;
  499. timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
  500. } else {
  501. /* populate pflow_set_header */
  502. set_hdr.set_length = 0;
  503. set_hdr.set_id = htons(set_id);
  504. m_copyback(m, 0, PFLOW_SET_HDRLEN, &set_hdr, M_NOWAIT);
  505. }
  506. return (m);
  507. }
  508. void
  509. copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
  510. struct pf_state *st, struct pf_state_key *sk, int src, int dst)
  511. {
  512. flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
  513. flow1->src_port = flow2->dest_port = sk->port[src];
  514. flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
  515. flow1->dest_port = flow2->src_port = sk->port[dst];
  516. flow1->dest_as = flow2->src_as =
  517. flow1->src_as = flow2->dest_as = 0;
  518. flow1->if_index_in = htons(st->if_index_in);
  519. flow1->if_index_out = htons(st->if_index_out);
  520. flow2->if_index_in = htons(st->if_index_out);
  521. flow2->if_index_out = htons(st->if_index_in);
  522. flow1->dest_mask = flow2->src_mask =
  523. flow1->src_mask = flow2->dest_mask = 0;
  524. flow1->flow_packets = htonl(st->packets[0]);
  525. flow2->flow_packets = htonl(st->packets[1]);
  526. flow1->flow_octets = htonl(st->bytes[0]);
  527. flow2->flow_octets = htonl(st->bytes[1]);
  528. /*
  529. * Pretend the flow was created or expired when the machine came up
  530. * when creation is in the future of the last time a package was seen
  531. * or was created / expired before this machine came up due to pfsync.
  532. */
  533. flow1->flow_start = flow2->flow_start = st->creation < 0 ||
  534. st->creation > st->expire ? htonl(0) : htonl(st->creation * 1000);
  535. flow1->flow_finish = flow2->flow_finish = st->expire < 0 ? htonl(0) :
  536. htonl(st->expire * 1000);
  537. flow1->tcp_flags = flow2->tcp_flags = 0;
  538. flow1->protocol = flow2->protocol = sk->proto;
  539. flow1->tos = flow2->tos = st->rule.ptr->tos;
  540. }
  541. void
  542. copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
  543. struct pflow_ipfix_flow4 *flow2, struct pf_state *st,
  544. struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
  545. {
  546. flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr;
  547. flow1->src_port = flow2->dest_port = sk->port[src];
  548. flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr;
  549. flow1->dest_port = flow2->src_port = sk->port[dst];
  550. flow1->if_index_in = htonl(st->if_index_in);
  551. flow1->if_index_out = htonl(st->if_index_out);
  552. flow2->if_index_in = htonl(st->if_index_out);
  553. flow2->if_index_out = htonl(st->if_index_in);
  554. flow1->flow_packets = htobe64(st->packets[0]);
  555. flow2->flow_packets = htobe64(st->packets[1]);
  556. flow1->flow_octets = htobe64(st->bytes[0]);
  557. flow2->flow_octets = htobe64(st->bytes[1]);
  558. /*
  559. * Pretend the flow was created when the machine came up when creation
  560. * is in the future of the last time a package was seen due to pfsync.
  561. */
  562. if (st->creation > st->expire)
  563. flow1->flow_start = flow2->flow_start = htobe64((time_second -
  564. time_uptime)*1000);
  565. else
  566. flow1->flow_start = flow2->flow_start = htobe64((time_second -
  567. (time_uptime - st->creation))*1000);
  568. flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
  569. (time_uptime - st->expire))*1000);
  570. flow1->protocol = flow2->protocol = sk->proto;
  571. flow1->tos = flow2->tos = st->rule.ptr->tos;
  572. }
  573. void
  574. copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
  575. struct pflow_ipfix_flow6 *flow2, struct pf_state *st,
  576. struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst)
  577. {
  578. bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip));
  579. bcopy(&sk->addr[src].v6, &flow2->dest_ip, sizeof(flow2->dest_ip));
  580. flow1->src_port = flow2->dest_port = sk->port[src];
  581. bcopy(&sk->addr[dst].v6, &flow1->dest_ip, sizeof(flow1->dest_ip));
  582. bcopy(&sk->addr[dst].v6, &flow2->src_ip, sizeof(flow2->src_ip));
  583. flow1->dest_port = flow2->src_port = sk->port[dst];
  584. flow1->if_index_in = htonl(st->if_index_in);
  585. flow1->if_index_out = htonl(st->if_index_out);
  586. flow2->if_index_in = htonl(st->if_index_out);
  587. flow2->if_index_out = htonl(st->if_index_in);
  588. flow1->flow_packets = htobe64(st->packets[0]);
  589. flow2->flow_packets = htobe64(st->packets[1]);
  590. flow1->flow_octets = htobe64(st->bytes[0]);
  591. flow2->flow_octets = htobe64(st->bytes[1]);
  592. /*
  593. * Pretend the flow was created when the machine came up when creation
  594. * is in the future of the last time a package was seen due to pfsync.
  595. */
  596. if (st->creation > st->expire)
  597. flow1->flow_start = flow2->flow_start = htobe64((time_second -
  598. time_uptime)*1000);
  599. else
  600. flow1->flow_start = flow2->flow_start = htobe64((time_second -
  601. (time_uptime - st->creation))*1000);
  602. flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
  603. (time_uptime - st->expire))*1000);
  604. flow1->protocol = flow2->protocol = sk->proto;
  605. flow1->tos = flow2->tos = st->rule.ptr->tos;
  606. }
  607. int
  608. export_pflow(struct pf_state *st)
  609. {
  610. struct pflow_softc *sc = NULL;
  611. struct pf_state_key *sk;
  612. sk = st->key[st->direction == PF_IN ? PF_SK_WIRE : PF_SK_STACK];
  613. SLIST_FOREACH(sc, &pflowif_list, sc_next) {
  614. switch (sc->sc_version) {
  615. case PFLOW_PROTO_5:
  616. if( sk->af == AF_INET )
  617. export_pflow_if(st, sk, sc);
  618. break;
  619. case PFLOW_PROTO_10:
  620. if( sk->af == AF_INET || sk->af == AF_INET6 )
  621. export_pflow_if(st, sk, sc);
  622. break;
  623. default: /* NOTREACHED */
  624. break;
  625. }
  626. }
  627. return (0);
  628. }
  629. int
  630. export_pflow_if(struct pf_state *st, struct pf_state_key *sk,
  631. struct pflow_softc *sc)
  632. {
  633. struct pf_state pfs_copy;
  634. struct ifnet *ifp = &sc->sc_if;
  635. u_int64_t bytes[2];
  636. int ret = 0;
  637. if (!(ifp->if_flags & IFF_RUNNING))
  638. return (0);
  639. if (sc->sc_version == PFLOW_PROTO_10)
  640. return (pflow_pack_flow_ipfix(st, sk, sc));
  641. /* PFLOW_PROTO_5 */
  642. if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES)
  643. && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES))
  644. return (pflow_pack_flow(st, sk, sc));
  645. /* flow > PFLOW_MAXBYTES need special handling */
  646. bcopy(st, &pfs_copy, sizeof(pfs_copy));
  647. bytes[0] = pfs_copy.bytes[0];
  648. bytes[1] = pfs_copy.bytes[1];
  649. while (bytes[0] > PFLOW_MAXBYTES) {
  650. pfs_copy.bytes[0] = PFLOW_MAXBYTES;
  651. pfs_copy.bytes[1] = 0;
  652. if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0)
  653. return (ret);
  654. if ((bytes[0] - PFLOW_MAXBYTES) > 0)
  655. bytes[0] -= PFLOW_MAXBYTES;
  656. }
  657. while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) {
  658. pfs_copy.bytes[1] = PFLOW_MAXBYTES;
  659. pfs_copy.bytes[0] = 0;
  660. if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0)
  661. return (ret);
  662. if ((bytes[1] - PFLOW_MAXBYTES) > 0)
  663. bytes[1] -= PFLOW_MAXBYTES;
  664. }
  665. pfs_copy.bytes[0] = bytes[0];
  666. pfs_copy.bytes[1] = bytes[1];
  667. return (pflow_pack_flow(&pfs_copy, sk, sc));
  668. }
  669. int
  670. copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc)
  671. {
  672. int s, ret = 0;
  673. s = splnet();
  674. if (sc->sc_mbuf == NULL) {
  675. if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0)) == NULL) {
  676. splx(s);
  677. return (ENOBUFS);
  678. }
  679. }
  680. m_copyback(sc->sc_mbuf, PFLOW_HDRLEN +
  681. (sc->sc_count * sizeof(struct pflow_flow)),
  682. sizeof(struct pflow_flow), flow, M_NOWAIT);
  683. if (pflowstats.pflow_flows == sc->sc_gcounter)
  684. pflowstats.pflow_flows++;
  685. sc->sc_gcounter++;
  686. sc->sc_count++;
  687. if (sc->sc_count >= sc->sc_maxcount)
  688. ret = pflow_sendout_v5(sc);
  689. splx(s);
  690. return(ret);
  691. }
  692. int
  693. copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc)
  694. {
  695. int s, ret = 0;
  696. s = splnet();
  697. if (sc->sc_mbuf == NULL) {
  698. if ((sc->sc_mbuf =
  699. pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID)) == NULL) {
  700. splx(s);
  701. return (ENOBUFS);
  702. }
  703. sc->sc_count4 = 0;
  704. timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT);
  705. }
  706. m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN +
  707. (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)),
  708. sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT);
  709. if (pflowstats.pflow_flows == sc->sc_gcounter)
  710. pflowstats.pflow_flows++;
  711. sc->sc_gcounter++;
  712. sc->sc_count4++;
  713. if (sc->sc_count4 >= sc->sc_maxcount4)
  714. ret = pflow_sendout_ipfix(sc, AF_INET);
  715. splx(s);
  716. return(ret);
  717. }
  718. int
  719. copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc)
  720. {
  721. int s, ret = 0;
  722. s = splnet();
  723. if (sc->sc_mbuf6 == NULL) {
  724. if ((sc->sc_mbuf6 =
  725. pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID)) == NULL) {
  726. splx(s);
  727. return (ENOBUFS);
  728. }
  729. sc->sc_count6 = 0;
  730. timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT);
  731. }
  732. m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN +
  733. (sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)),
  734. sizeof(struct pflow_ipfix_flow6), flow, M_NOWAIT);
  735. if (pflowstats.pflow_flows == sc->sc_gcounter)
  736. pflowstats.pflow_flows++;
  737. sc->sc_gcounter++;
  738. sc->sc_count6++;
  739. if (sc->sc_count6 >= sc->sc_maxcount6)
  740. ret = pflow_sendout_ipfix(sc, AF_INET6);
  741. splx(s);
  742. return(ret);
  743. }
  744. int
  745. pflow_pack_flow(struct pf_state *st, struct pf_state_key *sk,
  746. struct pflow_softc *sc)
  747. {
  748. struct pflow_flow flow1;
  749. struct pflow_flow flow2;
  750. int ret = 0;
  751. bzero(&flow1, sizeof(flow1));
  752. bzero(&flow2, sizeof(flow2));
  753. if (st->direction == PF_OUT)
  754. copy_flow_data(&flow1, &flow2, st, sk, 1, 0);
  755. else
  756. copy_flow_data(&flow1, &flow2, st, sk, 0, 1);
  757. if (st->bytes[0] != 0) /* first flow from state */
  758. ret = copy_flow_to_m(&flow1, sc);
  759. if (st->bytes[1] != 0) /* second flow from state */
  760. ret = copy_flow_to_m(&flow2, sc);
  761. return (ret);
  762. }
  763. int
  764. pflow_pack_flow_ipfix(struct pf_state *st, struct pf_state_key *sk,
  765. struct pflow_softc *sc)
  766. {
  767. struct pflow_ipfix_flow4 flow4_1, flow4_2;
  768. struct pflow_ipfix_flow6 flow6_1, flow6_2;
  769. int ret = 0;
  770. if (sk->af == AF_INET) {
  771. bzero(&flow4_1, sizeof(flow4_1));
  772. bzero(&flow4_2, sizeof(flow4_2));
  773. if (st->direction == PF_OUT)
  774. copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
  775. 1, 0);
  776. else
  777. copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc,
  778. 0, 1);
  779. if (st->bytes[0] != 0) /* first flow from state */
  780. ret = copy_flow_ipfix_4_to_m(&flow4_1, sc);
  781. if (st->bytes[1] != 0) /* second flow from state */
  782. ret = copy_flow_ipfix_4_to_m(&flow4_2, sc);
  783. } else if (sk->af == AF_INET6) {
  784. bzero(&flow6_1, sizeof(flow6_1));
  785. bzero(&flow6_2, sizeof(flow6_2));
  786. if (st->direction == PF_OUT)
  787. copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
  788. 1, 0);
  789. else
  790. copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc,
  791. 0, 1);
  792. if (st->bytes[0] != 0) /* first flow from state */
  793. ret = copy_flow_ipfix_6_to_m(&flow6_1, sc);
  794. if (st->bytes[1] != 0) /* second flow from state */
  795. ret = copy_flow_ipfix_6_to_m(&flow6_2, sc);
  796. }
  797. return (ret);
  798. }
  799. void
  800. pflow_timeout(void *v)
  801. {
  802. struct pflow_softc *sc = v;
  803. int s;
  804. s = splnet();
  805. switch (sc->sc_version) {
  806. case PFLOW_PROTO_5:
  807. pflow_sendout_v5(sc);
  808. break;
  809. case PFLOW_PROTO_10:
  810. pflow_sendout_ipfix(sc, AF_INET);
  811. break;
  812. default: /* NOTREACHED */
  813. break;
  814. }
  815. splx(s);
  816. }
  817. void
  818. pflow_timeout6(void *v)
  819. {
  820. struct pflow_softc *sc = v;
  821. int s;
  822. s = splnet();
  823. pflow_sendout_ipfix(sc, AF_INET6);
  824. splx(s);
  825. }
  826. void
  827. pflow_timeout_tmpl(void *v)
  828. {
  829. struct pflow_softc *sc = v;
  830. int s;
  831. s = splnet();
  832. pflow_sendout_ipfix_tmpl(sc);
  833. splx(s);
  834. }
  835. /* This must be called in splnet() */
  836. void
  837. pflow_flush(struct pflow_softc *sc)
  838. {
  839. switch (sc->sc_version) {
  840. case PFLOW_PROTO_5:
  841. pflow_sendout_v5(sc);
  842. break;
  843. case PFLOW_PROTO_10:
  844. pflow_sendout_ipfix(sc, AF_INET);
  845. pflow_sendout_ipfix(sc, AF_INET6);
  846. break;
  847. default: /* NOTREACHED */
  848. break;
  849. }
  850. }
  851. /* This must be called in splnet() */
  852. int
  853. pflow_sendout_v5(struct pflow_softc *sc)
  854. {
  855. struct mbuf *m = sc->sc_mbuf;
  856. struct pflow_header *h;
  857. struct ifnet *ifp = &sc->sc_if;
  858. struct timespec tv;
  859. timeout_del(&sc->sc_tmo);
  860. if (m == NULL)
  861. return (0);
  862. sc->sc_mbuf = NULL;
  863. if (!(ifp->if_flags & IFF_RUNNING)) {
  864. m_freem(m);
  865. return (0);
  866. }
  867. pflowstats.pflow_packets++;
  868. h = mtod(m, struct pflow_header *);
  869. h->count = htons(sc->sc_count);
  870. /* populate pflow_header */
  871. h->uptime_ms = htonl(time_uptime * 1000);
  872. getnanotime(&tv);
  873. h->time_sec = htonl(tv.tv_sec); /* XXX 2038 */
  874. h->time_nanosec = htonl(tv.tv_nsec);
  875. return (pflow_sendout_mbuf(sc, m));
  876. }
  877. /* This must be called in splnet() */
  878. int
  879. pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af)
  880. {
  881. struct mbuf *m;
  882. struct pflow_v10_header *h10;
  883. struct pflow_set_header *set_hdr;
  884. struct ifnet *ifp = &sc->sc_if;
  885. u_int32_t count;
  886. int set_length;
  887. switch (af) {
  888. case AF_INET:
  889. m = sc->sc_mbuf;
  890. timeout_del(&sc->sc_tmo);
  891. if (m == NULL)
  892. return (0);
  893. sc->sc_mbuf = NULL;
  894. count = sc->sc_count4;
  895. set_length = sizeof(struct pflow_set_header)
  896. + sc->sc_count4 * sizeof(struct pflow_ipfix_flow4);
  897. break;
  898. case AF_INET6:
  899. m = sc->sc_mbuf6;
  900. timeout_del(&sc->sc_tmo6);
  901. if (m == NULL)
  902. return (0);
  903. sc->sc_mbuf6 = NULL;
  904. count = sc->sc_count6;
  905. set_length = sizeof(struct pflow_set_header)
  906. + sc->sc_count6 * sizeof(struct pflow_ipfix_flow6);
  907. break;
  908. default:
  909. unhandled_af(af);
  910. }
  911. if (!(ifp->if_flags & IFF_RUNNING)) {
  912. m_freem(m);
  913. return (0);
  914. }
  915. pflowstats.pflow_packets++;
  916. set_hdr = mtod(m, struct pflow_set_header *);
  917. set_hdr->set_length = htons(set_length);
  918. /* populate pflow_header */
  919. M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
  920. if (m == NULL) {
  921. pflowstats.pflow_onomem++;
  922. return (ENOBUFS);
  923. }
  924. h10 = mtod(m, struct pflow_v10_header *);
  925. h10->version = htons(PFLOW_PROTO_10);
  926. h10->length = htons(PFLOW_IPFIX_HDRLEN + set_length);
  927. h10->time_sec = htonl(time_second); /* XXX 2038 */
  928. h10->flow_sequence = htonl(sc->sc_sequence);
  929. sc->sc_sequence += count;
  930. h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
  931. return (pflow_sendout_mbuf(sc, m));
  932. }
  933. /* This must be called in splnet() */
  934. int
  935. pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
  936. {
  937. struct mbuf *m;
  938. struct pflow_v10_header *h10;
  939. struct ifnet *ifp = &sc->sc_if;
  940. timeout_del(&sc->sc_tmo_tmpl);
  941. if (!(ifp->if_flags & IFF_RUNNING)) {
  942. return (0);
  943. }
  944. m = pflow_get_mbuf(NULL, 0);
  945. if (m == NULL)
  946. return (0);
  947. if (m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl),
  948. &sc->sc_tmpl_ipfix, M_NOWAIT)) {
  949. m_freem(m);
  950. return (0);
  951. }
  952. pflowstats.pflow_packets++;
  953. /* populate pflow_header */
  954. M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT);
  955. if (m == NULL) {
  956. pflowstats.pflow_onomem++;
  957. return (ENOBUFS);
  958. }
  959. h10 = mtod(m, struct pflow_v10_header *);
  960. h10->version = htons(PFLOW_PROTO_10);
  961. h10->length = htons(PFLOW_IPFIX_HDRLEN + sizeof(struct
  962. pflow_ipfix_tmpl));
  963. h10->time_sec = htonl(time_second); /* XXX 2038 */
  964. h10->flow_sequence = htonl(sc->sc_sequence);
  965. h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
  966. timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
  967. return (pflow_sendout_mbuf(sc, m));
  968. }
  969. int
  970. pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m)
  971. {
  972. sc->sc_if.if_opackets++;
  973. sc->sc_if.if_obytes += m->m_pkthdr.len;
  974. if (sc->so == NULL) {
  975. m_freem(m);
  976. return (EINVAL);
  977. }
  978. return (sosend(sc->so, sc->send_nam, NULL, m, NULL, 0));
  979. }
  980. int
  981. pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
  982. void *newp, size_t newlen)
  983. {
  984. if (namelen != 1)
  985. return (ENOTDIR);
  986. switch (name[0]) {
  987. case NET_PFLOW_STATS:
  988. if (newp != NULL)
  989. return (EPERM);
  990. return (sysctl_struct(oldp, oldlenp, newp, newlen,
  991. &pflowstats, sizeof(pflowstats)));
  992. default:
  993. return (EOPNOTSUPP);
  994. }
  995. return (0);
  996. }