libfixbuf-1.7.1/000755 000770 000024 00000000000 12606001063 016000 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/AUTHORS000644 000770 000024 00000000673 12406304621 017062 0ustar00emilyecoffmessagebus000000 000000 Brian Trammell is the original author of libfixbuf. libfixbuf is now maintained by the Network Situational Awareness Group at CERT/SEI . Thanks to the organizers and participants of the IPFIX Interoperability Events sponsored by IPS-MoME in Salzburg, Austria in March 2006 and by Fraunhofer FOKUS in Berlin, Germany in November 2006 for helping to ensure fixbuf's interoperability with other IPFIX implementations. libfixbuf-1.7.1/configure.ac000644 000770 000024 00000016532 12605776025 020315 0ustar00emilyecoffmessagebus000000 000000 dnl Process this file with autoconf to produce a configure script dnl ------------------------------------------------------------------------ dnl configure.ac dnl autotools build system for libfixbuf dnl ------------------------------------------------------------------------ dnl Copyright (C) 2005-2015 Carnegie Mellon University. All Rights Reserved. dnl ------------------------------------------------------------------------ dnl Authors: Brian Trammell, Dan Ruef , Chris Inacio dnl dnl ------------------------------------------------------------------------ dnl GNU Lesser GPL Rights pursuant to Version 2.1, February 1999 dnl Government Purpose License Rights (GPLR) pursuant to DFARS 252.227-7013 dnl ------------------------------------------------------------------------ dnl RCSIDENT("$Id: configure.in 18509 2012-08-23 19:13:27Z ecoff_svn $") AC_INIT([libfixbuf], [1.7.1], [netsa-help@cert.org], [libfixbuf]) AC_CONFIG_AUX_DIR([autoconf]) AC_COPYRIGHT([Copyright (C) 2006-2015 by Carnegie Mellon University GNU Public License (GPL) Rights pursuant to Version 2, June 1991 Government Purpose License Rights (GPLR) pursuant to DFARS 252.227-7013]) AM_INIT_AUTOMAKE([1.6.3 foreign]) dnl change this version number every new release. (1:0:0 starts at 1.3.0) dnl the first number should be changed if the interface has changed dnl the second number should be changed for bug fixes, small changes dnl the third number should be changed if the first number changes and dnl the release is backwards compatible with the previous release. LIBCOMPAT="5:0:2" AC_REVISION($Revision: 18509 $) AM_CONFIG_HEADER(include/fixbuf/config.h) AC_CONFIG_MACRO_DIR([m4]) AM_PROG_LIBTOOL AC_PROG_CC AC_PROG_CXX AC_PROG_INSTALL AC_PROG_MAKE_SET AC_HEADER_STDC AC_LANG_C CPPFLAGS='-I$(top_builddir)/include -I$(top_srcdir)/include'" $CPPFLAGS" AC_HEADER_STDC AC_CHECK_HEADERS([unistd.h stdint.h errno.h netinet/in.h sys/errno.h sys/socket.h pthread.h]) AM_WITH_DMALLOC AC_DEBUG RPM_CONFIG_FLAGS="" dnl ---------------------------------------------------------------------- dnl Set up doxygen dnl ---------------------------------------------------------------------- DX_HTML_FEATURE(ON) DX_CHM_FEATURE(OFF) DX_CHI_FEATURE(OFF) DX_MAN_FEATURE(OFF) DX_RTF_FEATURE(OFF) DX_XML_FEATURE(OFF) DX_PDF_FEATURE(OFF) DX_PS_FEATURE(OFF) DX_INIT_DOXYGEN(libfixbuf, Doxyfile, doc) dnl ---------------------------------------------------------------------- dnl Check for aligned access required dnl ---------------------------------------------------------------------- AX_CHECK_ALIGNED_ACCESS_REQUIRED dnl ---------------------------------------------------------------------- dnl Check for a suitable glib dnl ---------------------------------------------------------------------- GLIB_PRESENT=NO GLIB_LDADD= AM_PATH_GLIB_2_0([2.4.7],[GLIB_PRESENT=YES],,[gthread]) AC_ARG_WITH(glib-static, [ --with-glib-static=prefix use static glib tree],[ GLIB_STATIC_LIBGLIB2_A="${withval}/lib/libglib-2.0.a ${withval}/lib/libgthread-2.0.a" GLIB_STATIC_INCLUDE="${withval}/include/glib-2.0" GLIB_STATIC_LIBINCLUDE="${withval}/lib/glib-2.0/include" if test -f ${GLIB_STATIC_LIBGLIB2_A}; then if test -f "${GLIB_STATIC_INCLUDE}/glib.h"; then GLIB_LDADD=${GLIB_STATIC_LIBGLIB2_A} GLIB_CFLAGS="-I${GLIB_STATIC_INCLUDE} -I${GLIB_STATIC_LIBINCLUDE}" AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_CFLAGS) GLIB_PRESENT=YES AC_MSG_NOTICE([assuming static glib in ${withval} is good...]) fi fi ]) if test x"$GLIB_PRESENT" != "xYES"; then AC_MSG_ERROR([Cannot find a suitable glib2 (>= 2.4.7)]) fi AC_SUBST(GLIB_LDADD) dnl ---------------------------------------------------------------------- dnl Check for getaddrinfo dnl ---------------------------------------------------------------------- AC_CHECK_FUNCS(getaddrinfo) dnl --------------------------------------------------------------------- dnl Check for pthread dnl -------------------------------------------------------------------- AC_CHECK_LIB([pthread],[pthread_mutex_lock],[],[ AC_MSG_ERROR([Required pthread library not found]) ]) dnl ---------------------------------------------------------------------- dnl check for all of the Solaris specific libraries dnl ---------------------------------------------------------------------- AC_SEARCH_LIBS([nanosleep], [rt]) AC_SEARCH_LIBS([inet_ntoa], [nsl]) AC_SEARCH_LIBS([socket], [socket]) dnl ---------------------------------------------------------------------- dnl Check for SCTP support dnl ---------------------------------------------------------------------- AC_ARG_WITH(sctp, AC_HELP_STRING([--with-sctp=prefix], [Enable SCTP support using libsctp]),[ if test "x$withval" != "xno"; then if test -d ${withval}; then LDFLAGS="-L${withval}/lib ${LDFLAGS}" CFLAGS="-I{withval}/include ${CFLAGS}" RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-sctp=${withval}" else RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-sctp" fi dnl look for libsctp AC_CHECK_LIB(sctp, sctp_sendmsg,[ AC_DEFINE(FB_ENABLE_SCTP, 1, [Define to 1 to enable SCTP support]) LIBS="-lsctp ${LIBS}" AC_SUBST(FIXBUF_REQ_LIBSCTP, [1]) ],[ AC_MSG_ERROR([--with-sctp given but cannot find libsctp]) ]) dnl look for SCTP header files AC_CHECK_HEADER(netinet/sctp.h,[ AC_DEFINE(FB_INCLUDE_SCTP_H, 1, [Define to 1 to use sctp.h header]) AC_SUBST(FIXBUF_REQ_SCTPDEV, [1]) ], [], [AC_INCLUDES_DEFAULT([ #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif ])]) AC_CHECK_HEADER(netinet/sctp_uio.h,[ AC_DEFINE(FB_INCLUDE_SCTP_UIO_H, 1, [Define to 1 to use sctp_uio.h header]) ]) fi ]) dnl ---------------------------------------------------------------------- dnl Check for OpenSSL TLS and DTLS support dnl ---------------------------------------------------------------------- AC_ARG_WITH(openssl, AC_HELP_STRING([--with-openssl=prefix], [Use OpenSSL for TLS/DTLS support]),[ if test -d ${withval}; then LDFLAGS="-L${withval}/lib ${LDFLAGS}" CFLAGS="-I{withval}/include ${CFLAGS}" RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-openssl=${withval}" else RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-openssl" fi dnl look for libssl AC_CHECK_LIB(ssl,SSL_new,[ AC_DEFINE(HAVE_OPENSSL, 1, [Define to 1 to enable OpenSSL support]) LIBS="-lssl -lcrypto ${LIBS}" AC_SUBST(FIXBUF_REQ_LIBSSL, [1]) ],[ AC_MSG_ERROR([--with-openssl given but cannot find SSL_new()]) ]) dnl look for dtls AC_CHECK_LIB(ssl,DTLSv1_method,[ AC_DEFINE(HAVE_OPENSSL_DTLS, 1, [Define to 1 to enable DTLS support]) ],[ AC_MSG_NOTICE([OpenSSL does not support DTLS]) ]) AC_CHECK_HEADER(openssl/ssl.h,[], [ AC_MSG_ERROR([--with-openssl given but cannot find libssl headers.]) ]) ]) dnl ---------------------------------------------------------------------- dnl Check for Spread support dnl ---------------------------------------------------------------------- AC_PATH_SPREAD([4.1]) AC_SUBST(LIBCOMPAT) AC_SUBST(RPM_CONFIG_FLAGS) dnl automake 1.9 doesn't substitute these automatically, so we do it ourselves dnl just in case AC_SUBST([abs_top_srcdir]) AC_SUBST([abs_top_builddir]) AC_OUTPUT([ Makefile src/Makefile include/Makefile libfixbuf.pc libfixbuf.spec Doxyfile]) libfixbuf-1.7.1/COPYING000644 000770 000024 00000063500 12406304621 017043 0ustar00emilyecoffmessagebus000000 000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libfixbuf-1.7.1/doc/000755 000770 000024 00000000000 12606001064 016546 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/Doxyfile.in000644 000770 000024 00000144300 12406304621 020121 0ustar00emilyecoffmessagebus000000 000000 # Doxyfile 1.4.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libfixbuf # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @DX_DOCDIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). #USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. #DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is YES. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @abs_top_srcdir@/include/fixbuf # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = @abs_top_srcdir@/include/fixbuf/config.h \ @abs_top_srcdir@/include/fixbuf/autoinc.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html/libfixbuf # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = @abs_top_srcdir@/doc/Doxyhead.html # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = @abs_top_srcdir@/doc/Doxyfoot.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = @abs_top_srcdir@/doc/doxygen.css # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. #MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. #MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that a graph may be further truncated if the graph's # image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH # and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), # the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libfixbuf-1.7.1/doxygen.am000644 000770 000024 00000011211 12406304621 017774 0ustar00emilyecoffmessagebus000000 000000 # Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Automake macro files. # Generate automatic documentation using Doxygen. Goals and variables values # are controlled by the various DX_COND_??? conditionals set by autoconf. # # The provided goals are: # doxygen-doc: Generate all doxygen documentation. # doxygen-run: Run doxygen, which will generate some of the documentation # (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post # processing required for the rest of it (PS, PDF, and some MAN). # doxygen-man: Rename some doxygen generated man pages. # doxygen-ps: Generate doxygen PostScript documentation. # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake goals. If # doxygen is used to generate man pages, you can achieve this integration by # setting man3_MANS to the list of man pages generated and then adding the # dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # This is usually added to MOSTLYCLEANFILES. ## --------------------------------- ## ## Format-independent Doxygen rules. ## ## --------------------------------- ## if DX_COND_doc ## ------------------------------- ## ## Rules specific for HTML output. ## ## ------------------------------- ## if DX_COND_html DX_CLEAN_HTML = @DX_DOCDIR@/html endif DX_COND_html ## ------------------------------ ## ## Rules specific for CHM output. ## ## ------------------------------ ## if DX_COND_chm DX_CLEAN_CHM = @DX_DOCDIR@/chm if DX_COND_chi DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi endif DX_COND_chi endif DX_COND_chm ## ------------------------------ ## ## Rules specific for MAN output. ## ## ------------------------------ ## if DX_COND_man DX_CLEAN_MAN = @DX_DOCDIR@/man endif DX_COND_man ## ------------------------------ ## ## Rules specific for RTF output. ## ## ------------------------------ ## if DX_COND_rtf DX_CLEAN_RTF = @DX_DOCDIR@/rtf endif DX_COND_rtf ## ------------------------------ ## ## Rules specific for XML output. ## ## ------------------------------ ## if DX_COND_xml DX_CLEAN_XML = @DX_DOCDIR@/xml endif DX_COND_xml ## ----------------------------- ## ## Rules specific for PS output. ## ## ----------------------------- ## if DX_COND_ps DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps DX_PS_GOAL = doxygen-ps doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_LATEX) refman.tex; \ $(MAKEINDEX_PATH) refman.idx; \ $(DX_LATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_LATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi endif DX_COND_ps ## ------------------------------ ## ## Rules specific for PDF output. ## ## ------------------------------ ## if DX_COND_pdf DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf DX_PDF_GOAL = doxygen-pdf doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_PDFLATEX) refman.tex; \ $(DX_MAKEINDEX) refman.idx; \ $(DX_PDFLATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_PDFLATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ mv refman.pdf ../@PACKAGE@.pdf endif DX_COND_pdf ## ------------------------------------------------- ## ## Rules specific for LaTeX (shared for PS and PDF). ## ## ------------------------------------------------- ## if DX_COND_latex DX_CLEAN_LATEX = @DX_DOCDIR@/latex endif DX_COND_latex .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) $(DX_ENV) $(DX_DOXYGEN) $(DX_CONFIG) DX_CLEANFILES = \ -r \ @DX_DOCDIR@/@PACKAGE@.tag \ $(DX_CLEAN_HTML) \ $(DX_CLEAN_CHM) \ $(DX_CLEAN_CHI) \ $(DX_CLEAN_MAN) \ $(DX_CLEAN_RTF) \ $(DX_CLEAN_XML) \ $(DX_CLEAN_PS) \ $(DX_CLEAN_PDF) \ $(DX_CLEAN_LATEX) doxygen-clean: rm -rf $(DX_CLEANFILES) endif DX_COND_doc libfixbuf-1.7.1/include/000755 000770 000024 00000000000 12606001063 017423 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/INSTALL000644 000770 000024 00000022310 12406304621 017033 0ustar00emilyecoffmessagebus000000 000000 Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. libfixbuf-1.7.1/libfixbuf.pc.in000644 000770 000024 00000000505 12406304621 020707 0ustar00emilyecoffmessagebus000000 000000 prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libfixbuf Description: IPFIX Message Format Implementation Version: @VERSION@ Libs: -L${libdir} -lfixbuf @SPREAD_LDFLAGS@ @SPREAD_LIBS@ @LDFLAGS@ @LIBS@ @GLIB_LIBS@ Cflags: -I${includedir} @SPREAD_CC_DEFINE@ Requires: glib-2.0 >= 2.4.7 libfixbuf-1.7.1/libfixbuf.spec.in000644 000770 000024 00000003363 12545036674 021262 0ustar00emilyecoffmessagebus000000 000000 %define name libfixbuf %define version @PACKAGE_VERSION@ %define release 1 Summary: fixbuf IPFIX implementation library Name: %{name} Version: %{version} Release: %{release}%{?dist} Group: Applications/System License: LGPL Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version} Vendor: http://tools.netsa.cert.org/ Provides: libfixbuf Provides: libfixbuf.so Requires: glib2 >= 2.4.7 %if "x@FIXBUF_REQ_LIBSCTP@" == "x1" Requires: libsctp %endif %if "x@FIXBUF_REQ_LIBSPREAD@" == "x1" Requires: libspread %endif %if "x@FIXBUF_REQ_LIBSSL@" == "x1" Requires: openssl %endif BuildRequires: glib2-devel >= 2.4.7 BuildRequires: pkgconfig >= 0.8 %if "x@FIXBUF_REQ_SCTPDEV@" == "x1" BuildRequires: libsctp-devel %endif %if "x@FIXBUF_REQ_LIBSPREAD@" == "x1" BuildRequires: libspread-devel %endif %if "x@FIXBUF_REQ_LIBSSL@" == "x1" BuildRequires: openssl-devel %endif %description libfixbuf aims to be a compliant implementation of the IPFIX Protocol and message format, from which IPFIX Collecting Processes and IPFIX Exporting Processes may be built. %package devel Summary: Static libraries and C header files for libfixbuf Group: Applications/System Provides: libfixbuf-devel Requires: %{name} = %{version} Requires: pkgconfig >= 0.8 %description devel Static libraries and C header files for libfixbuf. %prep %setup -q -n %{name}-%{version} %build ./configure @RPM_CONFIG_FLAGS@ %{__make} %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{_bindir} %makeinstall %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc AUTHORS COPYING NEWS README %{_libdir}/*.a %{_libdir}/*.la %{_libdir}/*.so* %files devel %defattr(-,root,root) %doc doc/html %{_includedir}/* %{_libdir}/pkgconfig/* libfixbuf-1.7.1/m4/000755 000770 000024 00000000000 12606001063 016320 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/Makefile.am000644 000770 000024 00000003017 12545036674 020057 0ustar00emilyecoffmessagebus000000 000000 ## Process this file with automake to produce Makefile.in ## ------------------------------------------------------------------------ ## Makefile.am (toplevel) ## autotools build system for libfixbuf ## ------------------------------------------------------------------------ ## Copyright (C) 2005-2015 Carnegie Mellon University. All Rights Reserved. ## ------------------------------------------------------------------------ ## Authors: Brian Trammell ## ------------------------------------------------------------------------ ## GNU Lesser GPL Rights pursuant to Version 2.1, February 1999 ## Government Purpose License Rights (GPLR) pursuant to DFARS 252.227-7013 ## ------------------------------------------------------------------------ SUBDIRS = src include pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libfixbuf.pc include doxygen.am MOSTLYCLEANFILES = $(DX_CLEANFILES) ACLOCAL_AMFLAGS = -I m4 release-note-doc: NEWS $(top_srcdir)/doc/news2xhtml.pl ${PACKAGE_TARNAME} lgpl 10 < $(top_srcdir)/NEWS > doc/releases.xml make-doc-path: mkdir -p $(top_builddir)/doc/html copy-doxygen-doc: cp -pr doc/html $(distdir)/doc dist-hook: docs copy-doxygen-doc find $(distdir) -name .svn -type d -prune -exec rm -rf '{}' ';' distclean-local: rm -f $(top_builddir)/doc/releases.xml docs: make-doc-path doxygen-doc release-note-doc EXTRA_DIST = \ Doxyfile.in \ libfixbuf.spec \ libfixbuf.spec.in \ doc/Doxyhead.html \ doc/Doxyfoot.html \ doc/doxygen.css \ doc/news2xhtml.pl \ doc/LICENSE.txt libfixbuf-1.7.1/Makefile.in000644 000770 000024 00000106123 12605776213 020067 0ustar00emilyecoffmessagebus000000 000000 # Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Automake macro files. # Generate automatic documentation using Doxygen. Goals and variables values # are controlled by the various DX_COND_??? conditionals set by autoconf. # # The provided goals are: # doxygen-doc: Generate all doxygen documentation. # doxygen-run: Run doxygen, which will generate some of the documentation # (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post # processing required for the rest of it (PS, PDF, and some MAN). # doxygen-man: Rename some doxygen generated man pages. # doxygen-ps: Generate doxygen PostScript documentation. # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake goals. If # doxygen is used to generate man pages, you can achieve this integration by # setting man3_MANS to the list of man pages generated and then adding the # dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # This is usually added to MOSTLYCLEANFILES. VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/doxygen.am $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(top_srcdir)/include/fixbuf/config.h.in \ $(srcdir)/libfixbuf.pc.in $(srcdir)/libfixbuf.spec.in \ $(srcdir)/Doxyfile.in AUTHORS COPYING INSTALL NEWS README \ autoconf/compile autoconf/config.guess autoconf/config.sub \ autoconf/depcomp autoconf/install-sh autoconf/missing \ autoconf/ltmain.sh $(top_srcdir)/autoconf/compile \ $(top_srcdir)/autoconf/config.guess \ $(top_srcdir)/autoconf/config.sub \ $(top_srcdir)/autoconf/install-sh \ $(top_srcdir)/autoconf/ltmain.sh \ $(top_srcdir)/autoconf/missing subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ $(top_srcdir)/m4/ax_check_aligned_access_required.m4 \ $(top_srcdir)/m4/ax_prog_doxygen.m4 $(top_srcdir)/m4/debug.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/spread.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/fixbuf/config.h CONFIG_CLEAN_FILES = libfixbuf.pc libfixbuf.spec Doxyfile CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" DATA = $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUG_CFLAGS = @DEBUG_CFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DX_CONFIG = @DX_CONFIG@ DX_DOCDIR = @DX_DOCDIR@ DX_DOT = @DX_DOT@ DX_DOXYGEN = @DX_DOXYGEN@ DX_DVIPS = @DX_DVIPS@ DX_EGREP = @DX_EGREP@ DX_ENV = @DX_ENV@ DX_FLAG_chi = @DX_FLAG_chi@ DX_FLAG_chm = @DX_FLAG_chm@ DX_FLAG_doc = @DX_FLAG_doc@ DX_FLAG_dot = @DX_FLAG_dot@ DX_FLAG_html = @DX_FLAG_html@ DX_FLAG_man = @DX_FLAG_man@ DX_FLAG_pdf = @DX_FLAG_pdf@ DX_FLAG_ps = @DX_FLAG_ps@ DX_FLAG_rtf = @DX_FLAG_rtf@ DX_FLAG_xml = @DX_FLAG_xml@ DX_HHC = @DX_HHC@ DX_LATEX = @DX_LATEX@ DX_MAKEINDEX = @DX_MAKEINDEX@ DX_PDFLATEX = @DX_PDFLATEX@ DX_PERL = @DX_PERL@ DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIXBUF_REQ_LIBSCTP = @FIXBUF_REQ_LIBSCTP@ FIXBUF_REQ_LIBSPREAD = @FIXBUF_REQ_LIBSPREAD@ FIXBUF_REQ_LIBSSL = @FIXBUF_REQ_LIBSSL@ FIXBUF_REQ_SCTPDEV = @FIXBUF_REQ_SCTPDEV@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LDADD = @GLIB_LDADD@ GLIB_LIBS = @GLIB_LIBS@ GLIB_MKENUMS = @GLIB_MKENUMS@ GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCOMPAT = @LIBCOMPAT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPM_CONFIG_FLAGS = @RPM_CONFIG_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPREAD_CC_DEFINE = @SPREAD_CC_DEFINE@ SPREAD_CFLAGS = @SPREAD_CFLAGS@ SPREAD_LDFLAGS = @SPREAD_LDFLAGS@ SPREAD_LIBS = @SPREAD_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src include pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libfixbuf.pc @DX_COND_doc_TRUE@@DX_COND_html_TRUE@DX_CLEAN_HTML = @DX_DOCDIR@/html @DX_COND_chm_TRUE@@DX_COND_doc_TRUE@DX_CLEAN_CHM = @DX_DOCDIR@/chm @DX_COND_chi_TRUE@@DX_COND_chm_TRUE@@DX_COND_doc_TRUE@DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi @DX_COND_doc_TRUE@@DX_COND_man_TRUE@DX_CLEAN_MAN = @DX_DOCDIR@/man @DX_COND_doc_TRUE@@DX_COND_rtf_TRUE@DX_CLEAN_RTF = @DX_DOCDIR@/rtf @DX_COND_doc_TRUE@@DX_COND_xml_TRUE@DX_CLEAN_XML = @DX_DOCDIR@/xml @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@DX_PS_GOAL = doxygen-ps @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@DX_PDF_GOAL = doxygen-pdf @DX_COND_doc_TRUE@@DX_COND_latex_TRUE@DX_CLEAN_LATEX = @DX_DOCDIR@/latex @DX_COND_doc_TRUE@DX_CLEANFILES = \ @DX_COND_doc_TRUE@ -r \ @DX_COND_doc_TRUE@ @DX_DOCDIR@/@PACKAGE@.tag \ @DX_COND_doc_TRUE@ $(DX_CLEAN_HTML) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_CHM) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_CHI) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_MAN) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_RTF) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_XML) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_PS) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_PDF) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_LATEX) MOSTLYCLEANFILES = $(DX_CLEANFILES) ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ Doxyfile.in \ libfixbuf.spec \ libfixbuf.spec.in \ doc/Doxyhead.html \ doc/Doxyfoot.html \ doc/doxygen.css \ doc/news2xhtml.pl \ doc/LICENSE.txt all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/doxygen.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(srcdir)/doxygen.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): include/fixbuf/config.h: include/fixbuf/stamp-h1 @test -f $@ || rm -f include/fixbuf/stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/fixbuf/stamp-h1 include/fixbuf/stamp-h1: $(top_srcdir)/include/fixbuf/config.h.in $(top_builddir)/config.status @rm -f include/fixbuf/stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status include/fixbuf/config.h $(top_srcdir)/include/fixbuf/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f include/fixbuf/stamp-h1 touch $@ distclean-hdr: -rm -f include/fixbuf/config.h include/fixbuf/stamp-h1 libfixbuf.pc: $(top_builddir)/config.status $(srcdir)/libfixbuf.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libfixbuf.spec: $(top_builddir)/config.status $(srcdir)/libfixbuf.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-local distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-pkgconfigDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-pkgconfigDATA @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ cd @DX_DOCDIR@/latex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(MAKEINDEX_PATH) refman.idx; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ countdown=5; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ refman.log > /dev/null 2>&1 \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ && test $$countdown -gt 0; do \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ countdown=`expr $$countdown - 1`; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ done; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ cd @DX_DOCDIR@/latex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_MAKEINDEX) refman.idx; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ countdown=5; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ refman.log > /dev/null 2>&1 \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ && test $$countdown -gt 0; do \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ countdown=`expr $$countdown - 1`; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ done; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ mv refman.pdf ../@PACKAGE@.pdf @DX_COND_doc_TRUE@.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) @DX_COND_doc_TRUE@ $(DX_ENV) $(DX_DOXYGEN) $(DX_CONFIG) @DX_COND_doc_TRUE@doxygen-clean: @DX_COND_doc_TRUE@ rm -rf $(DX_CLEANFILES) release-note-doc: NEWS $(top_srcdir)/doc/news2xhtml.pl ${PACKAGE_TARNAME} lgpl 10 < $(top_srcdir)/NEWS > doc/releases.xml make-doc-path: mkdir -p $(top_builddir)/doc/html copy-doxygen-doc: cp -pr doc/html $(distdir)/doc dist-hook: docs copy-doxygen-doc find $(distdir) -name .svn -type d -prune -exec rm -rf '{}' ';' distclean-local: rm -f $(top_builddir)/doc/releases.xml docs: make-doc-path doxygen-doc release-note-doc # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libfixbuf-1.7.1/NEWS000644 000770 000024 00000025115 12605776121 016520 0ustar00emilyecoffmessagebus000000 000000 Version 1.7.1: 2105-10-09 ========================= Bug Fix for NetFlow v9 devices that implement Reverse Information Elements Version 1.7.0: 2015-07-01 ========================= Update IPFIX Information Elements to be compatible with IANA registry Add recursive freeing function fBufListFree() to free structured data elements Ignore extra filling bytes in sFlow records Bug Fix for NetFlow v9 Options Template Parsing Other Bug Fixes Version 1.6.2: 2014-12-03 ========================= Bug Fix for NetFlow v9 collectors with multiple streams Other Bug Fixes Version 1.6.1: 2014-10-14 ========================= Bug Fix for UDP connections that timeout frequently Version 1.6.0: 2014-09-29 ========================== New Support for sFlow Added support for decoding basicLists with unknown information elements New Template Callback Function Updated IPFIX Information Elements to be compatible with IANA registry Version 1.5.0: 2014-06-18 =========================== Updated IPFIX Information Elements to be compatible with IANA registry Added the ability to decode IPFIX from application's own data buffer Replaced select() with poll() for fbListeners. Applications will now bind to all addresses returned by getaddrinfo Added an InfoModel Iterator Removed fbListenerGroupWaitAcceptCallback() API function Removed fbListenerWaitAcceptCallback() API function Renamed IPFIX Structured Data Type Semantic #defines Bug Fix for NetFlow v9 Options Templates Other Bug Fixes Version 1.4.0: 2013-12-02 ============================ pyfixbuf, a python API for libfixbuf, is included as a separate package within the tarball (optional install) UDP IPFIX Listeners now reject IPFIX messages with invalid version numbers Added Environment Variable, FB_SUPPRESS_LOGS, to suppress NetFlow v9 log messages NetFlow v9 Options Templates and Records are now collected and translated to IPFIX. An fbInfoElement_st now contains all of the properties listed in RFC 5610. Added a macro, FB_IE_INIT_FULL, to define an Information Element with additional properties New API functions to create Options Templates/Records for encoding Information Element type information. New API functions to collect Information Element type records. New Template Callback for application to provide context to an incoming Template. IPFIX Elements updated to be compatible with IANA registry. NetFlow v9 compatible elements added to default Information Model. Version 1.3.0: 2013-03-08 ============================ Maintain count of missed NetFlow v9 export packets per session Added API function fbCollectorGetNetflowMissed to retrieve missed packet count IPFIX elements updated Spread Disconnect Bug fix Version 1.2.0: 2012-09-14 ============================ UDP Collection Enhancements. Manage UDP sessions by peer address and observation domain. Version 1.1.2: 2012-06-07 ============================ Bug Fixes. NetFlow v9 Bug Fixes. Version 1.1.1: 2011-12-22 ============================ Bug Fixes. Version 1.1.0: 2011-10-31 ============================ New IPFIX Elements NetFlow v9 Enhancements and bug fixes Version 1.0.2: 2011-09-12 ============================ Bug Fixes Version 1.0.1: 2011-06-01 ============================ Fix to maintain compatibility with GLib prior to version 2.10 Version 1.0.0: 2011-04-28 ============================= Added functionality to adhere to the proposed IPFIX extension: "Export of Structured Data in IPFIX". This proposed standard allows for the following three new data types. Added new data type: fbBasicList_t to house fixbuf "basicLists." Added new data type: fbSubTemplateList_t to house fixbuf "subTemplateLists." Added new data type: fbSubTemplateMultiList_t to house fixbuf "subTemplateMultiLists." Added the functionality to handle multiple listeners, allowing for connections on multiple ports. Support for Netflow V9. Spread support has been expanded to allow for greater flexibility in using one exporter to publish to multiple groups. Templates are now managed on a per-group basis for a Spread exporter. Templates can now be multicasted to select Spread groups. Default Automatic Mode for Listeners is now set to true. Many other bug fixes. Version 0.9.0: 2010-07-27 ============================== Added support for Spread Toolkit to allow publish subscribe distribution of YAF sensor output. Version 0.8.0: 2008-09-09 ================================= Addition of NetFlow v9 input translation on network connections. NetFlow v9 only works as a collector (listener) and only over UDP. (Most of those limitations are related to the nature of the NetFlow protocol itself.) Version 0.7.2: 2008-01-18 ================================= Minor build system change required to fix multithreaded fixbuf collection issues with skipfix in SiLK 0.11.9 and later. Version 0.7.1: 2007-09-28 =================================== Fixes encoding errors of octet array information elements on little-endian machines. Version 0.7.0: 2007-08-17 ================================ Fixes alignment issues on Solaris/SPARC; cross-platform build enhancements; support for - as stdin/stdout filename; partial flexible stream selection support; true biflow reverse PEN support. Version 0.6.0: 2007-05-17 ============================= libfixbuf 0.6.0 completely reorganizes the API to recenter it around an IPFIX Message Buffer object. It adds new, more flexible interfaces to lower level transport for building IPFIX Collecting and Exporting Processes, including a select()-based listener interface for multi-session collectors; support for SCTP and TLS over TCP as transport protocols; and support for reverse PEN based bidirectional flow export as in draft-ietf-ipfix-biflow-03. Storage of IPFIX Messages in files is supported, but the final message and final set support as in revision -00 of draft-trammell-ipfix-file has been removed. This release also renames all the calls and data structures to be in line with the conventions used in the NetSA SiLK codebase, and is therefore completely incompatible with previous releases; applications must be rewritten to use fixbuf 0.6.0. Version 0.5.0: 2006-09-29 =================================== libfixbuf 0.5.0 splits the API into application programming interface and transport programming interface, and adds new transport layers for TCP, UDP, and files. Version 0.4.1: 2006-07-07 ============================= libfixbuf 0.4.1 adds a new Information Element for YAF 0.1.6. Version 0.4.0: 2006-06-16 =============================== libfixbuf 0.4.0 is a bugfix and feature enhancement release. The FixSession structure has been removed, to store templates per FixReader or FixWriter instance. This was done to support per-session (transient) scoping of template IDs. This is an incompatible API change; fixbuf applications will have to be updated to use the new 0.4.0 API. Version 0.3.2: 2006-03-17 =============================== libfixbuf 0.3.2 is a bugfix release. Transcode plan caching now works properly. Version 0.3.1: 2006-03-14 =============================== libfixbuf 0.3.1 is a bugfix and feature enhancement release. Support now exists for full template table export, to comply with periodic template export requirements in the IPFIX protocol. Reduced-length information element encoding is now supported, as well, with full transcoder support for transcoding between identical information elements of different arbitrary lengths. Version 0.3.0: 2006-02-03 ================================= libfixbuf 0.3.0 adds an information element registry, changing the way that information elements are programmatically added to templates. New information elements have been added to support YAF. Also new is FixVarfield, a much more usable interface for transcoding variable-length information elements. Variable-length transcoding support has been completely rewritten and tested. fixport and fixcollect have been removed; the upcoming YAF IPFIX export and collection facility will take their place. Corner-case bugs in the writer and transcoder have been fixed as well. Version 0.2.0: 2006-01-06 ================================ libfixbuf 0.2.0 is a redesign of the libfixbuf API, renaming most calls. It adds MTU support for splitting record streams into multiple messages, built-in UDP export and collection support. Two new applications, fixport and fixcollect, are now provided for UDP export and collection. Additionally, this version modifies the API for handling private enterprise information elements, and adds new CERT private enterprise information elements for biflow support in NAF 0.4.2. Version 0.1.1: 2005-11-18 ================================= libfixbuf 0.1.1 is a bugfix release, fixing a read buffer reset bug that kept libfixbuf from reading multiple messages with the same reader. Version 0.1.0: 2005-10-31 ================================= libfixbuf 0.1.0 splits its session template table into "read" and "write" sides, to avoid template number space collisions when writing IPFIX filters using libfixbuf. It also splits calls to its low-level I/O functions to support future UDP and SCTP low-level I/O for IPFIX compliance. Alpha quality warnings still apply, though the API should be settling down soon. Version 0.0.7: 2005-10-03 ================================ libfixbuf 0.0.7 extends the FloCON preview release with Options Template Set support, (still untested but otherwise complete) variable-length information element support, and a few new information elements to support NAF 0.0.7. The library is still undocumented, and should still be considered alpha-quality. Version 0.0.3: 2005-09-16 =================================== libfixbuf 0.0.3 is the FloCON Developers' Preview Release of libfixbuf. This revision of libfixbuf is a partial implementation of the IPFIX protocol message format (as of September 2005) with support for long messages and sets as outlined in IETF individual draft draft-trammell-ipfix-file-00. Important features are missing, including: * Options Template Set support * Variable-length information element support (partial, untested) In addition, the API for this version is not documented, because it will change. Specificially: * Sessions support for information element registries, including type information for each information element number. This will allow libfixbuf to handle endian conversion, among other things. * Transcoder support for information element value translation within the context of a message; e.g. relative to absolute flow times, flow times to time and duration, etc. * Any other commentary received on API usability during or after FloCON will be considered, and identified issues addressed. See the README file for more on using libfixbuf. libfixbuf-1.7.1/README000644 000770 000024 00000014426 12545036674 016711 0ustar00emilyecoffmessagebus000000 000000 libfixbuf aims to be a compliant implementation of the IPFIX Protocol, as defined in the "Specification of the IPFIX Protocol for the Export of IP Flow Information" (RFC 5101). It supports the information model defined in "Information Model for IP Flow Information Export" (RFC 5102), extended as proposed by "Bidirectional Flow Export using IPFIX" (RFC 5103) to support information elements for representing biflows. libfixbuf supports UDP, TCP, SCTP, TLS over TCP, and Spread as transport protocols. Support for DTLS over UDP and DTLS over SCTP is forthcoming. It also supports operation as an IPFIX File Writer or IPFIX File Reader as defined in "An IPFIX-Based File Format" (draft-trammell-ipfix-file, current revision -05). libfixbuf version 1.0 supports structured data elements as described in "Export of Structured Data in IPFIX" (RFC 6313). This adds the ability to export basicLists, subTemplateLists, and subTemplateMultiLists. libfixbuf version 1.4 adds support for exporting type information for IPFIX elements as described in "Exporting Type Information for IPFIX Information Elements. (RFC 5610)." This expands the definition of an Information Element in the Information Model. In addition to the PEN, length, name, and ID, an Information Element can also have a data type, description, range, semantics, and units. An Options Template can be exported to define Information Element Type Records. New API Functions have been added to create and write these types of Options Records, as well as collect elements of this type so that Information Elements may be added to the Information Model as we receive them from the Exporting process. See public.h for more information. As of version 1.0, libfixbuf has support for NetFlow V9. libfixbuf converts the NetFlow v9 to IPFIX by changing the version number, dropping the sysUpTime from the header and converting postOctetDeltaCount to reverseOctetDeltaCount and postPacketDeltaCount to reversePacketDeltaCount as described in RFC 5103. In order for tools to properly make use of Information Elements that are offsets of the sysUpTime (flowStartSysUpTime), libfixbuf adds Information Element 160, systemInitTimeMilliseconds, to any template (and corresponding records) that contain either flowStartSysUpTime or flowEndSysUpTime. For any element that does not exist in libfixbuf's default Information Model (above ID 346), libfixbuf will convert this Information Element to "ciscoNetflowGeneric" (ID 9999) in the template. The only exceptions are the "NF_F_FW_EXT_EVENT" and "NF_F_FW_EVENT", often exported from Cisco's ASA Device (http://www.cisco.com/en/US/docs/security/asa/asa82/netflow/netflow.html), which will be converted to separate elements 9997 and 9998 respectively. Similarly, the Cisco ASA will often export elements 40001, 40002, 40003, and 40004. These elements are substituted with the IPFIX elements 225, 226, 227, and 228 respectively. Version 1.4 adds support for NetFlow v9 options template and record retrieval and conversion to IPFIX. The options scope type is converted to IE, messageScope. To disable NetFlow v9 log messages such as sequence number mismatch messages and record count discrepancy messages, run `make clean`, `CFLAGS="-DFB_SUPPRESS_LOGS=1" make -e`, `make install` when installing libfixbuf. Version 1.4 also adds a Python API for libfixbuf, pyfixbuf. pyfixbuf can be used to write applications, often called mediators, that collect and/or export IPFIX. pyfixbuf supports UDP and TCP as transport protocols, as well as file writing and reading. pyfixbuf requires netsa-python version 1.4 or later and should be installed before building and installing pyfixbuf. pyfixbuf does not automatically install when installing libfixbuf. Building and installing pyfixbuf is done using the standard setup.py mechanism. See pyfixbuf/README.txt for more information. Version 1.6 adds support for translating sFlow into IPFIX. libfixbuf only supports sFlow v5. libfixbuf will process Flow Samples (1), Extended Flow Samples (3), Counter Samples (2), and Extended Counter Samples (4). Any other format will return an FB_ERROR_SFLOW. Fixbuf translates sFlow records into a fixed IPFIX record for flow and counter records. A full description of the fields fixbuf exports for sFlow records is located in include/fixbuf/public.h. libfixbuf's public API is defined in public.h; see the documentation of that file for general documentation on getting started with libfixbuf, as well as detailed documentation on the public API calls and data types. libfixbuf API documentation is available in doc/html. Building -------- libfixbuf uses a reasonably standard autotools-based build system. The customary build procedure (./configure && make && make install) should work in most environments. libfixbuf requires glib-2.0 version 2.6.4 or later. If built against version 2.10 or later, it will automatically use the glib slab allocator for increased memory allocation performance. glib is available on most modern Linux distributions and BSD ports collections, or in source form from http://www.gtk.org. libfixbuf automatically uses the getaddrinfo(3) facility and the accompanying dual IPv4/IPv6 stack support if present. getaddrinfo(3) must be present to export or collect flows over IPv6. libfixbuf does not build with SCTP support by default. The --with-sctp option must be given to the libfixbuf ./configure script to include SCTP support. Also note that SCTP requires kernel support, and applications built against libfixbuf with libsctp may fail at runtime if that kernel support is not present. libfixbuf does not build with TLS support by default. The --with-openssl option must be given to the libfixbuf ./configure script to include TLS support. Known Issues ------------ The following are known issues with libfixbuf as of version 1.0.0: * There is no support for DTLS over UDP or DTLS over SCTP transport. * There is no support for application-selectable SCTP stream assignment or SCTP partial reliability. Templates are sent reliably on stream 0, and data sets are sent reliably on stream 1. * There is no automatic support for periodic template retransmission or periodic template expiration as required when transporting IPFIX over UDP. Applications using libfixbuf to transport IPFIX messages over UDP must maintain these timeouts and manually manage the session. libfixbuf-1.7.1/src/000755 000770 000024 00000000000 12606001063 016567 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/src/fbcollector.c000644 000770 000024 00000147753 12545036674 021274 0ustar00emilyecoffmessagebus000000 000000 /** @internal ** ** ** @file fbcollector.c ** IPFIX Collecting Process single transport session implementation ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2014 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ /*#define _GNU_SOURCE*/ #define _FIXBUF_SOURCE_ #include #include "fbcollector.h" #ident "$Id$" /*################################################# * * IPFIX functions for reading input, these are * the default functions * *#################################################*/ /** * fbCollectorDecodeMsgVL * * decodes the header of a variable length message to determine * how long the message is in order to read the appropriate * amount to complete the message * * * @return FALSE on error, TRUE on success */ static gboolean fbCollectorDecodeMsgVL( fbCollector_t *collector, fbCollectorMsgVL_t *hdr, size_t b_len, uint16_t *m_len, GError **err) { uint16_t h_version; uint16_t h_len; /* collector is unused in this function*/ (void)collector; h_version = g_ntohs(hdr->n_version); if (h_version != 0x000A) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message version 0x%04x; " "input is probably not an IPFIX Message stream.", g_ntohs(hdr->n_version)); *m_len = 0; return FALSE; } h_len = g_ntohs(hdr->n_len); if (h_len < 16) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message length 0x%04x; " "input is probably not an IPFIX Message stream.", g_ntohs(hdr->n_len)); *m_len = 0; return FALSE; } if (b_len && (h_len > b_len)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ, "Buffer too small to read IPFIX Message " "(message size %hu, buffer size %u).", h_len, (uint32_t)b_len); *m_len = 0; return FALSE; } *m_len = h_len; return TRUE; } /* * fbCollectMessageBuffer * * decodes the header of a variable length message to determine * how long the message is. * this is used for applications that wants to handle the * connection (reading, shutdown, etc.) itself. * An error FB_ERROR_BUFSZ means that the the buffer does not * contain a full message and an additional read should * occur. * * @return FALSE on error, TRUE on success */ gboolean fbCollectMessageBuffer( uint8_t *hdr, size_t b_len, size_t *m_len, GError **err) { fbCollectorMsgVL_t *iphdr = (fbCollectorMsgVL_t *)hdr; uint16_t h_version; uint16_t h_len; if (!hdr || (b_len < 16)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ, "Buffer length too small to contain IPFIX header" "(buffer size %u).", (uint32_t)b_len); *m_len = 0; return FALSE; } h_version = g_ntohs(iphdr->n_version); if (h_version != 0x000A) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message version 0x%04x; " "input is probably not an IPFIX Message stream.", g_ntohs(iphdr->n_version)); *m_len = 0; return FALSE; } h_len = g_ntohs(iphdr->n_len); if (h_len < 16) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message length 0x%04x; " "input is probably not an IPFIX Message stream.", g_ntohs(iphdr->n_len)); *m_len = 0; return FALSE; } if (h_len > b_len) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ, "Buffer too small to contain IPFIX Message " "(message size %hu, buffer size %u).", h_len, (uint32_t)b_len); *m_len = 0; return FALSE; } *m_len = h_len; return TRUE; } /** * fbCollectorMessageHeaderNull * * this is used to process a PDU after it has been read in a message * based transport protocol (UDP, SCTP) to adjust the header if * needed before sending it to post read fixing. This version does * nothing. NULL transform. * * @param collector pointer to the collector state structure * @param buffer pointer to the message buffer * @param b_len length of the buffer passed in * @param m_len pointer to the length of the resultant buffer * @param err pointer to a GLib error structure * * @return TRUE (this always works) * */ static gboolean fbCollectorMessageHeaderNull ( fbCollector_t *collector __attribute__((unused)), uint8_t *buffer __attribute__((unused)), size_t b_len, uint16_t *m_len, GError **err __attribute__((unused)) ) { *m_len = b_len; return TRUE; } /** * fbCollectorUDPMessageHeader * * this is used to process a PDU after it has been read in a message * based transport protocol (UDP, SCTP) to adjust the header if * needed before sending it to post read fixing. This version does * nothing. NULL transform. * * @param collector pointer to the collector state structure * @param buffer pointer to the message buffer * @param b_len length of the buffer passed in * @param m_len pointer to the length of the resultant buffer * @param err pointer to a GLib error structure * * @return TRUE (this always works) * */ static gboolean fbCollectorUDPMessageHeader ( fbCollector_t *collector, uint8_t *buffer, size_t b_len, uint16_t *m_len, GError **err) { uint16_t h_version; *m_len = b_len; if (b_len > 16) { if (!fbCollectorHasTranslator(collector)) { h_version = g_ntohs(*(uint16_t *)buffer); if (h_version != 0x000A) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message Version 0x%04x", h_version); return FALSE; } } collector->obdomain = g_ntohl(*(uint32_t *)(buffer + 12)); /* Update collector time */ collector->time = time(NULL); } return TRUE; } /** * fbCollectorPostProcNull * * this is used to process a PDU after it has been read in order to transform * it, except that this function does _no_ transforms * * @param collector _not used_ * * @return TRUE (always succesfull) * */ static gboolean fbCollectorPostProcNull( fbCollector_t *collector, uint8_t *dataBuf, size_t *bufLen, GError **err) { (void)collector; (void)dataBuf; (void)bufLen; (void)err; return TRUE; } /** * fbCollectorCloseTranslatorNull * * default function to clean up the translator state, but there is * none, and this function does nothing * * @param collector current collector * */ static void fbCollectorCloseTranslatorNull( fbCollector_t *collector) { (void)collector; return; } /** * fbCollectorSessionTimeoutNull * * default function to clean up timed out UDP sessions. * this function does nothing * * @param collector current collector * @param session session that will be timed out * */ static void fbCollectorSessionTimeoutNull( fbCollector_t *collector, fbSession_t *session) { (void)collector; (void)session; return; } /*################################################# * * the rest of the meat of the collector implementation * *#################################################*/ /** * fbCollectorReadFile * * * */ static gboolean fbCollectorReadFile( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { int rc; uint16_t h_len; gboolean goodLen; /* Read and decode version and length */ g_assert(*msglen > 4); rc = fread(msgbase, 1, 4, collector->stream.fp); if (rc > 0) { goodLen = collector->coreadLen(collector,(fbCollectorMsgVL_t *)msgbase, *msglen, &h_len, err); if (FALSE == goodLen) return FALSE; msgbase += 4; } else if (feof(collector->stream.fp)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "I/O error: %s", strerror(errno)); return FALSE; } /* read rest of message */ rc = fread(msgbase, 1, h_len - 4, collector->stream.fp); if (rc > 0) { *msglen = rc + 4; if (!collector->copostRead(collector, msgbase, msglen, err)) { return FALSE; } return TRUE; } else if (feof(collector->stream.fp)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "I/O error: %s", strerror(errno)); return FALSE; } } /** * fbCollectorCloseFile * * * */ static void fbCollectorCloseFile( fbCollector_t *collector) { if (collector->stream.fp != stdin) { fclose(collector->stream.fp); } collector->active = FALSE; } /** * fbCollectorAllocFP * * * */ fbCollector_t *fbCollectorAllocFP( void *ctx, FILE *fp) { fbCollector_t *collector = NULL; /* Create a new collector */ collector = g_slice_new0(fbCollector_t); /* Fill the collector in */ collector->ctx = ctx; collector->stream.fp = fp; collector->bufferedStream = TRUE; collector->active = TRUE; collector->coread = fbCollectorReadFile; collector->copostRead = fbCollectorPostProcNull; collector->coreadLen = fbCollectorDecodeMsgVL; collector->comsgHeader = fbCollectorMessageHeaderNull; collector->cotransClose = fbCollectorCloseTranslatorNull; collector->cotimeOut = fbCollectorSessionTimeoutNull; collector->translationActive = FALSE; collector->rip = -1; collector->wip = -1; /* All done */ return collector; } /** * fbCollectorAllocFile * * * */ fbCollector_t *fbCollectorAllocFile( void *ctx, const char *path, GError **err) { fbCollector_t *collector = NULL; FILE *fp = NULL; /* check to see if we're opening stdin */ if ((strlen(path) == 1) && (path[0] == '-')) { /* don't open a terminal */ if (isatty(fileno(stdin))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Refusing to open stdin terminal for collection"); return NULL; } /* yep, stdin */ fp = stdin; } else { /* nope, just a regular file; open it. */ fp = fopen(path, "r"); } /* check for error */ if (!fp) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Couldn't open %s for collection: %s", path, strerror(errno)); return NULL; } /* allocate a collector */ collector = fbCollectorAllocFP(ctx, fp); /* set the file close function */ collector->coclose = fbCollectorCloseFile; /* set the default collector function */ collector->copostRead = fbCollectorPostProcNull; /* default translator cleanup function */ collector->cotransClose = fbCollectorCloseTranslatorNull; /* set the default message read length function */ collector->coreadLen = fbCollectorDecodeMsgVL; /* set the default message header transform function */ collector->comsgHeader = fbCollectorMessageHeaderNull; /* set the default session timed out function - won't get called */ collector->cotimeOut = fbCollectorSessionTimeoutNull; /* mark the stream if it is a buffered file pointer */ collector->bufferedStream = TRUE; /* set that a input translator is not in use */ collector->translationActive = FALSE; /* since we're not a listener */ collector->rip = -1; collector->wip = -1; /* all done */ return collector; } #if FB_ENABLE_SCTP /** * fbCollectorReadSCTP * * * */ static gboolean fbCollectorReadSCTP( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { uint16_t msgSize; struct sockaddr peer; socklen_t peerlen = sizeof(peer); struct sctp_sndrcvinfo sri; int sctp_flags = 0; int rc; rc = sctp_recvmsg(collector->stream.fd, msgbase, *msglen, &peer, &peerlen, &sri, &sctp_flags); if (rc > 0) { if (!collector->comsgHeader(collector, msgbase, rc, &msgSize, err)) { return FALSE; } *msglen = msgSize; if (!collector->copostRead(collector, msgbase, msglen, err)) { return FALSE; } return TRUE; } else if (rc == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file"); return FALSE; } else if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "SCTP read interrupt"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "TCP I/O error: %s", strerror(errno)); return FALSE; } } #endif /* FB_ENABLE_SCTP */ static int fbCollectorHandleSelect( fbCollector_t *collector) { fd_set rdfds; int maxfd; int count; int retVal = 0; uint8_t byte; g_assert(collector); if (collector->rip > collector->stream.fd) { maxfd = collector->rip; } else { maxfd = collector->stream.fd; } maxfd++; FD_ZERO(&rdfds); FD_SET(collector->rip, &rdfds); FD_SET(collector->stream.fd, &rdfds); count = select(maxfd, &rdfds, NULL, NULL, NULL); if (count) { if (FD_ISSET(collector->stream.fd, &rdfds)) { retVal = 0; } if (FD_ISSET(collector->rip, &rdfds)) { read(collector->rip, &byte, sizeof(byte)); return -1; } return retVal; } else { return -1; } } /** * fbCollectorReadTCP * * * */ static gboolean fbCollectorReadTCP( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { int rc; uint16_t h_len, rrem; gboolean goodLen; /* Read and decode version and length */ g_assert(*msglen > 4); rrem = 4; while (rrem) { rc = fbCollectorHandleSelect(collector); if (rc < 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Interrupted by pipe"); /* interrupted by pipe read or other error with select*/ return FALSE; } rc = read(collector->stream.fd, msgbase, rrem); if (rc > 0) { rrem -= rc; msgbase += rc; } else if (rc == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file"); return FALSE; } else if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "TCP read interrupt at message start"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "TCP I/O error: %s", strerror(errno)); return FALSE; } } goodLen = collector->coreadLen(collector, (fbCollectorMsgVL_t *)(msgbase - 4), *msglen, &h_len, err); if (FALSE == goodLen) return FALSE; /* read rest of message */ rrem = h_len - 4; while (rrem) { rc = fbCollectorHandleSelect(collector); if (rc < 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Interrupted by pipe"); /* interrupted by pipe read or other error with select*/ return FALSE; } rc = read(collector->stream.fd, msgbase, rrem); if (rc > 0) { rrem -= rc; msgbase += rc; } else if (rc == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file"); return FALSE; } else if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "TCP read interrupt in message"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "TCP I/O error: %s", strerror(errno)); return FALSE; } } /* Post process, if needed and return message length from header. */ *msglen = h_len; if (!collector->copostRead(collector, msgbase, msglen, err)) { return FALSE; } return TRUE; } static void fbCollectorSetUDPSpec( fbCollector_t *collector, fbUDPConnSpec_t *spec) { if (collector->udp_head == NULL) { collector->udp_head = spec; collector->udp_tail = spec; } else if (collector->udp_head != spec) { /* don't pick if it's new */ if (spec->prev || spec->next) { /* connect last to next */ if (spec->prev) { spec->prev->next = spec->next; } /* connect next to last last */ if (spec->next) { spec->next->prev = spec->prev; } else { collector->udp_tail = spec->prev; } spec->prev = NULL; fbListenerSetPeerSession(collector->listener, spec->session); } /* now set it in the front */ spec->next = collector->udp_head; collector->udp_head->prev = spec; collector->udp_head = spec; } } static void fbCollectorFreeUDPSpec( fbCollector_t *collector, fbUDPConnSpec_t *spec) { /* let translators release state */ collector->cotimeOut(collector, spec->session); /* don't free the last session, fbufree will do that */ if (collector->udp_tail != collector->udp_head) { fbSessionFree(spec->session); } if (collector->udp_tail == spec) { if (spec->prev) { collector->udp_tail = spec->prev; spec->prev->next = NULL; } else { collector->udp_tail = NULL; } } if (collector->multi_session) { fbListenerAppFree(collector->listener, spec->ctx); } g_slice_free(fbUDPConnSpec_t, spec); } /** * fbCollectorVerifyUDPPeer * * * */ static gboolean fbCollectorVerifyUDPPeer( fbCollector_t *collector, struct sockaddr *from, socklen_t fromlen, GError **err) { fbUDPConnSpec_t *udp = collector->udp_head; gboolean found = FALSE; /* stash the address if we've not seen it before */ /* compare the address if we have */ /* appinit should simulate no data (NLREAD) if message is from wrong peer*/ if (collector->accept_only) { if (collector->peer.so.sa_family == from->sa_family) { if (from->sa_family == AF_INET) { if (memcmp(&(collector->peer.ip4.sin_addr), &(((struct sockaddr_in *)from)->sin_addr), sizeof(struct in_addr))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Ignoring message from peer"); return FALSE; } } else if (from->sa_family == AF_INET6) { if(memcmp(&(collector->peer.ip6.sin6_addr), &(((struct sockaddr_in6 *)from)->sin6_addr), sizeof(struct in6_addr))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Ignoring message from peer"); return FALSE; } } } } else { memcpy(&(collector->peer.so), from, (fromlen > sizeof(collector->peer)) ? sizeof(collector->peer) : fromlen); } while (udp) { /* loop through and find current one */ if (udp->obdomain == collector->obdomain) { if (!memcmp(&(udp->peer.so), from, udp->peerlen)) { /* we have a match - set session */ fbCollectorSetUDPSpec(collector, udp); found = TRUE; break; } } udp = udp->next; } if (!found) { udp = g_slice_new0(fbUDPConnSpec_t); memcpy(&(udp->peer.so), from, (fromlen > sizeof(udp->peer)) ? sizeof(udp->peer) : fromlen); udp->peerlen = (fromlen > sizeof(udp->peer)) ? sizeof(udp->peer) : fromlen; udp->obdomain = collector->obdomain; /* create a new session */ udp->session = fbListenerSetPeerSession(collector->listener, NULL); fbCollectorSetUDPSpec(collector, udp); /* call app init for new UDP connection*/ if (collector->multi_session) { if (!fbListenerCallAppInit(collector->listener, udp, err)) { udp->last_seen = collector->time; udp->reject = TRUE; return FALSE; } } else { /* backwards compatibility -> need to associate the ctx with all sessions */ udp->ctx = collector->ctx; } } else { if (udp->reject) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Rejecting previously rejected connection"); return FALSE; } } collector->ctx = udp->ctx; udp->last_seen = collector->time; while (collector->udp_tail && (difftime(collector->time, collector->udp_tail->last_seen) > FB_UDP_TIMEOUT)) { /* timeout check */ fbCollectorFreeUDPSpec(collector, collector->udp_tail); } return TRUE; } /** * fbCollectorReadUDP * * * */ static gboolean fbCollectorReadUDP( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { uint16_t msgSize = 0; ssize_t recvlen = 0; int rc; union { struct sockaddr so; struct sockaddr_in ip4; struct sockaddr_in6 ip6; } peer; socklen_t peerlen; memset(&peer, 0, sizeof(peer)); rc = fbCollectorHandleSelect(collector); if (rc < 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Interrupted by pipe"); /* interrupted by pipe read or other error with select*/ return FALSE; } peerlen = sizeof(peer); recvlen = recvfrom(collector->stream.fd, msgbase, *msglen, 0, (struct sockaddr *)&peer, &peerlen); if (peer.so.sa_family == AF_INET && !collector->stream_by_port) { peer.ip4.sin_port = 0; } else if (peer.so.sa_family == AF_INET6) { if (!collector->stream_by_port) peer.ip6.sin6_port = 0; peer.ip6.sin6_flowinfo = 0; peer.ip6.sin6_scope_id = 0; } if (!collector->comsgHeader(collector, msgbase, recvlen, &msgSize, err)) { return FALSE; } if (msgSize > 0) { *msglen = msgSize; /** Fixed this to do the right thing. We now map ip addresses * and observation domains to sessions. If accept-only is set * on the collector, we'll only return TRUE if the ips match. * We will return NL_READ if FALSE, and the app using fixbuf * should ignore error codes = NL_READ.**/ /* this will only veto if we set accept from explicitly*/ if (!fbCollectorVerifyUDPPeer(collector, &(peer.so), peerlen, err)) { return FALSE; } if (!collector->copostRead(collector, msgbase, msglen, err)) { return FALSE; } return TRUE; } else if (errno == EINTR || errno == EWOULDBLOCK) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "UDP read interrupt or timeout"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "UDP I/O error: %s", strerror(errno)); return FALSE; } } /** * fbCollectorCloseSocket * * * */ static void fbCollectorCloseSocket( fbCollector_t *collector) { if (collector->stream.fd != -1) { close(collector->stream.fd); /* don't set to -1 because we need it to remove listener */ } if (collector->rip != -1) { close(collector->rip); collector->rip = -1; } if (collector->wip != -1) { close(collector->wip); collector->wip = -1; } collector->active = FALSE; } /** * fbCollectorAllocSocket * * * */ fbCollector_t *fbCollectorAllocSocket( fbListener_t *listener, void *ctx, int fd, struct sockaddr *peer, size_t peerlen) { fbCollector_t *collector = NULL; fbConnSpec_t *spec = fbListenerGetConnSpec(listener); int pfd[2]; /* Create a new collector */ collector = g_slice_new0(fbCollector_t); /* Fill it in */ collector->listener = listener; collector->ctx = ctx; collector->stream.fd = fd; collector->bufferedStream = FALSE; collector->active = TRUE; collector->copostRead = fbCollectorPostProcNull; collector->coreadLen = fbCollectorDecodeMsgVL; collector->comsgHeader = fbCollectorMessageHeaderNull; collector->coclose = fbCollectorCloseSocket; collector->cotransClose = fbCollectorCloseTranslatorNull; collector->cotimeOut = fbCollectorSessionTimeoutNull; collector->translationActive = FALSE; collector->multi_session = FALSE; /* Create interrupt pipe */ if (pipe(pfd)) { return NULL; } collector->rip = pfd[0]; collector->wip = pfd[1]; if (peerlen) { memcpy(&(collector->peer.so), peer, (peerlen > sizeof(collector->peer)) ? sizeof(collector->peer) : peerlen); } /* Select a reader function */ switch(spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: collector->coread = fbCollectorReadSCTP; break; #endif case FB_TCP: collector->coread = fbCollectorReadTCP; break; case FB_UDP: collector->coread = fbCollectorReadUDP; collector->comsgHeader = fbCollectorUDPMessageHeader; break; default: g_assert_not_reached(); } /* All done */ return collector; } #if HAVE_OPENSSL /** * fbCollectorReadTLS * * * */ static gboolean fbCollectorReadTLS( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { int rc; uint16_t h_len, rrem; gboolean rv; /* Read and decode version and length */ g_assert(*msglen > 4); rrem = 4; while (rrem) { rc = SSL_read(collector->ssl, msgbase, rrem); if (rc > 0) { rrem -= rc; msgbase += rc; } else if (rc == 0) { /* FIXME this isn't _quite_ robust but it's good enough for now. we'll fix this when we do TLS/TCP stress testing. */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "TLS connection shutdown"); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "TLS I/O error at message start: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); return FALSE; } } rv = collector->coreadLen(collector, (fbCollectorMsgVL_t *)(msgbase - 4), *msglen, &h_len, err); if (rv == FALSE) return FALSE; /* read rest of message */ rrem = h_len - 4; while (rrem) { rc = SSL_read(collector->ssl, msgbase, rrem); if (rc > 0) { rrem -= rc; msgbase += rc; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "TLS I/O error in message: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); return FALSE; } } /* All done. Return message length from header. */ *msglen = h_len; return TRUE; } /** * fbCollectorCloseTLS * * * */ static void fbCollectorCloseTLS( fbCollector_t *collector) { SSL_shutdown(collector->ssl); SSL_free(collector->ssl); if (collector->rip != -1) { close(collector->rip); collector->rip = -1; } if (collector->wip != -1) { close(collector->wip); collector->wip = -1; } collector->active = FALSE; } /** * fbCollectorOpenTLS * * * */ static gboolean fbCollectorOpenTLS( fbCollector_t *collector, GError **err) { fbConnSpec_t *spec = fbListenerGetConnSpec(collector->listener); BIO *conn; gboolean ok = TRUE; /* Initialize SSL context if necessary */ if (!spec->vssl_ctx) { if (!fbConnSpecInitTLS(spec, TRUE, err)) { return FALSE; } } /* wrap a stream BIO around the opened socket */ if (!(conn = BIO_new_socket(collector->stream.fd, 1))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't wrap socket for TLS: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* create SSL socket */ if (!(collector->ssl = SSL_new((SSL_CTX *)spec->vssl_ctx))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldnt create TLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* accept SSL connection */ SSL_set_accept_state(collector->ssl); SSL_set_bio(collector->ssl, conn, conn); SSL_set_mode(collector->ssl, SSL_MODE_AUTO_RETRY); if (SSL_accept(collector->ssl) <= 0) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't accept on connected TLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* FIXME do post-connection verification */ end: if (!ok) { collector->active = FALSE; if (collector->ssl) { SSL_free(collector->ssl); collector->ssl = NULL; } else if (conn) { BIO_vfree(conn); } } return ok; } #if HAVE_OPENSSL_DTLS /** * fbCollectorOpenDTLS * * * */ static gboolean fbCollectorOpenDTLS( fbCollector_t *collector, GError **err) { fbConnSpec_t *spec = fbListenerGetConnSpec(collector->listener); BIO *conn; gboolean ok = TRUE; /* Initialize SSL context if necessary */ if (!spec->vssl_ctx) { if (!fbConnSpecInitTLS(spec, TRUE, err)) { return FALSE; } } /* wrap a stream BIO around the opened socket */ if (!(conn = BIO_new_dgram(collector->stream.fd, 1))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't wrap socket for TLS: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* create SSL socket */ if (!(collector->ssl = SSL_new((SSL_CTX *)spec->vssl_ctx))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldnt create TLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Enable cookie exchange */ SSL_set_options(collector->ssl, SSL_OP_COOKIE_EXCHANGE); /* accept SSL connection */ SSL_set_bio(collector->ssl, conn, conn); SSL_set_accept_state(collector->ssl); SSL_set_mode(collector->ssl, SSL_MODE_AUTO_RETRY); if (SSL_accept(collector->ssl) <= 0) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't accept on connected TLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* FIXME do post-connection verification */ end: if (!ok) { collector->active = FALSE; if (collector->ssl) { SSL_free(collector->ssl); collector->ssl = NULL; } else if (conn) { BIO_vfree(conn); } } return ok; } #endif /* HAVE_OPENSSL_DTLS */ /** * fbCollectorAllocTLS * * * */ fbCollector_t *fbCollectorAllocTLS( fbListener_t *listener, void *ctx, int fd, struct sockaddr *peer, size_t peerlen, GError **err) { gboolean ok = TRUE; fbCollector_t *collector = NULL; fbConnSpec_t *spec = fbListenerGetConnSpec(listener); /* Create a new collector */ collector = g_slice_new0(fbCollector_t); /* Fill it in */ collector->listener = listener; collector->ctx = ctx; collector->stream.fd = fd; collector->bufferedStream = FALSE; collector->active = TRUE; collector->copostRead = fbCollectorPostProcNull; collector->coreadLen = fbCollectorDecodeMsgVL; collector->comsgHeader = fbCollectorMessageHeaderNull; collector->coread = fbCollectorReadTLS; collector->coclose = fbCollectorCloseTLS; collector->cotransClose = fbCollectorCloseTranslatorNull; collector->cotimeOut = fbCollectorSessionTimeoutNull; collector->translationActive = FALSE; if (peerlen) { memcpy(&(collector->peer.so), peer, (peerlen > sizeof(collector->peer)) ? sizeof(collector->peer) : peerlen); } /* Do TLS accept atop opened socket */ switch (spec->transport) { case FB_TLS_TCP: ok = fbCollectorOpenTLS(collector, err); break; #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: #endif ok = fbCollectorOpenDTLS(collector, err); break; #endif default: g_assert_not_reached(); } /* Nuke collector on TLS setup error */ if (!ok) { g_slice_free(fbCollector_t, collector); return NULL; } /* All done */ return collector; } #endif /* HAVE_OPENSSL */ #if HAVE_SPREAD static gboolean fbCollectorSpreadOpen( fbCollector_t *collector, GError **err ) { int ret; int i = 0; char grp[MAX_GROUP_NAME]; fbSpreadSpec_t *spread = collector->stream.spread; if (!spread->daemon) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name cannot be null" ); return FALSE; } if (!spread->daemon[0]) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name cannot be empty" ); return FALSE; } /*if (strnlen( spread->daemon, 262 ) > 261)*/ if ( !(memchr( spread->daemon, 0, 261)) ) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name too long" ); return FALSE; } if (!spread->groups) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread groups cannot be null" ); return FALSE; } if (!spread->groups[0].name[0]) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread groups cannot be empty" ); return FALSE; } if (!spread->session) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread session cannot be null" ); return FALSE; } ret = SP_connect( spread->daemon, 0, 0, 0, &(spread->recv_mbox), spread->privgroup ); if (ret != ACCEPT_SESSION) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error connecting to Spread daemon %s: %s", spread->daemon, fbConnSpreadError( ret ) ); return FALSE; } // mark it active here, fbCollectorFree() will need to disconnect collector->active = TRUE; for (i = 0; i < spread->num_groups; ++i) { ret = SP_join( spread->recv_mbox, spread->groups[i].name); if (ret) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error joining to Spread data group %s: %s", spread->groups[i].name, fbConnSpreadError( ret ) ); return FALSE; } } /* now that we have joined the data plane group, join the control/template plane group to signal exporters that we need the templates for this group. */ for (i = 0; i < spread->num_groups; ++i) { memset( grp, 0, sizeof( grp ) ); strncpy( grp, spread->groups[i].name, sizeof( grp) - 2 ); strcat( grp, "T" ); ret = SP_join( spread->recv_mbox, grp ); if (ret) { g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error joining to Spread control/template group %s: %s", spread->groups[i].name, fbConnSpreadError( ret ) ); return FALSE; } } return TRUE; } /* There is no good way to deal with sequence numbers in Spread. * This was added to return False if the collector receives * a message where it is not the first group listed in msg. * This is because the exporter only looks at the first group * when deciding what sequence number to export */ static gboolean fbCollectorSpreadPostProc( fbCollector_t *collector, uint8_t *buffer, size_t *b_len, GError **err) { if (fbCollectorTestGroupMembership(collector, 0)) { return TRUE; } (void) collector; (void) buffer; (void) b_len; (void) err; return FALSE; } int fbCollectorGetSpreadReturnGroups( fbCollector_t *collector, char *groups[] ) { int loop = 0; fbSpreadSpec_t *spread = collector->stream.spread; for ( loop = 0; loop < spread->recv_num_groups; loop++){ groups[loop] = spread->recv_groups[loop].name; } return spread->recv_num_groups; } static gboolean fbCollectorSpreadRead( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err ) { fbSpreadSpec_t *spread = collector->stream.spread; service service_type = 0; char sender[MAX_GROUP_NAME]; int16 mess_type = 0; int endian_mismatch; int no_mess = 1; int ret; do { ret = SP_receive( spread->recv_mbox, &service_type, sender, spread->recv_max_groups, &(spread->recv_num_groups), (char (*)[])spread->recv_groups, &mess_type, &endian_mismatch, *msglen, (char *)msgbase ); if (spread->recv_exit) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOF, "End of file: spread shut down or was not connected"); return FALSE; } if (ret < 0) { if (ret == GROUPS_TOO_SHORT) { g_free(spread->recv_groups); spread->recv_max_groups = -spread->recv_num_groups; spread->recv_groups = g_new0( sp_groupname_t, spread->recv_max_groups ); } else if (ret == BUFFER_TOO_SHORT) { *msglen = -endian_mismatch; g_set_error( err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "msglen too small (%zd required)", *msglen ); return FALSE; } else if ((ret == CONNECTION_CLOSED) || (ret == ILLEGAL_SESSION)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "End of file: %s", fbConnSpreadError(ret)); return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "error(%d) receiving Spread message: %s", ret, fbConnSpreadError(ret)); *msglen = 0; return FALSE; } } else { *msglen = ret; no_mess = 0; } } while (no_mess); return TRUE; } static void fbCollectorSpreadClose( fbCollector_t *collector ) { if (collector->active) { SP_disconnect( collector->stream.spread->recv_mbox ); } collector->active = FALSE; } fbCollector_t *fbCollectorAllocSpread( void *ctx, fbSpreadParams_t *params, GError **err ) { fbCollector_t *collector = g_slice_new( fbCollector_t ); memset( collector, 0, sizeof( fbCollector_t ) ); collector->ctx = ctx; collector->stream.spread = fbConnSpreadCopy( params ); collector->bufferedStream = FALSE; collector->active = FALSE; collector->spread_active = 1; collector->coread = fbCollectorSpreadRead; collector->coreadLen = fbCollectorDecodeMsgVL; /* after SCTP */ collector->copostRead = fbCollectorSpreadPostProc; /* after SCTP */ collector->comsgHeader = fbCollectorMessageHeaderNull; /* after SCTP */ collector->coclose = fbCollectorSpreadClose; collector->cotransClose = fbCollectorCloseTranslatorNull; /* after SCTP */ collector->cotimeOut = fbCollectorSessionTimeoutNull; collector->translationActive = FALSE; if (!fbCollectorSpreadOpen( collector, err )) { fbCollectorFree( collector ); return 0; } return collector; } gboolean fbCollectorTestGroupMembership( fbCollector_t *collector, int group_offset) { int loop; fbSpreadSpec_t *spread = NULL; if (!collector) { return TRUE; } if (!collector->spread_active) { return TRUE; } spread = collector->stream.spread; for (loop = 0; loop < spread->num_groups; loop++) { if (strcmp(spread->recv_groups[group_offset].name, spread->groups[loop].name) == 0) { fbSessionSetGroup(spread->session, (char *)spread->recv_groups[group_offset].name); return TRUE; } } return FALSE; } #endif /* HAVE_SPREAD */ /** * fbCollectMessage * * * */ gboolean fbCollectMessage( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err) { /* Ensure stream is open */ if (!collector->active) return FALSE; /* Attempt to read message */ if (collector->coread(collector, msgbase, msglen, err)) return TRUE; /* Read failure; signal error */ return FALSE; } /** * fbCollectorGetContext * * * */ void *fbCollectorGetContext( fbCollector_t *collector) { return collector->ctx; } /** * fbCollectorHasTranslator * * use this is check to see if a protocol translation * is in use for this collector. Needed by the transcode * and IPFIX machinery to get rid of some error checks * which no longer apply. * * @param collector pointer to the collector state struct * * @return TRUE if a translator is in use, FALSE otherwise */ gboolean fbCollectorHasTranslator( fbCollector_t *collector) { return collector->translationActive; } /** * fbCollectorGetFD * * * */ int fbCollectorGetFD( fbCollector_t *collector) { return collector->stream.fd; } /** * fbCollectorSetFD * * * */ void fbCollectorSetFD( fbCollector_t *collector, int fd) { if (collector) { collector->stream.fd = fd; } } /** * fbCollectorClose * * * */ void fbCollectorClose( fbCollector_t *collector) { if (collector->active && collector->coclose) collector->coclose(collector); if (collector->listener) { fbListenerRemove(collector->listener, collector->stream.fd); } } /** * fbCollectorFree * * * */ void fbCollectorFree( fbCollector_t *collector) { if (!collector->multi_session) { fbListenerAppFree(collector->listener, collector->ctx); } collector->cotransClose(collector); fbCollectorClose(collector); #if HAVE_SPREAD if (collector->coclose == fbCollectorSpreadClose) { fbConnSpreadFree( collector->stream.spread ); } #endif while (collector->udp_tail) { fbCollectorFreeUDPSpec(collector, collector->udp_tail); } g_slice_free(fbCollector_t, collector); } /** * fbCollectorClearTranslator * * @param collector the collector on which to remove * the translator * * @return TRUE on success, FALSE on failure */ gboolean fbCollectorClearTranslator( fbCollector_t *collector, GError **err __attribute__((unused)) ) { collector->cotransClose(collector); return TRUE; } /** * fbCollectorSetTranslator * * this sets the collector input to any * given translator * * @param collector the collector to apply the protocol * convertor to * @param postProcFunc a function called after the read * to do any post processing/conversion to turn * the buffer into an IPFIX buffer * @param vlMessageFunc function to determine the * amount needed to complete the next read * @param headerFunc function to transform the header after * a block read before it is sent to the * postProcFunc (called when vlMessageFunc isn't) * @param trCloseFunc if anything is needed to be cleaned * up in the translator when a collector is closed * this function will be called before the collector * is closed * @param timeOutFunc when UDP sessions timeout, this function will * clear any state associated with the session. * @param opaque a void pointer to hold a translator * specific state structure * @param err holds the glib based error message on * error * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetTranslator( fbCollector_t *collector, fbCollectorPostProc_fn postProcFunc, fbCollectorVLMessageSize_fn vlMessageFunc, fbCollectorMessageHeader_fn headerFunc, fbCollectorTransClose_fn trCloseFunc, fbCollectorSessionTimeout_fn timeOutFunc, void *opaque, GError **err) { if (NULL != collector->translatorState) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TRANSMISC, "Translator is already set on this collector, " "must be cleared first"); return FALSE; } collector->copostRead = postProcFunc; collector->coreadLen = vlMessageFunc; collector->comsgHeader = headerFunc; collector->cotransClose = trCloseFunc; collector->cotimeOut = timeOutFunc; collector->translatorState = opaque; collector->translationActive = TRUE; return TRUE; } struct sockaddr* fbCollectorGetPeer( fbCollector_t *collector) { return (&collector->peer.so); } void fbCollectorInterruptSocket( fbCollector_t *collector) { uint8_t byte = 0xe7; #if HAVE_SPREAD if (collector->spread_active) { fbCollectorSpreadClose(collector); return; } #endif write(collector->wip, &byte, sizeof(byte)); write(collector->rip, &byte, sizeof(byte)); } void fbCollectorRemoveListenerLastBuf( fBuf_t *fbuf, fbCollector_t *collector) { /* may not have a listener - esp for spread */ if (collector->listener) { fbListenerRemoveLastBuf(fbuf, collector->listener); } } uint32_t fbCollectorGetObservationDomain( fbCollector_t *collector) { if (!collector) { return 0; } return collector->obdomain; } void fbCollectorSetAcceptOnly( fbCollector_t *collector, struct sockaddr *address, size_t address_length) { collector->accept_only = TRUE; memcpy(&(collector->peer.so), address, (address_length > sizeof(collector->peer)) ? sizeof(collector->peer) : address_length); } void fbCollectorSetUDPMultiSession( fbCollector_t *collector, gboolean multi_session) { collector->multi_session = multi_session; } /** * netflow v9 spec says: * NetFlow Collectors SHOULD use the combination of the source IP * address and the Source ID field to separate different export * streams originating from the same Exporter. * * however, some routers make this difficult, so turn this flag * on to prevent fixbuf from clearing out the ports before comparing * sockaddr structs. */ void fbCollectorManageUDPStreamByPort( fbCollector_t *collector, gboolean manage_port) { collector->stream_by_port = manage_port; } libfixbuf-1.7.1/src/fbcollector.h000644 000770 000024 00000031744 12545036674 021271 0ustar00emilyecoffmessagebus000000 000000 /** @internal ** ** ** @file fbcollector.h ** IPFIX Collecting Process single transport session implementation ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #ifndef FB_COLLECTOR_H_ #define FB_COLLECTOR_H_ #define _FIXBUF_SOURCE_ #include #ident "$Id$" /* 30 mins in seconds */ #define FB_UDP_TIMEOUT 1800 /** * fbCollectorClose_fn * * the close function for a given collector; it is transport * specific * * @param collector the handle to the collecting process * */ typedef void (*fbCollectorClose_fn)( fbCollector_t *collector); /** structure definition of the start of IPFIX & NetFlow messages */ typedef struct fbCollectorMsgVL_st { uint16_t n_version; uint16_t n_len; } fbCollectorMsgVL_t; /** * fbCollectorClearTranslator * * After setting an input translator for a collector, this function clears * that operation. The collector, after this call, will again operate as * an IPFIX collector. * * @param collector a collecting process endpoint. * @param err An error message set on return when an error occurs * * @return TRUE on success, FALSE on error */ gboolean fbCollectorClearTranslator( fbCollector_t *collector, GError **err); /** * fbCollectorPostProc_fn * * The defines the function for the post processing function for * implementing a translator to IPFIX. This gets called after * a PDU for the protocol is read. * * @param collector a collecting process endpoint * @param dataBuf a pointer to the PDU body * @param err An error message set on return when an error occurs * * @return TRUE of success, FALSE on error */ typedef gboolean (*fbCollectorPostProc_fn)( fbCollector_t *collector, uint8_t *dataBuf, size_t *bufLen, GError **err); /** * fbCollectorVLMessageSize_fn * * This function returns the size of the PDU for a read. It is * specific to the protocol to be translated. * * @param collector a collecting process endpoint * @param hdr a pointer to the IPFIX header (although can be cast * into a uint8_t * and used as a pointer into the * buffer) * @param b_len the length of the header just read in * @param m_len a return value with the length of the PDU to be read * @param err An error message set on the return when an error occurs * * @return TRUE on success, FALSE on error */ typedef gboolean (*fbCollectorVLMessageSize_fn)( fbCollector_t *collector, fbCollectorMsgVL_t *hdr, size_t b_len, uint16_t *m_len, GError **err); /** * fbCollectorMessageHeader_fn * * This function is called for message based read channels when the * fbCollectorVLMessageSize_fn is not called. (UDP & SCTP) TCP & * files are read as streams and the concept of a PDU doesn't exist * in the same fashion as message based protocols. This function * reconstructs the header of a message in order for it to be workable * with the fbCollectorPostProc_fn. * * Or you could view it this way, this function is the result of taking * an optimization in fbCollectorVLMessageSize_fn which modifies the * header in order to avoid a mempy. This is where the memcpy happens * if you don't call fbCollectorVLMessageSize_fn. (At least for NetFlow * V9.) * * @param collector pointer to the collector state structure * @param buffer pointer to the raw data buffer * @param b_len length of the buffer passed in * @param m_len length of the message on output (might be different * than b_len from transformations made here) * @param err An error message set on return if an error occurs * * @return TRUE on success, FALSE on error (check err) * */ typedef gboolean (*fbCollectorMessageHeader_fn)( fbCollector_t *collector, uint8_t *buffer, size_t b_len, uint16_t *m_len, GError **err); /** * fbCollectorTransClose_fn * * This is called to cleanup any translator state when a collector * with a translator is closed. * * @param collector a collecting process endpoint * */ typedef void (*fbCollectorTransClose_fn)( fbCollector_t *collector); /** * fbCollectorSessionTimeout_fn * * This is the definition of the function the collector calls when it * times out a UDP session. It needs to be a function pointer to allow * translators the ability to free any state that is associated with * the timed out session. * * @param collector pointer to collector * @param session pointer to session that is being timed out * */ typedef void (*fbCollectorSessionTimeout_fn) ( fbCollector_t *collector, fbSession_t *session); /** * fbCollectorSetTranslator * * This sets a translator on the given collecting process. There are various * function points that need to be set in order to implement a collector that * can read something other than IPFIX, e.g. NetFlow. Not all functions need * to be reimplemented, depending on the protocol to be adapted, however, a * valid function pointer needs to be provided for each function. The * fbcollector and fbnetflow source code can provide more detailed example * and information about the exact implementation. * * @param collector a collecting process endpoint * @param postProcFunc a function that gets called after a pdu has been read * so that any necessary transformations may occur * @param vlMessageFunc this function is used to determine how large a single * read should be from the file/network handle; it should * return a whole PDU if possible * @param headerFunc function to transform the header after a block read before * it is sent to the postProcFunc (called when * vlMessageFunc isn't) * @param trCloseFunc this function gets called when the collector gets closed * to clean up any data, etc. that the the translator * requires * @param timeOutFunc this function gets called when the collector times out * UDP sessions, so it can clear any related state. * @param opaque the fixbuf standard collector code will not look at this * pointer. The translator can use this and retrieve it from * the collector structure as needed during its operation * @param err An error message set on return when an error occurs * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetTranslator( fbCollector_t *collector, fbCollectorPostProc_fn postProcFunc, fbCollectorVLMessageSize_fn vlMessageFunc, fbCollectorMessageHeader_fn headerFunc, fbCollectorTransClose_fn trCloseFunc, fbCollectorSessionTimeout_fn timeOutFunc, void *opaque, GError **err); /** * fbCollectorRead_fn * * This is the definition of the read function the collector calls in order * to read a PDU from the stream/file. It is defined as a function pointer * to be able to accomodate the various different connection types supported * by fixbuf. * * @param collector a collecting process endpoint * @param msgbase the buffer to store the PDU in * @param msglen the length of the PDU stored in msgbase * @param err An error message set on return of a failure * * @return TRUE on success, FALSE on error * */ typedef gboolean (*fbCollectorRead_fn) ( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err); struct fbCollector_st { /** Listener from which this Collector was created. */ fbListener_t *listener; /** * Application context. Created and owned by the application * when the listener calls the callback. */ void *ctx; /** Cached peer address. Filled in at allocation time */ union { struct sockaddr so; struct sockaddr_in ip4; struct sockaddr_in6 ip6; } peer; /** Current export stream */ union { /** Buffered file pointer, for file transport */ FILE *fp; /** * Unbuffered socket, for SCTP, TCP, or UDP transport. * Also used as base socket for TLS and DTLS support. */ int fd; #if HAVE_SPREAD fbSpreadSpec_t * spread; #endif } stream; /** * Interrupt pipe read end file descriptor. * Used to unblock a call to fbListenerWait(). */ int rip; /** * Interrupt pipe write end file descriptor. * Used to unblock a call to fbListenerWait(). */ int wip; gboolean bufferedStream; gboolean translationActive; gboolean active; gboolean accept_only; gboolean multi_session; gboolean stream_by_port; uint32_t obdomain; time_t time; #if HAVE_OPENSSL /** OpenSSL socket, for TLS or DTLS over the socket in fd. */ SSL *ssl; #endif #if HAVE_SPREAD /** Need something to distinguish collectors if we have spread but don't use it */ uint8_t spread_active; #endif fbCollectorRead_fn coread; fbCollectorVLMessageSize_fn coreadLen; fbCollectorPostProc_fn copostRead; fbCollectorMessageHeader_fn comsgHeader; fbCollectorClose_fn coclose; fbCollectorTransClose_fn cotransClose; fbCollectorSessionTimeout_fn cotimeOut; void *translatorState; fbUDPConnSpec_t *udp_head; fbUDPConnSpec_t *udp_tail; }; #endif libfixbuf-1.7.1/src/fbconnspec.c000644 000770 000024 00000037754 12545036674 021115 0ustar00emilyecoffmessagebus000000 000000 /* ** fbconnspec.c ** IPFIX Connection Specifier implementation ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #ident "$Id$" #define HAVE_GETADDRINFO 1 #if !HAVE_GETADDRINFO struct addrinfo { int ai_family; /* protocol family for socket */ int ai_socktype; /* socket type */ int ai_protocol; /* protocol for socket */ socklen_t ai_addrlen; /* length of socket-address */ struct sockaddr *ai_addr; /* socket-address for socket */ struct addrinfo *ai_next; /* pointer to next in list */ }; #endif #if HAVE_GETADDRINFO static void fbConnSpecFreeAI( fbConnSpec_t *spec) { if (spec->vai) { freeaddrinfo((struct addrinfo *)spec->vai); spec->vai = NULL; } } gboolean fbConnSpecLookupAI( fbConnSpec_t *spec, gboolean passive, GError **err) { struct addrinfo hints; struct addrinfo * tempaddr = NULL; int ai_err; /* free old addrinfo if necessary */ fbConnSpecFreeAI(spec); /* set up hints */ memset(&hints, 0, sizeof(hints)); /* some ancient linuxen won't let you specify this */ #ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG; #endif if (passive) hints.ai_flags |= AI_PASSIVE; hints.ai_family = AF_UNSPEC; /* determine socket type and protocol */ switch (spec->transport) { /* * Yeah, this is wrong. Use SOCK_STREAM/IPPROTO_TCP for SCTP. * getaddrinfo(2) doesn't take SCTP hints. We'll rewrite the socktype and * protocol later at connection time. */ #if FB_ENABLE_SCTP case FB_SCTP: #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: #endif #endif case FB_TCP: #if HAVE_OPENSSL case FB_TLS_TCP: #endif hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; break; case FB_UDP: #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: #endif hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; break; default: g_assert_not_reached(); } /* get addrinfo for host/port */ if ((ai_err = getaddrinfo(spec->host, spec->svc, &hints, &tempaddr) )) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error looking up address %s:%s: %s", spec->host ? spec->host : "*", spec->svc, gai_strerror(ai_err)); return FALSE; } spec->vai = tempaddr; /* lookup succeeded. */ return TRUE; } #else static void fbConnSpecFreeAI( fbConnSpec_t *spec) { struct addrinfo *ai; if (spec->vai) { ai = (struct addrinfo *)spec->vai; g_free(ai->ai_addr); g_free(ai); spec->vai = NULL; } } gboolean fbConnSpecLookupAI( fbConnSpec_t *spec, gboolean passive, GError **err) { struct sockaddr_in *sa = NULL; struct hostent *he = NULL; struct servent *se = NULL; unsigned long svcaddrlong; char *svcaddrend; struct addrinfo *ai = NULL; /* free old addrinfo if necessary */ fbConnSpecFreeAI(spec); /* create a sockaddr */ sa = g_new0(struct sockaddr_in, 1); /* get service address */ svcaddrlong = strtoul(spec->svc, &svcaddrend, 10); if (svcaddrend != svcaddr) { /* Convert long to net-order uint16_t */ sa->sin_port = g_htons((uint16_t)svcaddrlong); } else { struct servent *se; /* Do service lookup */ if (!(se = getservbyname(spec->svc, "udp"))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error looking up service %s", spec->svc); g_free(sa); return FALSE; } sa->sin_port = se->s_port; } /* get host address */ if (spec->host) { if (!(he = gethostbyname(spec->host))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error looking up host %s: %s", spec->host, hstrerror(h_errno)); g_free(sa); return FALSE; } sa->sin_addr.s_addr = *(he->h_addr); } else { if (passive) { sa->sin_addr.s_addr = htonl(INADDR_ANY); } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "cannot connect() without host address"); g_free(sa); return FALSE; } } /* fake up a struct addrinfo */ ai = g_new0(struct addrinfo, 1); ai->ai_family = AF_INET; ai->ai_addrlen = sizeof(struct sockaddr_in); ai->ai_addr = sa; /* get socktype and protocol from transport */ switch (spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: #endif ai->ai_socktype = SOCK_SEQPACKET; ai->ai_protocol = 0; break; #endif case FB_TCP: #if HAVE_OPENSSL case FB_TLS_TCP: #endif ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = IPPROTO_TCP; break; case FB_UDP: #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: #endif ai->ai_socktype = SOCK_DGRAM; ai->ai_protocol = IPPROTO_UDP; break; default: g_assert_not_reached(); } spec->vai = ai; return TRUE; } #endif /* HAVE_GETADDRINFO */ #if HAVE_OPENSSL static int fbConnSpecGetTLSPassword( char *pwbuf, int pwsz, int rwflag, void *vpwstr) { (void)rwflag; if (vpwstr) { strncpy(pwbuf, (const char *)vpwstr, pwsz); return strlen(pwbuf); } else { *pwbuf = '\0'; return 0; } } static int fbConnSpecVerifyTLSCert( int pvok, X509_STORE_CTX *x509_ctx) { (void)pvok; (void)x509_ctx; return 1; } gboolean fbConnSpecInitTLS( fbConnSpec_t *spec, gboolean passive, GError **err) { SSL_METHOD *tlsmeth = NULL; SSL_CTX *ssl_ctx = NULL; gboolean ok = TRUE; /* Initialize the library and error strings */ SSL_library_init(); SSL_load_error_strings(); /* * Select a TLS method based on passivity and transport. * Shortcircuit on no TLS initialization necessary for sockets. */ switch (spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: #endif case FB_TCP: case FB_UDP: return TRUE; #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method(); break; #endif case FB_TLS_TCP: tlsmeth = passive ? TLSv1_server_method() : TLSv1_client_method(); break; #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method(); break; #endif default: g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IMPL, "Unsupported TLS method."); return FALSE; } /* Verify we have all the files we need */ g_assert(spec->ssl_ca_file); g_assert(spec->ssl_cert_file); g_assert(spec->ssl_key_file); /* nuke the old context if there is one */ if (spec->vssl_ctx) { SSL_CTX_free((SSL_CTX *)spec->vssl_ctx); spec->vssl_ctx = NULL; } /* create an SSL_CTX object */ ssl_ctx = SSL_CTX_new(tlsmeth); if (!ssl_ctx) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Cannot create SSL context: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); ok = FALSE; goto end; } /* Set up password callback */ SSL_CTX_set_default_passwd_cb(ssl_ctx, fbConnSpecGetTLSPassword); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, spec->ssl_key_pass); /* Load CA certificate */ if (SSL_CTX_load_verify_locations(ssl_ctx, spec->ssl_ca_file, NULL) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load certificate authority file %s: %s", spec->ssl_ca_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Load certificate */ if (SSL_CTX_use_certificate_chain_file(ssl_ctx, spec->ssl_cert_file) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load certificate file %s: %s", spec->ssl_cert_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Load private key */ if (SSL_CTX_use_PrivateKey_file(ssl_ctx, spec->ssl_key_file, SSL_FILETYPE_PEM) != 1) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Failed to load private key file %s: %s", spec->ssl_key_file, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Require verification */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, fbConnSpecVerifyTLSCert); /* Stash SSL context in specifier */ spec->vssl_ctx = ssl_ctx; end: /* free incomplete SSL context */ if (!ok) SSL_CTX_free(ssl_ctx); return ok; } #endif /* HAVE_OPENSSL */ fbConnSpec_t *fbConnSpecCopy( fbConnSpec_t *spec) { fbConnSpec_t *newspec = g_slice_new0(fbConnSpec_t); newspec->transport = spec->transport; newspec->host = spec->host ? g_strdup(spec->host) : NULL; newspec->svc = spec->svc ? g_strdup(spec->svc) : NULL; newspec->ssl_ca_file = spec->ssl_ca_file ? g_strdup(spec->ssl_ca_file) : NULL; newspec->ssl_cert_file = spec->ssl_cert_file ? g_strdup(spec->ssl_cert_file) : NULL; newspec->ssl_key_file = spec->ssl_key_file ? g_strdup(spec->ssl_key_file) : NULL; newspec->ssl_key_pass = spec->ssl_key_pass ? g_strdup(spec->ssl_key_pass) : NULL; newspec->vai = NULL; newspec->vssl_ctx = NULL; return newspec; } void fbConnSpecFree( fbConnSpec_t *spec) { if (!spec) { return; } if (spec->host) g_free(spec->host); if (spec->svc) g_free(spec->svc); if (spec->ssl_ca_file) g_free(spec->ssl_ca_file); if (spec->ssl_cert_file) g_free(spec->ssl_cert_file); if (spec->ssl_key_file) g_free(spec->ssl_key_file); if (spec->ssl_key_pass) g_free(spec->ssl_key_pass); fbConnSpecFreeAI(spec); #if HAVE_OPENSSL if (spec->vssl_ctx) { SSL_CTX_free((SSL_CTX *)spec->vssl_ctx); } #endif g_slice_free1(sizeof(fbConnSpec_t), spec); } #if HAVE_SPREAD fbSpreadSpec_t *fbConnSpreadCopy( fbSpreadParams_t *params ) { int n = 0; char **g = 0; fbSpreadSpec_t *spec = g_slice_new0( fbSpreadSpec_t ); memset( spec, 0, sizeof( fbSpreadSpec_t ) ); spec->session = params->session; spec->daemon = params->daemon ? g_strdup( params->daemon ) : NULL; for (g=params->groups; *g; ++g) { if (*g[0]) ++spec->num_groups; } spec->groups = g_new0( sp_groupname_t, spec->num_groups ); for (g=params->groups; *g; ++g) { /* have to copy one less than max. Template groups will be automatically created by appending 'T' to the groups specified here. */ if (*g[0]) strncpy( spec->groups[n++].name, *g, MAX_GROUP_NAME-1 ); } spec->recv_max_groups = FB_SPREAD_NUM_GROUPS; spec->recv_groups = g_new0( sp_groupname_t, spec->recv_max_groups ); spec->recv_max = FB_SPREAD_MTU; spec->recv_mess = g_new0( char, spec->recv_max ); spec->num_groups_to_send = 0; fbSessionSetGroupParams(spec->session, spec->groups, spec->num_groups); return spec; } void fbConnSpreadFree( fbSpreadSpec_t *spec ) { if (spec->daemon) g_free(spec->daemon); if (spec->groups) g_free(spec->groups); if (spec->recv_groups) g_free(spec->recv_groups); if (spec->recv_mess) g_free(spec->recv_mess); if (spec->groups_to_send) g_free(spec->groups_to_send); g_slice_free(fbSpreadSpec_t, spec); } const char * fbConnSpreadError( int err ) { switch (err) { case ILLEGAL_GROUP: return "illegal group"; case ILLEGAL_SESSION: return "illegal session"; case CONNECTION_CLOSED: return "connection closed"; case ILLEGAL_SPREAD: return "illegal daemon name"; case COULD_NOT_CONNECT: return "could not connect"; case REJECT_VERSION: return "client/daemon version mismatch"; case REJECT_NO_NAME: return "name with no name length, or no name and name length"; case REJECT_ILLEGAL_NAME: return "illegal name (length or character)"; case REJECT_NOT_UNIQUE: return "name not unique"; default: break; } return "unknown error"; } #endif /* HAVE_SPREAD */ libfixbuf-1.7.1/src/fbexporter.c000644 000770 000024 00000116027 12545036674 021144 0ustar00emilyecoffmessagebus000000 000000 /** * @internal * * @file fbexporter.c * * IPFIX Exporting Process single transport session implementation * ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ * */ #define _FIXBUF_SOURCE_ /*#define _GNU_SOURCE*/ #include #ident "$Id$" /** * If set in exporter SCTP mode, use simple automatic stream selection as * specified in the IPFIX protocol without flexible stream selection: send * templates on stream 0, and data on stream 1. */ #define FB_F_SCTP_AUTOSTREAM 0x80000000 /** * If set in exporter SCTP mode, use TTL-based partial reliability for * non-template messages. */ #define FB_F_SCTP_PR_TTL 0x40000000 typedef gboolean (*fbExporterOpen_fn)( fbExporter_t *exporter, GError **err); typedef gboolean (*fbExporterWrite_fn) ( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err); typedef void (*fbExporterClose_fn)( fbExporter_t *exporter); struct fbExporter_st { /** Specifier used for stream open */ union { fbConnSpec_t *conn; #if HAVE_SPREAD fbSpreadSpec_t *spread; #endif char *path; } spec; /** Current export stream */ union { /** Buffered file pointer, for file transport */ FILE *fp; /** Buffer for data if providing own transport */ uint8_t *buffer; /** * Unbuffered socket, for SCTP, TCP, or UDP transport. * Also used as base socket for TLS and DTLS support. */ int fd; } stream; /** SCTP mode. Union of FB_SCTP_F_* flags. */ uint32_t sctp_mode; /** Next SCTP stream */ int sctp_stream; /** Partial reliability parameter (see mode) */ int sctp_pr_param; #if HAVE_OPENSSL /** OpenSSL socket, for TLS or DTLS over the socket in fd. */ SSL *ssl; #endif gboolean active; size_t msg_len; fbExporterOpen_fn exopen; fbExporterWrite_fn exwrite; fbExporterClose_fn exclose; uint16_t mtu; }; /** *fbExporterOpenFile * * * @param exporter * @param err * * @return */ static gboolean fbExporterOpenFile ( fbExporter_t *exporter, GError **err) { /* check to see if we're opening stdout */ if ((strlen(exporter->spec.path) == 1) && (exporter->spec.path[0] == '-')) { /* don't open a terminal */ if (isatty(fileno(stdout))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Refusing to open stdout terminal for export"); return FALSE; } /* yep, stdout */ exporter->stream.fp = stdout; } else { /* nope, just a regular file */ exporter->stream.fp = fopen(exporter->spec.path, "w"); } /* check for error */ if (!exporter->stream.fp) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Couldn't open %s for export: %s", exporter->spec.path, strerror(errno)); return FALSE; } /* set active flag */ exporter->active = TRUE; return TRUE; } /** *fbExporterWriteFile * * * @param exporter * @param msgbase * @param msglen * @param err * * @return */ static gboolean fbExporterWriteFile( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { size_t rc; rc = fwrite(msgbase, 1, msglen, exporter->stream.fp); if (rc == msglen) { return TRUE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Couldn't write %u bytes to %s: %s", (uint32_t)msglen, exporter->spec.path, strerror(errno)); return FALSE; } } /** *fbExporterCloseFile * * * @param exporter * */ static void fbExporterCloseFile ( fbExporter_t *exporter) { if (exporter->stream.fp == stdout) { fflush(exporter->stream.fp); } else { fclose(exporter->stream.fp); } exporter->stream.fp = NULL; exporter->active = FALSE; } /** *fbExporterAllocFile * * * @param path * @param exporter * * @return */ fbExporter_t *fbExporterAllocFile( const char *path) { fbExporter_t *exporter; /* Create a new exporter */ exporter = g_slice_new0(fbExporter_t); /* Copy the path */ exporter->spec.path = g_strdup(path); /* Set up stream management functions */ exporter->exopen = fbExporterOpenFile; exporter->exwrite = fbExporterWriteFile; exporter->exclose = fbExporterCloseFile; exporter->mtu = 65496; return exporter; } /** * fbExporterOpenBuffer * * */ static gboolean fbExporterOpenBuffer( fbExporter_t *exporter, GError **err) { /* set active flag */ exporter->active = TRUE; return TRUE; } /** *fbExporterCloseBuffer * * * @param exporter * */ static void fbExporterCloseBuffer ( fbExporter_t *exporter) { exporter->active = FALSE; } static gboolean fbExporterWriteBuffer( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { memcpy(exporter->stream.buffer, msgbase, msglen); exporter->msg_len = msglen; return TRUE; } /** * fbExporterAllocBuffer * * * */ fbExporter_t *fbExporterAllocBuffer( uint8_t *buf, uint16_t bufsize) { fbExporter_t *exporter = NULL; exporter = g_slice_new0(fbExporter_t); exporter->exwrite = fbExporterWriteBuffer; exporter->exopen = fbExporterOpenBuffer; exporter->exclose = fbExporterCloseBuffer; exporter->mtu = bufsize; exporter->stream.buffer = buf; return exporter; } /** *fbExporterSetFilePath * * * @param exporter * @param path * */ void fbExporterSetFilePath( fbExporter_t *exporter, char *path) { /* Only valid if this is a file path based exporter */ g_assert(exporter->exopen == fbExporterOpenFile); /* Force exporter closed if it's active */ if (exporter->active) exporter->exclose(exporter); /* Free old file path if necessary */ if (exporter->spec.path) { g_free(exporter->spec.path); } exporter->spec.path = g_strdup(path); } /** *fbExporterAllocFP * * @param fp * * @return */ fbExporter_t *fbExporterAllocFP( FILE *fp) { fbExporter_t *exporter; /* Create a new exporter */ exporter = g_slice_new0(fbExporter_t); /* Reference the path */ exporter->spec.path = g_strdup("FP"); /* Set up stream management functions */ exporter->exwrite = fbExporterWriteFile; exporter->mtu = 65496; /* set active flag */ exporter->active = TRUE; /* set file pointer */ exporter->stream.fp = fp; return exporter; } /** *fbExporterSetFP * * * @param exporter * @param fp * */ void fbExporterSetFP( fbExporter_t *exporter, FILE *fp) { /* Only valid if this is a file path based exporter */ g_assert(!exporter->exopen); g_assert(exporter->exwrite == fbExporterWriteFile); /* Change file pointer */ exporter->stream.fp = fp; } /** *fbExporterIgnoreSigpipe * * */ static void fbExporterIgnoreSigpipe() { static gboolean ignored = FALSE; struct sigaction sa, osa; if (ignored) return; sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGPIPE,&sa,&osa)) { g_error("sigaction(SIGPIPE) failed: %s", strerror(errno)); } ignored = TRUE; } /** *fbExporterMaxSendbuf * * * @param sock * @param size * * @return */ static gboolean fbExporterMaxSendbuf( int sock, int *size) { while (*size > 4096) { if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, size, sizeof(*size)) == 0) { return TRUE; } if (errno != ENOBUFS) { return FALSE; } *size -= (*size > 1024 * 1024) ? 1024 * 1024 : 2048; } return FALSE; } #define FB_SOCKBUF_DEFAULT (4 * 1024 * 1024) /** *fbExporterOpenSocket * * @param exporter * @param err * * @return */ static gboolean fbExporterOpenSocket( fbExporter_t *exporter, GError **err) { struct addrinfo *ai = NULL; int sockbuf_sz = FB_SOCKBUF_DEFAULT; /* Turn the exporter connection specifier into an addrinfo */ if (!fbConnSpecLookupAI(exporter->spec.conn, FALSE, err)) return FALSE; ai = (struct addrinfo *)exporter->spec.conn->vai; /* ignore sigpipe if we're doing TCP or SCTP export */ if ((exporter->spec.conn->transport == FB_TCP) || (exporter->spec.conn->transport == FB_TLS_TCP) #if FB_ENABLE_SCTP || (exporter->spec.conn->transport == FB_SCTP) || (exporter->spec.conn->transport == FB_DTLS_SCTP) #endif ) { fbExporterIgnoreSigpipe(); } /* open socket of appropriate type for connection specifier */ do { #if FB_ENABLE_SCTP if ((exporter->spec.conn->transport == FB_SCTP) || (exporter->spec.conn->transport == FB_DTLS_SCTP)) { /* Kludge for SCTP. addrinfo doesn't accept SCTP hints. */ ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = IPPROTO_SCTP; } #endif exporter->stream.fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (exporter->stream.fd < 0) continue; if (connect(exporter->stream.fd, ai->ai_addr, ai->ai_addrlen) == 0) break; close(exporter->stream.fd); } while ((ai = ai->ai_next)); /* check for no openable socket */ if (ai == NULL) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't create connected TCP socket to %s:%s %s", exporter->spec.conn->host, exporter->spec.conn->svc, strerror(errno)); return FALSE; } /* increase send buffer size for UDP */ if ((exporter->spec.conn->transport == FB_UDP) || (exporter->spec.conn->transport == FB_DTLS_UDP)) { if (!fbExporterMaxSendbuf(exporter->stream.fd, &sockbuf_sz)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't set socket buffer size on %s: %s", exporter->spec.conn->host, strerror(errno)); close(exporter->stream.fd); return FALSE; } } /* set active flag */ exporter->active = TRUE; return TRUE; } #if FB_ENABLE_SCTP /** *fbExporterWriteSCTP * * * @param exporter * @param msgbase * @param msglen * @param err * * @return */ static gboolean fbExporterWriteSCTP ( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { ssize_t rc; uint16_t initial_setid; gboolean is_template; int sctp_flags = 0; uint32_t sctp_ttl = 0; /* Check to see if this is a template message */ initial_setid = *(uint16_t *)(msgbase + 16); if (initial_setid == FB_TID_TS || initial_setid == FB_TID_OTS) { is_template = TRUE; } else { is_template = FALSE; } /* Do automatic stream selection if requested. */ if (exporter->sctp_mode & FB_F_SCTP_AUTOSTREAM) { if (is_template) { exporter->sctp_stream = 0; } else { exporter->sctp_stream = 1; } } /* Use partial reliability if requested for non-template messages */ if (!is_template && (exporter->sctp_mode & FB_F_SCTP_PR_TTL)) { sctp_flags |= FB_F_SCTP_PR_TTL; sctp_ttl = exporter->sctp_pr_param; } rc = sctp_sendmsg(exporter->stream.fd, msgbase, msglen, NULL, 0, /* destination sockaddr */ 0, /* payload protocol */ sctp_flags, /* flags */ exporter->sctp_stream, /* stream */ sctp_ttl, /* message lifetime (ms) */ 0); /* context */ if (rc == (ssize_t)msglen) { return TRUE; } else if (rc == -1) { if (errno == EPIPE) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLWRITE, "Connection reset (EPIPE) on SCTP write"); } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "I/O error: %s", strerror(errno)); } return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "short write: wrote %d while writing %lu", (int)rc, msglen); return FALSE; } } #endif /* FB_ENABLE_SCTP */ /** *fbExporterWriteTCP * * * @param exporter * @param msgbase * @param msglen * @param err * * @return */ static gboolean fbExporterWriteTCP ( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { ssize_t rc; rc = write(exporter->stream.fd, msgbase, msglen); if (rc == (ssize_t)msglen) { return TRUE; } else if (rc == -1) { if (errno == EPIPE) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLWRITE, "Connection reset (EPIPE) on TCP write"); } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "I/O error: %s", strerror(errno)); } return FALSE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "short write: wrote %d while writing %u", (int)rc, (uint32_t)msglen); return FALSE; } } /** * fbExporterWriteUDP * * * @param exporter * @param msgbase * @param msglen * @param err * * @return */ static gboolean fbExporterWriteUDP ( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { static gboolean sendGood = TRUE; ssize_t rc; /* Send the buffer as a single message */ rc = send(exporter->stream.fd, msgbase, msglen, 0); /* Deal with the results */ if (rc == (ssize_t)msglen) { return TRUE; } else if (rc == -1) { if (TRUE == sendGood) { g_warning( "I/O error on UDP send: %s (socket closed on receiver?)", strerror(errno)); g_warning("packets will be lost"); send(exporter->stream.fd, msgbase, msglen, 0); sendGood = FALSE; return TRUE; } return TRUE; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Short write on UDP send: wrote %d while writing %u", (int)rc, (uint32_t)msglen); return FALSE; } } /** *fbExporterCloseSocket * * * @param exporter * */ static void fbExporterCloseSocket ( fbExporter_t *exporter) { close(exporter->stream.fd); exporter->active = FALSE; } #if HAVE_OPENSSL /** *fbExporterOpenTLS * * * @param exporter * @param err * * @return */ static gboolean fbExporterOpenTLS ( fbExporter_t *exporter, GError **err) { BIO *conn = NULL; gboolean ok = TRUE; /* Initialize SSL context if necessary */ if (!exporter->spec.conn->vssl_ctx) { if (!fbConnSpecInitTLS(exporter->spec.conn, FALSE, err)) { return FALSE; } } /* open underlying socket */ if (!fbExporterOpenSocket(exporter, err)) return FALSE; /* wrap a stream BIO around the opened socket */ if (!(conn = BIO_new_socket(exporter->stream.fd, 1))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't wrap socket to %s:%s for TLS: %s", exporter->spec.conn->host, exporter->spec.conn->svc, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* create SSL socket */ if (!(exporter->ssl = SSL_new((SSL_CTX *)exporter->spec.conn->vssl_ctx))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldnt create TLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* connect to it */ SSL_set_bio(exporter->ssl, conn, conn); if (SSL_connect(exporter->ssl) <= 0) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't connect TLS socket to %s:%s: %s", exporter->spec.conn->host, exporter->spec.conn->svc, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* FIXME do post-connection verification */ end: if (!ok) { exporter->active = FALSE; if (exporter->ssl) { SSL_free(exporter->ssl); exporter->ssl = NULL; } else if (conn) { BIO_vfree(conn); } } return ok; } #if HAVE_OPENSSL_DTLS /** *fbExporterOpenDTLS * * @param exporter * @param err * * @return * */ static gboolean fbExporterOpenDTLS ( fbExporter_t *exporter, GError **err) { BIO *conn = NULL; gboolean ok = TRUE; struct sockaddr peer; size_t peerlen = sizeof(struct sockaddr); /* Initialize SSL context if necessary */ if (!exporter->spec.conn->vssl_ctx) { if (!fbConnSpecInitTLS(exporter->spec.conn, FALSE, err)) { return FALSE; } } /* open underlying socket */ if (!fbExporterOpenSocket(exporter, err)) return FALSE; /* wrap a datagram BIO around the opened socket */ if (!(conn = BIO_new_dgram(exporter->stream.fd, 1))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't wrap socket to %s:%s for DTLS: %s", exporter->spec.conn->host, exporter->spec.conn->svc, ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* Tell dgram bio what its name is */ if (getsockname(exporter->stream.fd, &peer, (socklen_t *)&peerlen) < 0) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't wrap socket to %s:%s for DTLS: %s", exporter->spec.conn->host, exporter->spec.conn->svc, strerror(errno)); goto end; } BIO_ctrl_set_connected(conn, 1, &peer); /* create SSL socket */ if (!(exporter->ssl = SSL_new((SSL_CTX *)exporter->spec.conn->vssl_ctx))) { ok = FALSE; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldnt create DTLS socket: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); goto end; } /* connect to it */ SSL_set_bio(exporter->ssl, conn, conn); SSL_set_connect_state(exporter->ssl); /* FIXME do post-connection verification */ end: if (!ok) { exporter->active = FALSE; if (exporter->ssl) { SSL_free(exporter->ssl); exporter->ssl = NULL; } else if (conn) { BIO_vfree(conn); } } return ok; } #endif /* HAVE_OPENSSL_DTLS */ /** *fbExporterWriteTLS * * * @param exporter * @param msgbase * @param msglen * @param err * * @return */ static gboolean fbExporterWriteTLS ( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { int rc; while (msglen) { rc = SSL_write(exporter->ssl, msgbase, msglen); if (rc <= 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "I/O error: %s", ERR_error_string(ERR_get_error(), NULL)); while (ERR_get_error()); return FALSE; } /* we sent some bytes - advance pointers */ msglen -= rc; msgbase += rc; } return TRUE; } /** *fbExporterCloseTLS * * * @param exporter * */ static void fbExporterCloseTLS ( fbExporter_t *exporter) { SSL_shutdown(exporter->ssl); SSL_free(exporter->ssl); exporter->active = FALSE; } #endif /* HAVE_OPENSSL */ /** *fbExporterGetMTU * * @param exporter * * @return */ uint16_t fbExporterGetMTU( fbExporter_t *exporter) { return exporter->mtu; } /** *fbExporterAllocNet * * @param spec * * @return */ fbExporter_t *fbExporterAllocNet( fbConnSpec_t *spec) { fbExporter_t *exporter = NULL; /* Host must not be null */ g_assert(spec->host); /* Create a new exporter */ exporter = g_slice_new0(fbExporter_t); /* Copy the connection specifier */ exporter->spec.conn = fbConnSpecCopy(spec); /* Set up functions */ switch (spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: exporter->exopen = fbExporterOpenSocket; exporter->exwrite = fbExporterWriteSCTP; exporter->exclose = fbExporterCloseSocket; exporter->sctp_mode = FB_F_SCTP_AUTOSTREAM; exporter->sctp_stream = 0; exporter->mtu = 8192; break; #endif case FB_TCP: exporter->exopen = fbExporterOpenSocket; exporter->exwrite = fbExporterWriteTCP; exporter->exclose = fbExporterCloseSocket; exporter->mtu = 8192; break; case FB_UDP: exporter->exopen = fbExporterOpenSocket; exporter->exwrite = fbExporterWriteUDP; exporter->exclose = fbExporterCloseSocket; exporter->mtu = 1420; break; #if HAVE_OPENSSL #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: exporter->exopen = fbExporterOpenDTLS; exporter->exwrite = fbExporterWriteTLS; exporter->exclose = fbExporterCloseTLS; exporter->sctp_mode = FB_F_SCTP_AUTOSTREAM; exporter->sctp_stream = 0; exporter->mtu = 8192; break; #endif case FB_TLS_TCP: exporter->exopen = fbExporterOpenTLS; exporter->exwrite = fbExporterWriteTLS; exporter->exclose = fbExporterCloseTLS; exporter->mtu = 8192; break; #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: exporter->exopen = fbExporterOpenDTLS; exporter->exwrite = fbExporterWriteTLS; exporter->exclose = fbExporterCloseTLS; exporter->mtu = 1320; break; #endif #endif default: #ifndef FB_ENABLE_SCTP if (spec->transport == FB_SCTP || spec->transport == FB_DTLS_SCTP) { g_error("Libfixbuf not enabled for SCTP Transport. " " Run configure with --with-sctp"); } #endif if (spec->transport == FB_TLS_TCP || spec->transport == FB_DTLS_SCTP || spec->transport == FB_DTLS_UDP) { g_error("Libfixbuf not enabled for this mode of transport. " " Run configure with --with-openssl"); } } /* Return new exporter */ return exporter; } #if HAVE_SPREAD /** * fbExporterSpreadReceiver * */ static void * fbExporterSpreadReceiver( void *arg ) { int i = 0; char grp[MAX_GROUP_NAME]; fbExporter_t *exporter = (fbExporter_t *)arg; fbSpreadSpec_t *spread = exporter->spec.spread; service service_type = 0; char sender[MAX_GROUP_NAME]; int num_groups = 0; int16 mess_type = 0; int endian_mismatch; int run = 1; int ret; membership_info memb_info; #if 0 /* this loop is to allow a debugger to be attached */ int foo = 1; do { sleep(1); } while (foo); #endif ret = SP_connect(spread->daemon, 0, 0, 1, &(spread->recv_mbox), spread->recv_privgroup); if (ret != ACCEPT_SESSION) { g_set_error(&(spread->recv_err), FB_ERROR_DOMAIN, FB_ERROR_CONN, "error connecting to Spread daemon %s: %s", spread->daemon, fbConnSpreadError(ret)); return 0; } for (i = 0; i < spread->num_groups; i++) { /* exporter listener only joins template/control plane group, the group name is always the name of the data plane group plus 'T' added to the end. */ memset(grp, 0, sizeof(grp)); strncpy(grp, spread->groups[i].name, sizeof(grp) - 2); strcat(grp, "T"); ret = SP_join(spread->recv_mbox, grp); if (ret) { g_set_error(&(spread->recv_err), FB_ERROR_DOMAIN, FB_ERROR_CONN, "error joining to Spread group %s: %s", spread->groups[i].name, fbConnSpreadError(ret)); return 0; } } do { ret = SP_receive(spread->recv_mbox, &service_type, sender, spread->recv_max_groups, &num_groups, (char (*)[])spread->recv_groups, &mess_type, &endian_mismatch, spread->recv_max, spread->recv_mess); if (spread->recv_exit) { SP_disconnect(spread->recv_mbox); continue; } if (ret < 0) { if (ret == GROUPS_TOO_SHORT) { g_free(spread->recv_groups); spread->recv_max_groups = -ret; spread->recv_groups = g_new0(sp_groupname_t, spread->recv_max_groups); } else if (ret == BUFFER_TOO_SHORT) { g_free(spread->recv_mess); spread->recv_max = -endian_mismatch; spread->recv_mess = g_new0(char, spread->recv_max); } else { g_set_error(&(spread->recv_err), FB_ERROR_DOMAIN, FB_ERROR_IO, "error receiving Spread message: %s", fbConnSpreadError(ret)); SP_disconnect(spread->recv_mbox); run = 0; } continue; } /* actually received a message! Now process it */ if (!Is_reg_memb_mess(service_type) || !Is_caused_join_mess(service_type)) continue; if (SP_get_memb_info(spread->recv_mess, service_type, &memb_info) < 0) continue; if (!memb_info.changed_member[0]) continue; if (strncmp(memb_info.changed_member, spread->recv_privgroup, MAX_GROUP_NAME) == 0) { continue; } /** Send Relevant Templates to New Member only. */ /** memb_info.changed_member is private group name */ /** sender is group they are subscribing to */ fbSessionSetPrivateGroup(spread->session, sender, memb_info.changed_member); } while (run); return 0; } /** * fbExporterSpreadOpen * * @param exporter * @param err */ static gboolean fbExporterSpreadOpen( fbExporter_t *exporter, GError **err ) { int ret; if (!exporter->spec.spread->daemon) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name cannot be null"); return FALSE; } if (!exporter->spec.spread->daemon[0]) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name cannot be empty"); return FALSE; } if (!(memchr(exporter->spec.spread->daemon, 0, 261))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread daemon name too long"); return FALSE; } if (!exporter->spec.spread->groups) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread groups cannot be null"); return FALSE; } if (!exporter->spec.spread->groups[0].name[0]) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread groups cannot be empty"); return FALSE; } if (!exporter->spec.spread->session) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Spread session cannot be null"); return FALSE; } pthread_mutex_init(&(exporter->spec.spread->write_lock), 0); ret = SP_connect(exporter->spec.spread->daemon, 0, 0, 0, &(exporter->spec.spread->mbox), exporter->spec.spread->privgroup); if (ret != ACCEPT_SESSION) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error connecting to Spread daemon %s: %s", exporter->spec.spread->daemon, fbConnSpreadError(ret)); return FALSE; } exporter->spec.spread->recv_err = 0; exporter->spec.spread->recv_exit = 0; ret = pthread_create(&(exporter->spec.spread->recv_thread), NULL, fbExporterSpreadReceiver, exporter ); if (ret) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error creating Spread receiver thread: %s",strerror(ret)); SP_disconnect(exporter->spec.spread->mbox); return FALSE; } /*pthread_detach(exporter->spec.spread->recv_thread);*/ exporter->active = TRUE; return TRUE; } /** * fbExporterSpreadWrite * * @param exporter * @param msg * @param msg size * @param err */ static gboolean fbExporterSpreadWrite( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err ) { int ret = 0; fbSpreadSpec_t *spread; pthread_mutex_lock(&(exporter->spec.spread->write_lock)); spread = exporter->spec.spread; if (spread->num_groups == 1) { ret = SP_multicast(spread->mbox, RELIABLE_MESS, spread->groups[0].name, 0, msglen, (const char *)msgbase); } else if (spread->num_groups_to_send == 1) { ret = SP_multicast(spread->mbox, RELIABLE_MESS, spread->groups_to_send[0].name, 0, msglen, (const char *)msgbase); } else if (spread->num_groups_to_send > 1) { ret = SP_multigroup_multicast(spread->mbox, RELIABLE_MESS, spread->num_groups_to_send, (const char (*)[])spread->groups_to_send, 0, msglen, (const char *)msgbase); } else { ret = SP_multigroup_multicast(spread->mbox, RELIABLE_MESS, spread->num_groups, (const char (*)[])spread->groups, 0, msglen, (const char *)msgbase); } if (ret < 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "error receiving Spread message: %s", fbConnSpreadError(ret)); } pthread_mutex_unlock(&(exporter->spec.spread->write_lock)); return (ret < 0) ? FALSE : TRUE; } /** * fbExporterSpreadClose * * @param exporter */ static void fbExporterSpreadClose( fbExporter_t *exporter ) { if (exporter->active) { pthread_cancel(exporter->spec.spread->recv_thread); pthread_join(exporter->spec.spread->recv_thread, NULL); SP_disconnect(exporter->spec.spread->mbox); } exporter->active = FALSE; } /** * fbExporterAllocSpread * * @param Spread_params */ fbExporter_t *fbExporterAllocSpread( fbSpreadParams_t *params ) { fbExporter_t *exporter = NULL; g_assert(params->daemon); g_assert(params->groups); g_assert(params->groups[0]); exporter = g_slice_new0(fbExporter_t); memset(exporter, 0, sizeof(fbExporter_t)); exporter->spec.spread = fbConnSpreadCopy(params); exporter->exopen = fbExporterSpreadOpen; exporter->exwrite = fbExporterSpreadWrite; exporter->exclose = fbExporterSpreadClose; #ifdef DEBUG exporter->mtu = 8192; #else exporter->mtu = FB_SPREAD_MTU; #endif return exporter; } /** * fbExporterSetGroupsToSend * * @param exporter * @param groups * @param num_groups * */ void fbExporterSetGroupsToSend( fbExporter_t *exporter, char **groups, int num_groups) { int n = 0; char **g = 0; fbSpreadSpec_t *spread = exporter->spec.spread; if (!spread->groups_to_send) { spread->groups_to_send = g_new0(sp_groupname_t, spread->num_groups); } g = groups; for (n=0; n < num_groups; n++) { strncpy(spread->groups_to_send[n].name, *g, MAX_GROUP_NAME-1); g++; } spread->num_groups_to_send = n; } /** * fbExporterCheckGroups * * If we are sending to a new (different) group of Spread Groups - return TRUE * to emit the buffer and set new export groups. * * @param exporter * @param groups * @param num_groups */ gboolean fbExporterCheckGroups( fbExporter_t *exporter, char **groups, int num_groups) { int n; fbSpreadSpec_t *spread = exporter->spec.spread; if (num_groups != spread->num_groups_to_send) { return TRUE; } for (n = 0; n < num_groups; n++) { if (strcmp(spread->groups_to_send[n].name, groups[n]) != 0) { return TRUE; } } return FALSE; } #endif /* HAVE_SPREAD */ /** *fbExporterSetStream * * @param exporter * @param sctp_stream * */ void fbExporterSetStream( fbExporter_t *exporter, int sctp_stream) { exporter->sctp_mode &= ~FB_F_SCTP_AUTOSTREAM; exporter->sctp_stream = sctp_stream; } /** *fbExporterAutoStream * * @param exporter * * */ void fbExporterAutoStream( fbExporter_t *exporter) { exporter->sctp_mode |= FB_F_SCTP_AUTOSTREAM; } /** *fbExporterSetPRTTL * * @param exporter * @param pr_ttl * * */ void fbExporterSetPRTTL( fbExporter_t *exporter, int pr_ttl) { if (pr_ttl > 0) { exporter->sctp_mode |= FB_F_SCTP_PR_TTL; exporter->sctp_pr_param = pr_ttl; } else { exporter->sctp_mode &= ~FB_F_SCTP_PR_TTL; exporter->sctp_pr_param = 0; } } /** *fbExportMessage * * * @param exporter * @param msgbase * @param msglen * @param err * * @return * */ gboolean fbExportMessage( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err) { /* Ensure stream is open */ if (!exporter->active) { g_assert(exporter->exopen); if (!exporter->exopen(exporter, err)) return FALSE; } /* Attempt to write message */ if (exporter->exwrite(exporter, msgbase, msglen, err)) return TRUE; /* Close exporter on write failure */ if (exporter->exclose) exporter->exclose(exporter); return FALSE; } /** *fbExporterFree * * * @param exporter * */ void fbExporterFree( fbExporter_t *exporter) { fbExporterClose(exporter); if (exporter->exwrite == fbExporterWriteFile) { g_free(exporter->spec.path); } #ifdef HAVE_SPREAD else if (exporter->exwrite == fbExporterSpreadWrite) { fbConnSpreadFree( exporter->spec.spread ); } #endif else { fbConnSpecFree(exporter->spec.conn); } g_slice_free(fbExporter_t, exporter); } /** *fbExporterClose * * * * @param exporter */ void fbExporterClose( fbExporter_t *exporter) { if (exporter->active && exporter->exclose) exporter->exclose(exporter); } /** * fbExporterGetMsgLen * * * @param exporter */ size_t fbExporterGetMsgLen( fbExporter_t *exporter) { return exporter->msg_len; } libfixbuf-1.7.1/src/fbinfomodel.c000644 000770 000024 00000243767 12545036674 021264 0ustar00emilyecoffmessagebus000000 000000 /* ** fbinfomodel.c ** IPFIX Information Model and IE storage management ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #ident "$Id$" struct fbInfoModel_st { GHashTable *ie_table; GHashTable *ie_byname; GStringChunk *ie_names; GStringChunk *ie_desc; GPtrArray *ie_list; }; static fbInfoElement_t defaults[] = { FB_IE_INIT_FULL("octetDeltaCount", 0, 1, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("packetDeltaCount", 0, 2, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("deltaFlowCount", 0, 3, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("protocolIdentifier", 0, 4, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipClassOfService", 0, 5, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("tcpControlBits", 0, 6, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("sourceTransportPort", 0, 7, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("sourceIPv4Address", 0, 8, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("sourceIPv4PrefixLength", 0, 9, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_BITS, 0, 32, FB_UINT_8, NULL), FB_IE_INIT_FULL("ingressInterface", 0, 10, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("destinationTransportPort", 0, 11, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("destinationIPv4Address", 0, 12, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("destinationIPv4PrefixLength", 0, 13, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_BITS, 0, 32, FB_UINT_8, NULL), FB_IE_INIT_FULL("egressInterface", 0, 14, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("ipNextHopIPv4Address", 0, 15, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("bgpSourceAsNumber", 0, 16, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("bgpDestinationAsNumber", 0, 17, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("bgpNextHopIPv4Address", 0, 18, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("postMCastPacketDeltaCount", 0, 19, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postMCastOctetDeltaCount", 0, 20, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_PACKETS | FB_IE_DELTACOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowEndSysUpTime", 0, 21, 4, FB_IE_F_ENDIAN| FB_IE_F_REVERSIBLE | FB_UNITS_MILLISECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("flowStartSysUpTime", 0, 22, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("postOctetDeltaCount", 0, 23, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS | FB_IE_DELTACOUNTER, 0, 0, FB_UINT_64, NULL ), FB_IE_INIT_FULL("postPacketDeltaCount", 0, 24, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_PACKETS | FB_IE_DELTACOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("minimumIpTotalLength", 0, 25, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("maximumIpTotalLength", 0, 26, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("sourceIPv6Address", 0, 27, 16, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("destinationIPv6Address", 0, 28, 16, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("sourceIPv6PrefixLength", 0, 29, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_BITS, 0, 128, FB_UINT_8, NULL), FB_IE_INIT_FULL("destinationIPv6PrefixLength", 0, 30, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_BITS, 0, 128, FB_UINT_8, NULL), FB_IE_INIT_FULL("flowLabelIPv6", 0, 31, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("icmpTypeCodeIPv4", 0, 32, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("igmpType", 0, 33, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), /* NetFlow Compatibility 34-35*/ FB_IE_INIT_FULL("samplingInterval", 0, 34, 4, FB_IE_F_ENDIAN | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingAlgorithm", 0, 35, 1, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("flowActiveTimeout", 0, 36, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("flowIdleTimeout", 0, 37, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_UINT_16, NULL), /* NetFlow Compatibility 38-39 */ FB_IE_INIT_FULL("engineType", 0, 38, 1, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("engineId", 0, 39, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("exportedOctetTotalCount", 0, 40, 8, FB_IE_F_ENDIAN | FB_UNITS_SECONDS | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("exportedMessageTotalCount", 0, 41, 8, FB_IE_F_ENDIAN | FB_UNITS_MESSAGES | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("exportedFlowRecordTotalCount", 0, 42, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ipv4RouterSc", 0, 43, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("sourceIPv4Prefix", 0, 44, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("destinationIPv4Prefix", 0, 45, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("mplsTopLabelType", 0, 46, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("mplsTopLabelIPv4Address", 0, 47, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), /* NetFlow Compatibility 48-50*/ FB_IE_INIT_FULL("flowSamplerID", 0, 48, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("flowSamplerMode", 0, 49, 1, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("flowSamplerRandomInterval", 0, 50, 4, FB_IE_F_ENDIAN | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("classId", 0, 51, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("minimumTTL", 0, 52, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_HOPS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("maximumTTL", 0, 53, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_HOPS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("fragmentIdentification", 0, 54, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("postIpClassOfService", 0, 55, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("sourceMacAddress", 0, 56, 6, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("postDestinationMacAddress", 0, 57, 6, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("vlanId", 0, 58, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("postVlanId", 0, 59, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("ipVersion", 0, 60, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("flowDirection", 0, 61, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipNextHopIPv6Address", 0, 62, 16, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("bgpNextHopIPv6Address", 0, 63, 16, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("ipv6ExtensionHeaders", 0, 64, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("mplsTopLabelStackSection", 0, 70, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection2", 0, 71, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection3", 0, 72, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection4", 0, 73, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection5", 0, 74, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection6", 0, 75, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection7", 0, 76, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection8", 0, 77, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection9", 0, 78, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection10", 0, 79, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("destinationMacAddress", 0, 80, 6, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("postSourceMacAddress", 0, 81, 6, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("interfaceName", 0, 82, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("interfaceDescription", 0, 83, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), /* NetFlow Compatibility */ FB_IE_INIT_FULL("samplerName", 0, 84, FB_IE_VARLEN, FB_IE_IDENTIFIER, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("octetTotalCount", 0, 85, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("packetTotalCount", 0, 86, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flagsAndSamplerId", 0, 87, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("fragmentOffset", 0, 88, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), /* NETFLOW COMPATIBILITY */ FB_IE_INIT_FULL("forwardingStatus", 0, 89, 1, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("mplsVpnRouteDistinguisher", 0, 90, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsTopLabelPrefixLength", 0, 91, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_BITS, 0, 32, FB_UINT_8, NULL), /* NetFlow Compatibility */ FB_IE_INIT_FULL("srcTrafficIndex", 0, 92, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("dstTrafficIndex", 0, 93, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("applicationDescription", 0, 94, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("applicationId", 0, 95, FB_IE_VARLEN, FB_IE_IDENTIFIER, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("applicationName", 0, 96, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("postIpDiffServCodePoint", 0, 98, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 63, FB_UINT_8, NULL), FB_IE_INIT_FULL("multicastReplicationFactor", 0, 99, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("className", 0, 100, FB_IE_VARLEN, 0, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("classificationEngineId", 0, 101, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("layer2packetSectionOffset", 0, 102, 2, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("layer2packetSectionSize", 0, 103, 2, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("layer2packetSectionData", 0, 104, FB_IE_VARLEN, 0, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("bgpNextAdjacentAsNumber", 0, 128, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("bgpPrevAdjacentAsNumber", 0, 129, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("exporterIPv4Address", 0, 130, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("exporterIPv6Address", 0, 131, 16, FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("droppedOctetDeltaCount", 0, 132, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("droppedPacketDeltaCount", 0, 133, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("droppedOctetTotalCount", 0, 134, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("droppedPacketTotalCount", 0, 135, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowEndReason", 0, 136, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("commonPropertiesId", 0, 137, 8, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("observationPointId", 0, 138, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("icmpTypeCodeIPv6", 0, 139, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("mplsTopLabelIPv6Address", 0, 140, 16, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("lineCardId", 0, 141, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("portId", 0, 142, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("meteringProcessId", 0, 143, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("exportingProcessId", 0, 144, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("templateId", 0, 145, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("wlanChannelId", 0, 146, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("wlanSSID", 0, 147, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("flowId", 0, 148, 8, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("observationDomainId", 0, 149, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("flowStartSeconds", 0, 150, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("flowEndSeconds", 0, 151, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("flowStartMilliseconds", 0, 152, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("flowEndMilliseconds", 0, 153, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("flowStartMicroseconds", 0, 154, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("flowEndMicroseconds", 0, 155, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MICROSECONDS, 0,0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("flowStartNanoseconds", 0, 156, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_NANOSECONDS, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("flowEndNanoseconds", 0, 157, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_NANOSECONDS, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("flowStartDeltaMicroseconds", 0, 158, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE| FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("flowEndDeltaMicroseconds", 0, 159, 4, FB_IE_F_ENDIAN| FB_IE_F_REVERSIBLE | FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("systemInitTimeMilliseconds", 0, 160, 8, FB_IE_F_ENDIAN| FB_IE_F_REVERSIBLE | FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("flowDurationMilliseconds", 0, 161, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY | FB_UNITS_MILLISECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("flowDurationMicroseconds", 0, 162, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MICROSECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("observedFlowTotalCount", 0, 163, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ignoredPacketTotalCount", 0, 164, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ignoredOctetTotalCount", 0, 165, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("notSentFlowTotalCount", 0, 166, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("notSentPacketTotalCount", 0, 167, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("notSentOctetTotalCount", 0, 168, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("destinationIPv6Prefix", 0, 169, 16, FB_IE_F_REVERSIBLE, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("sourceIPv6Prefix", 0, 170, 16, FB_IE_F_REVERSIBLE, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("postOctetTotalCount", 0, 171, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postPacketTotalCount", 0, 172, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowKeyIndicator", 0, 173, 8, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postMCastPacketTotalCount", 0, 174, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postMCastOctetTotalCount", 0, 175, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("icmpTypeIPv4", 0, 176, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("icmpCodeIPv4", 0, 177, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("icmpTypeIPv6", 0, 178, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("icmpCodeIPv6", 0, 179, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("udpSourcePort", 0, 180, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("udpDestinationPort", 0, 181, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpSourcePort", 0, 182, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpDestinationPort", 0, 183, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpSequenceNumber", 0, 184, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("tcpAcknowledgementNumber", 0, 185, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("tcpWindowSize", 0, 186, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpUrgentPointer", 0, 187, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpHeaderLength", 0, 188, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipHeaderLength", 0, 189, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("totalLengthIPv4", 0, 190, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("payloadLengthIPv6", 0, 191, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("ipTTL", 0, 192, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_HOPS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("nextHeaderIPv6", 0, 193, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0,FB_UINT_8, NULL), FB_IE_INIT_FULL("mplsPayloadLength", 0, 194, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("ipDiffServCodePoint", 0, 195, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 63, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipPrecedence", 0, 196, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 7, FB_UINT_8, NULL), FB_IE_INIT_FULL("fragmentFlags", 0, 197, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("octetDeltaSumOfSquares", 0, 198, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("octetTotalSumOfSquares", 0, 199, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("mplsTopLabelTTL", 0, 200, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_HOPS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("mplsLabelStackLength", 0, 201, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("mplsLabelStackDepth", 0, 202, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_ENTRIES, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("mplsTopLabelExp", 0, 203, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipPayloadLength", 0, 204, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("udpMessageLength", 0, 205, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("isMulticast", 0, 206, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipv4IHL", 0, 207, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_WORDS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ipv4Options", 0, 208, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("tcpOptions", 0, 209, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("paddingOctets", 0, 210, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("collectorIPv4Address", 0, 211, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("collectorIPv6Address", 0, 212, 16, FB_IE_DEFAULT, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("exportInterface", 0, 213, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("exportProtocolVersion", 0, 214, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("exportTransportProtocol", 0, 215, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("collectorTransportPort", 0, 216, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("exporterTransportPort", 0, 217, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("tcpSynTotalCount", 0, 218, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("tcpFinTotalCount", 0, 219, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("tcpRstTotalCount", 0, 220, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("tcpPshTotalCount", 0, 221, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("tcpAckTotalCount", 0, 222, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("tcpUrgTotalCount", 0, 223, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ipTotalLength", 0, 224, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postNATSourceIPv4Address", 0, 225, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("postNATDestinationIPv4Address", 0, 226, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("postNAPTSourceTransportPort", 0, 227, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("postNAPTDestinationTransportPort", 0, 228, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("natOriginatingAddressRealm", 0, 229, 1, FB_IE_F_ENDIAN | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("natEvent", 0, 230, 1, FB_IE_F_ENDIAN, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("initiatorOctets", 0, 231, 8, FB_IE_F_ENDIAN | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("responderOctets", 0, 232, 8, FB_IE_F_ENDIAN | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("firewallEvent", 0, 233, 1, FB_IE_F_ENDIAN, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ingressVRFID", 0, 234, 4, FB_IE_F_ENDIAN, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("egressVRFID", 0, 235, 4, FB_IE_F_ENDIAN, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("VRFname", 0, 236, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("postMplsTopLabelExp", 0, 237, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("tcpWindowScale", 0, 238, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("biflowDirection", 0, 239, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ethernetHeaderLength", 0, 240, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_OCTETS, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ethernetPayloadLength", 0, 241, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE| FB_IE_IDENTIFIER | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("ethernetTotalLength", 0, 242, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("dot1qVlanId", 0, 243, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_OCTETS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("dot1qPriority", 0, 244, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("dot1qCustomerVlanId", 0, 245, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("dot1qCustomerPriority", 0, 246, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("metroEvcId", 0, 247, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("metroEvcType", 0, 248, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("pseudoWireId", 0, 249, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("pseudoWireType", 0, 250, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("pseudoWireControlWord", 0, 251, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("ingressPhysicalInterface", 0, 252, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("egressPhysicalInterface", 0, 253, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("postDot1qVlanId", 0, 254, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("postDot1qCustomerVlanId", 0, 255, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("ethernetType", 0, 256, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("postIpPrecedence", 0, 257, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 7, FB_UINT_8, NULL), FB_IE_INIT_FULL("collectionTimeMilliseconds", 0, 258, 8, FB_IE_F_ENDIAN | FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("exportSctpStreamId", 0, 259, 2, FB_IE_F_ENDIAN | FB_IE_F_ENDIAN, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("maxExportSeconds", 0, 260, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("maxFlowEndSeconds", 0, 261, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("messageMD5Checksum", 0, 262, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("messageScope", 0, 263, 1, FB_IE_F_ENDIAN, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("minExportSeconds", 0, 264, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("minFlowStartSeconds", 0, 265, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("opaqueOctets", 0, 266, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("sessionScope", 0, 267, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("maxFlowEndMicroseconds", 0, 268, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("maxFlowEndMilliseconds", 0, 269, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("maxFlowEndNanoseconds", 0, 270, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_NANOSECONDS, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("minFlowStartMicroseconds", 0, 271, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("minFlowStartMilliseconds", 0, 272, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("minFlowStartNanoseconds", 0, 273, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_NANOSECONDS, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("collectorCertificate", 0, 274, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("exporterCertificate", 0, 275, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("dataRecordsReliability", 0, 276, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_BOOL, NULL), FB_IE_INIT_FULL("observationPointType", 0, 277, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("newConnectionDeltaCount", 0, 278, 4, FB_IE_F_ENDIAN | FB_IE_DELTACOUNTER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("connectionSumDurationSeconds", 0, 279, 8, FB_IE_F_ENDIAN | FB_UNITS_SECONDS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("connectionTransactionId", 0, 280, 8, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postNATSourceIPv6Address", 0, 281, 16, FB_IE_F_REVERSIBLE, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("postNATDestinationIPv6Address", 0, 282, 16, FB_IE_F_REVERSIBLE, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("natPoolId", 0, 283, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("natPoolName", 0, 284, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("anonymizationFlags", 0, 285, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("anonymizationTechnique", 0, 286, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("informationElementIndex", 0, 287, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("p2pTechnology", 0, 288, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("tunnelTechnology", 0, 289, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("encryptedTechnology", 0, 290, FB_IE_VARLEN, FB_IE_F_REVERSIBLE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("basicList", 0, FB_IE_BASIC_LIST, FB_IE_VARLEN, FB_IE_LIST, 0, 0, FB_BASIC_LIST, NULL), FB_IE_INIT_FULL("subTemplateList", 0, FB_IE_SUBTEMPLATE_LIST, FB_IE_VARLEN, FB_IE_LIST, 0, 0, FB_SUB_TMPL_LIST, NULL), FB_IE_INIT_FULL("subTemplateMultiList", 0, FB_IE_SUBTEMPLATE_MULTILIST, FB_IE_VARLEN, FB_IE_LIST, 0, 0, FB_SUB_TMPL_MULTI_LIST, NULL), FB_IE_INIT_FULL("bgpValidityState", 0, 294, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("IPSecSPI", 0, 295, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("greKey", 0, 296, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("natType", 0, 297, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("initiatorPackets", 0, 298, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("responderPackets", 0, 299, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("observationDomainName", 0, 300, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("selectionSequenceId", 0, 301, 8, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("selectorId", 0, 302, 8, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("informationElementId", 0, 303, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("selectorAlgorithm", 0, 304, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("samplingPacketInterval", 0, 305, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingPacketSpace", 0, 306, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingTimeInterval", 0, 307, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_IE_QUANTITY | FB_UNITS_MICROSECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingTimeSpace", 0, 308, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE| FB_IE_QUANTITY | FB_UNITS_MICROSECONDS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingSize", 0, 309, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingPopulation", 0, 310, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY | FB_UNITS_PACKETS, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("samplingProbability", 0, 311, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("dataLinkFrameSize", 0, 312, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("ipHeaderPacketSection", 0, 313, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("ipPayloadPacketSection", 0, 314, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("dataLinkFrameSection", 0, 315, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsLabelStackSection", 0, 316, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("mplsPayloadPacketSection", 0, 317, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("selectorIdTotalPktsObserved", 0, 318, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("selectorIdTotalPktsSelected", 0, 319, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("absoluteError", 0, 320, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("relativeError", 0, 321, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("observationTimeSeconds", 0, 322, 4, FB_IE_F_ENDIAN | FB_IE_DEFAULT | FB_UNITS_SECONDS, 0, 0, FB_DT_SEC, NULL), FB_IE_INIT_FULL("observationTimeMilliseconds", 0, 323, 8, FB_IE_F_ENDIAN | FB_IE_DEFAULT | FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("observationTimeMicroseconds", 0, 324, 8, FB_IE_F_ENDIAN | FB_IE_DEFAULT | FB_UNITS_MICROSECONDS, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("observationTimeNanoseconds", 0, 325, 8, FB_IE_F_ENDIAN | FB_IE_DEFAULT | FB_UNITS_NANOSECONDS, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("digestHashValue", 0, 326, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashIPPayloadOffset", 0, 327, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashIPPayloadSize", 0, 328, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashOutputRangeMin", 0, 329, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashOutputRangeMax", 0, 330, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashSelectedRangeMin", 0, 331, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashSelectedRangeMax", 0, 332, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashDigestOutput", 0, 333, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_BOOL, NULL), FB_IE_INIT_FULL("hashInitialiserValue", 0, 334, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("selectorName", 0, 335, FB_IE_VARLEN, FB_IE_F_NONE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("upperCILimit", 0, 336, 8, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("lowerCILimit", 0, 337, 8, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("confidenceLevel", 0, 338, 8, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_FLOAT_64, NULL), FB_IE_INIT_FULL("informationElementDataType", 0, 339, 1, FB_IE_F_ENDIAN, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("informationElementDescription", 0, 340, FB_IE_VARLEN, FB_IE_F_NONE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("informationElementName", 0, 341, FB_IE_VARLEN, FB_IE_F_NONE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("informationElementRangeBegin", 0, 342, 8, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("informationElementRangeEnd", 0, 343, 8, FB_IE_F_ENDIAN | FB_IE_QUANTITY, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("informationElementSemantics", 0, 344, 1, FB_IE_F_ENDIAN, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("informationElementUnits", 0, 345, 2, FB_IE_F_ENDIAN, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("privateEnterpriseNumber", 0, 346, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("virtualStationInterfaceId", 0, 347, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("virtualStationInterfaceName", 0, 348, FB_IE_VARLEN, FB_IE_F_NONE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("virtualStationUUID", 0, 349, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("virtualStationName", 0, 350, FB_IE_VARLEN, FB_IE_F_NONE, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("layer2SegmentId", 0, 351, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2OctetDeltaCount", 0, 352, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2OctetTotalCount", 0, 353, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ingressUnicastPacketTotalCount", 0, 354, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ingressMulticastPacketTotalCount", 0, 355, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ingressBroadcastPacketTotalCount", 0, 356, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("egressUnicastPacketTotalCount", 0, 357, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("egressBroadcastPacketTotalCount", 0, 358, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("monitoringIntervalStartMilliSeconds", 0, 359, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("monitoringIntervalEndMilliSeconds", 0, 360, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE |FB_UNITS_MILLISECONDS, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("portRangeStart", 0, 361, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("portRangeEnd", 0, 362, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("portRangeStepSize", 0, 363, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("portRangeNumPorts", 0, 364, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("staMacAddress", 0, 365, 6, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("staIPv4Address", 0, 366, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("wtpMacAddress", 0, 367, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("ingressInterfaceType", 0, 368, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("egressInterfaceType", 0, 369, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("rtpSequenceNumber", 0, 370, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("userName", 0, 371, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("applicationCategoryName", 0, 372, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("applicationSubCategoryName", 0, 373, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("applicationGroupName", 0, 374, FB_IE_VARLEN, FB_IE_DEFAULT, 0, 0, FB_STRING, NULL), FB_IE_INIT_FULL("originalFlowsPresent", 0, 375, 8, FB_IE_F_ENDIAN | FB_IE_DELTACOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("originalFlowsInitiated", 0, 376, 8, FB_IE_F_ENDIAN | FB_IE_DELTACOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("originalFlowsCompleted", 0, 377, 8, FB_IE_F_ENDIAN | FB_IE_DELTACOUNTER | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("distinctCountOfSourceIPAddress", 0, 378, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("distinctCountOfDestinationIPAddress", 0, 379, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("distinctCountOfSourceIPv4Address", 0, 380, 4, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("distinctCountOfDestinationIPv4Address", 0, 381, 4, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("distinctCountOfSourceIPv6Address", 0, 382, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("distinctCountOfDestinationIPv6Address", 0, 383, 8, FB_IE_F_ENDIAN | FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("valueDistributionMethod", 0, 384, 1, FB_IE_F_ENDIAN | FB_IE_DEFAULT, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("rfc3550JitterMilliseconds", 0, 385, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_DT_MILSEC, NULL), FB_IE_INIT_FULL("rfc3550JitterMicroseconds", 0, 386, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_DT_MICROSEC, NULL), FB_IE_INIT_FULL("rfc3550JitterNanoseconds", 0, 387, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_DT_NANOSEC, NULL), FB_IE_INIT_FULL("dot1qDEI", 0, 388, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_BOOL, NULL), FB_IE_INIT_FULL("dot1qCustomerDEI",0, 389,1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_BOOL, NULL), FB_IE_INIT_FULL("flowSelectorAlgorithm", 0, 390, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER | FB_IE_DEFAULT, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("flowSelectedOctetDeltaCount", 0, 391, 8, FB_IE_F_ENDIAN | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowSelectedPacketDeltaCount", 0, 392, 8, FB_IE_F_ENDIAN | FB_UNITS_PACKETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowSelectedFlowDeltaCount", 0, 393, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("selectorIDTotalFlowsObserved", 0, 394, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("selectorIDTotalFlowsSelected", 0, 395, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("samplingFlowInterval", 0, 396, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("samplingFlowSpacing", 0, 397, 8, FB_IE_F_ENDIAN | FB_UNITS_FLOWS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowSamplingTimeInterval", 0, 398, 8, FB_IE_F_ENDIAN | FB_UNITS_MICROSECONDS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("flowSamplingTimeSpacing", 0, 399, 8, FB_IE_F_ENDIAN | FB_UNITS_MICROSECONDS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("hashFlowDomain", 0, 400, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("transportOctetDeltaCount", 0, 401, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("transportPacketDeltaCount", 0, 402, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("originalExporterIPv4Address", 0, 403, 4, FB_IE_F_ENDIAN, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("originalExporterIPv6Address", 0, 404, 16, FB_IE_F_ENDIAN, 0, 0, FB_IP6_ADDR, NULL), FB_IE_INIT_FULL("originalObservationDomainId", 0, 405, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("intermediateProcessId", 0, 406, 4, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("ignoredDataRecordTotalCount", 0, 407, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE| FB_IE_TOTALCOUNTER, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("dataLinkFrameType", 0, 408, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_FLAGS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("sectionOffset", 0, 409, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("sectionExportedOctets", 0, 410, 2, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_QUANTITY, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("dot1qServiceInstanceTag", 0, 411, FB_IE_VARLEN, FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_OCTET_ARRAY, NULL), FB_IE_INIT_FULL("dot1qServiceInstanceId", 0, 412, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_32, NULL), FB_IE_INIT_FULL("dot1qServiceInstancePriority", 0, 413, 1, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("dot1qCustomerSourceMacAddress", 0, 414, 6, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), FB_IE_INIT_FULL("dot1qCustomerDestinationMacAddress", 0,415, 6, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_MAC_ADDR, NULL), /* 416 was duplicate of 352 */ FB_IE_INIT_FULL("postLayer2OctetDeltaCount", 0, 417, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postMCastLayer2OctetDeltaCount", 0, 418, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), /* 419 was duplicate of 353 */ FB_IE_INIT_FULL("postLayer2OctetTotalCount", 0, 420, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("postMCastLayer2OctetTotalCount", 0, 421, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("minimumLayer2TotalLength", 0, 422, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("maximumLayer2TotalLength", 0, 423, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("droppedLayer2OctetDeltaCount", 0, 424, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("droppedLayer2OctetTotalCount", 0, 425, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("ignoredLayer2OctetTotalCount", 0, 426, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("notSentLayer2OctetTotalCount", 0, 427, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2OctetDeltaSumOfSquares", 0, 428, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2OctetTotalSumOfSquares", 0, 429, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_OCTETS, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2FrameDeltaCount", 0, 430, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DELTACOUNTER | FB_UNITS_FRAMES, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("layer2FrameTotalCount", 0, 431, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_FRAMES, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("pseudoWireDestinationIPv4Address", 0, 432, 4, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_DEFAULT, 0, 0, FB_IP4_ADDR, NULL), FB_IE_INIT_FULL("ignoredLayer2FrameTotalCount", 0, 433, 8, FB_IE_F_ENDIAN | FB_IE_F_REVERSIBLE | FB_IE_TOTALCOUNTER | FB_UNITS_FRAMES, 0, 0, FB_UINT_64, NULL), FB_IE_INIT_FULL("NF_F_FW_EXT_EVENT", 0, FB_CISCO_ASA_EVENT_XTRA, 2, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_16, NULL), FB_IE_INIT_FULL("NF_F_FW_EVENT", 0, FB_CISCO_ASA_EVENT_ID, 1, FB_IE_F_ENDIAN | FB_IE_IDENTIFIER, 0, 0, FB_UINT_8, NULL), FB_IE_INIT_FULL("ciscoNetflowGeneric", 0, FB_CISCO_GENERIC, 8, FB_IE_F_ENDIAN, 0, 0, FB_UINT_64, NULL), FB_IE_NULL }; static fbInfoElementSpec_t ie_type_spec[] = { {"informationElementRangeBegin", 0, 0 }, {"informationElementRangeEnd", 0, 0 }, {"privateEnterpriseNumber", 0, 0 }, {"informationElementUnits", 0, 0 }, {"informationElementId", 0, 0 }, {"informationElementDataType", 0, 0 }, {"informationElementSemantics", 0, 0 }, {"paddingOctets", 6, 1 }, {"informationElementName", 0, 0 }, {"informationElementDescription", 0, 0 }, FB_IESPEC_NULL }; uint32_t fbInfoElementHash( fbInfoElement_t *ie) { return ((ie->ent & 0x0000ffff) << 16) | (ie->num << 2) | (ie->midx << 4); } gboolean fbInfoElementEqual( const fbInfoElement_t *a, const fbInfoElement_t *b) { return ((a->ent == b->ent) && (a->num == b->num) && (a->midx == b->midx)); } void fbInfoElementDebug( gboolean tmpl, fbInfoElement_t *ie) { if (ie->len == FB_IE_VARLEN) { fprintf(stderr, "VL %02x %08x:%04x %2u (%s)\n", ie->flags, ie->ent, ie->num, ie->midx, tmpl ? ie->ref.canon->ref.name : ie->ref.name); } else { fprintf(stderr, "%2u %02x %08x:%04x %2u (%s)\n", ie->len, ie->flags, ie->ent, ie->num, ie->midx, tmpl ? ie->ref.canon->ref.name : ie->ref.name); } } static void fbInfoElementFree( fbInfoElement_t *ie) { g_slice_free(fbInfoElement_t, ie); } fbInfoModel_t *fbInfoModelAlloc() { fbInfoModel_t *model = NULL; /* Create an information model */ model = g_slice_new0(fbInfoModel_t); /* Allocate information element tables */ model->ie_table = g_hash_table_new_full( (GHashFunc)fbInfoElementHash, (GEqualFunc)fbInfoElementEqual, NULL, (GDestroyNotify)fbInfoElementFree); model->ie_byname = g_hash_table_new(g_str_hash, g_str_equal); model->ie_list = g_ptr_array_new(); /* Allocate information element name chunk */ model->ie_names = g_string_chunk_new(64); model->ie_desc = g_string_chunk_new(128); /* Add IETF information elements to the information model */ fbInfoModelAddElementArray(model, defaults); /* Return the new information model */ return model; } void fbInfoModelFree( fbInfoModel_t *model) { g_hash_table_destroy(model->ie_byname); g_string_chunk_free(model->ie_names); g_string_chunk_free(model->ie_desc); g_hash_table_destroy(model->ie_table); g_ptr_array_free(model->ie_list, TRUE); g_slice_free(fbInfoModel_t, model); } static void fbInfoModelReversifyName( const char *fwdname, char *revname, size_t revname_sz) { /* paranoid string copy */ strncpy(revname + FB_IE_REVERSE_STRLEN, fwdname, revname_sz - FB_IE_REVERSE_STRLEN - 1); revname[revname_sz - 1] = (char)0; /* uppercase first char */ revname[FB_IE_REVERSE_STRLEN] = toupper(revname[FB_IE_REVERSE_STRLEN]); /* prepend reverse */ memcpy(revname, FB_IE_REVERSE_STR, FB_IE_REVERSE_STRLEN); } #define FB_IE_REVERSE_BUFSZ 256 void fbInfoModelAddElement( fbInfoModel_t *model, fbInfoElement_t *ie) { fbInfoElement_t *model_ie = NULL; fbInfoElement_t *found; char revname[FB_IE_REVERSE_BUFSZ]; /* Allocate a new information element */ model_ie = g_slice_new0(fbInfoElement_t); /* Copy external IE to model IE */ model_ie->ref.name = g_string_chunk_insert(model->ie_names, ie->ref.name); model_ie->midx = 0; model_ie->ent = ie->ent; model_ie->num = ie->num; model_ie->len = ie->len; model_ie->flags = ie->flags; model_ie->min = ie->min; model_ie->max = ie->max; model_ie->type = ie->type; if (ie->description) { model_ie->description = g_string_chunk_insert(model->ie_desc, ie->description); } /* Insert model IE into tables */ if ((found = g_hash_table_lookup(model->ie_table, model_ie))) { /* replace it if already exists */ /* insert will replace but only will replace the value, not the key */ /* since insert frees the value and the key and the value are the */ /* same - this creates a problem. g_hash_table_replace replaces */ /* the key and the value */ g_hash_table_replace(model->ie_table, model_ie, model_ie); } else { g_hash_table_insert(model->ie_table, model_ie, model_ie); } if ((found = g_hash_table_lookup(model->ie_byname, model_ie->ref.name))) { g_ptr_array_remove(model->ie_list, found); } g_ptr_array_add(model->ie_list, model_ie); g_hash_table_insert(model->ie_byname, (char *)model_ie->ref.name,model_ie); /* Short circuit if not reversible or not IANA-managed */ if (!(ie->flags & FB_IE_F_REVERSIBLE)) { return; } /* Allocate a new reverse information element */ model_ie = g_slice_new0(fbInfoElement_t); /* Generate reverse name */ fbInfoModelReversifyName(ie->ref.name, revname, sizeof(revname)); /* Copy external IE to reverse model IE */ model_ie->ref.name = g_string_chunk_insert(model->ie_names, revname); model_ie->midx = 0; model_ie->ent = ie->ent ? ie->ent : FB_IE_PEN_REVERSE; model_ie->num = ie->ent ? ie->num | FB_IE_VENDOR_BIT_REVERSE : ie->num; model_ie->len = ie->len; model_ie->flags = ie->flags; model_ie->min = ie->min; model_ie->max = ie->max; model_ie->type = ie->type; /* Insert model IE into tables */ g_hash_table_insert(model->ie_table, model_ie, model_ie); if ((found = g_hash_table_lookup(model->ie_byname, model_ie->ref.name))) { g_ptr_array_remove(model->ie_list, found); } g_ptr_array_add(model->ie_list, model_ie); g_hash_table_insert(model->ie_byname, (char *)model_ie->ref.name,model_ie); } void fbInfoModelAddElementArray( fbInfoModel_t *model, fbInfoElement_t *ie) { for (; ie->ref.name; ie++) fbInfoModelAddElement(model, ie); } const fbInfoElement_t *fbInfoModelGetElement( fbInfoModel_t *model, fbInfoElement_t *ex_ie) { return g_hash_table_lookup(model->ie_table, ex_ie); } gboolean fbInfoElementCopyToTemplate( fbInfoModel_t *model, fbInfoElement_t *ex_ie, fbInfoElement_t *tmpl_ie) { const fbInfoElement_t *model_ie = NULL; /* Look up information element in the model */ model_ie = fbInfoModelGetElement(model, ex_ie); if (!model_ie) { /* Information element not in model. Note it's alien and add it. */ ex_ie->ref.name = g_string_chunk_insert(model->ie_names, "_alienInformationElement"); ex_ie->flags |= FB_IE_F_ALIEN; fbInfoModelAddElement(model, ex_ie); model_ie = fbInfoModelGetElement(model, ex_ie); g_assert(model_ie); } /* Refer to canonical IE in the model */ tmpl_ie->ref.canon = model_ie; /* Copy model IE to template IE */ tmpl_ie->midx = 0; tmpl_ie->ent = model_ie->ent; tmpl_ie->num = model_ie->num; tmpl_ie->len = ex_ie->len; tmpl_ie->flags = model_ie->flags; tmpl_ie->type = model_ie->type; tmpl_ie->min = model_ie->min; tmpl_ie->max = model_ie->max; tmpl_ie->description = model_ie->description; /* All done */ return TRUE; } const fbInfoElement_t *fbInfoModelGetElementByName( fbInfoModel_t *model, const char *name) { return g_hash_table_lookup(model->ie_byname, name); } const fbInfoElement_t *fbInfoModelGetElementByID( fbInfoModel_t *model, uint16_t id, uint32_t ent) { fbInfoElement_t tempElement; tempElement.midx = 0; tempElement.ent = ent; tempElement.num = id; return fbInfoModelGetElement(model, &tempElement); } gboolean fbInfoElementCopyToTemplateByName( fbInfoModel_t *model, const char *name, uint16_t len_override, fbInfoElement_t *tmpl_ie) { const fbInfoElement_t *model_ie = NULL; /* Look up information element in the model */ model_ie = fbInfoModelGetElementByName(model, name); if (!model_ie) return FALSE; /* Refer to canonical IE in the model */ tmpl_ie->ref.canon = model_ie; /* Copy model IE to template IE */ tmpl_ie->midx = 0; tmpl_ie->ent = model_ie->ent; tmpl_ie->num = model_ie->num; tmpl_ie->len = len_override ? len_override : model_ie->len; tmpl_ie->flags = model_ie->flags; tmpl_ie->type = model_ie->type; tmpl_ie->min = model_ie->min; tmpl_ie->max = model_ie->max; tmpl_ie->description = model_ie->description; /* All done */ return TRUE; } fbTemplate_t *fbInfoElementAllocTypeTemplate( fbInfoModel_t *model, GError **err) { fbTemplate_t *tmpl = NULL; tmpl = fbTemplateAlloc(model); if (!fbTemplateAppendSpecArray(tmpl, ie_type_spec, 0xffffffff, err)) return NULL; fbTemplateSetOptionsScope(tmpl, 1); return tmpl; } gboolean fbInfoElementWriteOptionsRecord( fBuf_t *fbuf, const fbInfoElement_t *model_ie, uint16_t tid, GError **err) { fbInfoElementOptRec_t rec; if (model_ie == NULL) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NOELEMENT, "Invalid [NULL] Information Element"); return FALSE; } rec.ie_range_begin = model_ie->min; rec.ie_range_end = model_ie->max; rec.ie_pen = model_ie->ent; rec.ie_units = FB_IE_UNITS(model_ie->flags); rec.ie_semantic = FB_IE_SEMANTIC(model_ie->flags); rec.ie_id = model_ie->num; rec.ie_type = model_ie->type; memset(rec.padding, 0, sizeof(rec.padding)); rec.ie_name.buf = (uint8_t *)model_ie->ref.name; rec.ie_name.len = strlen(model_ie->ref.name); rec.ie_desc.buf = (uint8_t *)model_ie->description; if (model_ie->description) { rec.ie_desc.len = strlen(model_ie->description); } else { rec.ie_desc.len = 0; } if (!fBufSetExportTemplate(fbuf, tid, err)) { return FALSE; } if (!fBufSetInternalTemplate(fbuf, tid, err)) { return FALSE; } if (!fBufAppend(fbuf, (uint8_t *)&rec, sizeof(rec), err)) { return FALSE; } return TRUE; } gboolean fbInfoElementAddOptRecElement( fbInfoModel_t *model, fbInfoElementOptRec_t *rec) { fbInfoElement_t ie; char name[500]; char description[4096]; if (rec->ie_pen != 0) { ie.min = rec->ie_range_begin; ie.max = rec->ie_range_end; ie.ent = rec->ie_pen; ie.num = rec->ie_id; ie.type = rec->ie_type; strncpy(name, (char *)rec->ie_name.buf, rec->ie_name.len); name[rec->ie_name.len] = '\0'; ie.ref.name = name; strncpy(description, (char *)rec->ie_desc.buf, rec->ie_desc.len); description[rec->ie_desc.len] = '\0'; ie.description = description; ie.flags = 0; ie.flags |= rec->ie_units << 16; ie.flags |= rec->ie_semantic << 8; /* length is inferred from data type */ switch (ie.type) { case FB_OCTET_ARRAY: case FB_STRING: case FB_BASIC_LIST: case FB_SUB_TMPL_LIST: case FB_SUB_TMPL_MULTI_LIST: ie.len = FB_IE_VARLEN; break; case FB_UINT_8: case FB_INT_8: case FB_BOOL: ie.len = 1; break; case FB_UINT_16: case FB_INT_16: ie.len = 2; break; case FB_UINT_32: case FB_INT_32: case FB_DT_SEC: case FB_FLOAT_32: case FB_IP4_ADDR: ie.len = 4; break; case FB_MAC_ADDR: ie.len = 6; break; case FB_UINT_64: case FB_INT_64: case FB_DT_MILSEC: case FB_DT_MICROSEC: case FB_DT_NANOSEC: case FB_FLOAT_64: ie.len = 8; break; case FB_IP6_ADDR: ie.len = 16; default: g_warning("Adding element %s with invalid data type [%d]", name, rec->ie_type); ie.len = FB_IE_VARLEN; } fbInfoModelAddElement(model, &ie); return TRUE; } return FALSE; } gboolean fbInfoModelTypeInfoRecord( fbTemplate_t *tmpl) { /* ignore padding. */ if (fbTemplateContainsAllFlaggedElementsByName(tmpl, ie_type_spec, 0)) { return TRUE; } return FALSE; } guint fbInfoModelCountElements( const fbInfoModel_t *model) { return model->ie_list->len; } void fbInfoModelIterInit( fbInfoModelIter_t *iter, const fbInfoModel_t *model) { iter->model = model; iter->index = 0; } const fbInfoElement_t *fbInfoModelIterNext( fbInfoModelIter_t *iter) { if (iter->index >= iter->model->ie_list->len) { return NULL; } return g_ptr_array_index(iter->model->ie_list, iter->index++); } const fbInfoElement_t *fbInfoModelAddAlienElement( fbInfoModel_t *model, fbInfoElement_t *ex_ie) { const fbInfoElement_t *model_ie = NULL; if (ex_ie == NULL) { return NULL; } /* Information element not in model. Note it's alien and add it. */ ex_ie->ref.name = g_string_chunk_insert(model->ie_names, "_alienInformationElement"); ex_ie->flags |= FB_IE_F_ALIEN; fbInfoModelAddElement(model, ex_ie); model_ie = fbInfoModelGetElement(model, ex_ie); g_assert(model_ie); return model_ie; } libfixbuf-1.7.1/src/fblistener.c000644 000770 000024 00000122617 12545036674 021123 0ustar00emilyecoffmessagebus000000 000000 /*@internal * * fblistener.c * IPFIX Collecting Process connection listener implementation * * ------------------------------------------------------------------------ * Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. * ------------------------------------------------------------------------ * Authors: Brian Trammell * ------------------------------------------------------------------------ * @OPENSOURCE_HEADER_START@ * Use of the libfixbuf system and related source code is subject to the terms * of the following licenses: * * GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 * Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 * * NO WARRANTY * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER * PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY * PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN * "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY * KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT * LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, * MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE * OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, * SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY * TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF * WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. * LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF * CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON * CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE * DELIVERABLES UNDER THIS LICENSE. * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie * Mellon University, its trustees, officers, employees, and agents from * all claims or demands made against them (and any related losses, * expenses, or attorney's fees) arising out of, or relating to Licensee's * and/or its sub licensees' negligent use or willful misuse of or * negligent conduct or willful misconduct regarding the Software, * facilities, or other rights or assistance granted by Carnegie Mellon * University under this License, including, but not limited to, any * claims of product liability, personal injury, death, damage to * property, or violation of any laws or regulations. * * Carnegie Mellon University Software Engineering Institute authored * documents are sponsored by the U.S. Department of Defense under * Contract FA8721-05-C-0003. Carnegie Mellon University retains * copyrights in all material produced under this contract. The U.S. * Government retains a non-exclusive, royalty-free license to publish or * reproduce these documents, or allow others to do so, for U.S. * Government purposes only pursuant to the copyright license under the * contract clause at 252.227.7013. * * @OPENSOURCE_HEADER_END@ * ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #include #ident "$Id$" /** * * Understanding socket handling and collector construction within the * fixbuf listener: * * Error handling on connections in fixbuf is very different between * TCP and UDP connections. The reasons behind this are partial * tied up within the IPFIX standard and its handling of UDP. * But within fixbuf, this needs to be understood in terms of how * collector's are created with respect to listener's. * * For both TCP and UDP, when a listener is created, a listening * socket is created with the listener. (lsock) * * For UDP, the listener sock (lsock) is the socket used to create * the collector. The collector gets created immediately, and the * collector is the structure that is associated with the fBuf * structure which actually handles PDU's. * * For TCP, the case is different. The listening socket is used * primarily for the listenerWait call. It is used as a socket * passed to select waiting for connection establishment. Then * an accept call is made which creates a new socket handle. * That socket handle is used is to create the collector, and the * lsock handle is left only within the listener. * * When an error occurs, the normal usage of the API would be * to call fBufFree and call listenerWait again. In the case * of TCP this works. The library will wait for a new connection * to the listener lsock and create a new collector from a new * socket from the accept call. For UDP, this will not work, and * the library will simply hang. (Each lsock also has a * corresponding set of pipes to detect interrupts) and the select * call will simply wait on the read pipe handle. * * */ #define MAX_BUFFER_FREE 100 /* Maximum number of connections allowed by fixbuf */ #define MAX_CONNECTIONS 25 struct fbListener_st { /** Connection specifier for passive socket. */ fbConnSpec_t *spec; /** Base session. Used for internal templates. */ fbSession_t *session; /** UDP Base Session. Only set for UDP listeners. * Since UDP sessions are created at connection time, * this holds the first one so we can free it. */ fbSession_t *udp_session; /** Last buffer returned by fbListenerWait(). */ fBuf_t *lastbuf; /** The set of file descriptors to be monitored */ struct pollfd *pfd_array; /** size of array */ nfds_t pfd_len; /** Holds last file descriptor used */ int lsock; /** mode (-1 for udp) */ int mode; /** * Interrupt pipe read end file descriptor. * Used to unblock a call to fbListenerWait(). */ int rip; /** * Interrupt pipe write end file descriptor. * Used to unblock a call to fbListenerWait(). */ int wip; /** * used to hold the handle to the collector for * this listener */ fbCollector_t *collectorHandle; /** * File descriptor table. * Maps file descriptors to active listener-managed buffer instances. */ GHashTable *fdtab; /** * Application initialization function. Allows the application * to bind internal context to a collector, and to reject connections * after accept() but before session setup. */ fbListenerAppInit_fn appinit; /** Application free function. Frees storage allocated by appinit. */ fbListenerAppFree_fn appfree; }; typedef struct fbListenerWaitFDSet_st { fd_set fds; int maxfd; fBuf_t *fbuf; } fbListenerWaitFDSet_t; /** * Structure that holds the listeners that are added to the group. */ struct fbListenerGroup_st { /** pointer to the head of the listener group result list */ fbListenerEntry_t *head; /** pointer to the last fbListener */ fbListenerEntry_t *lastlist; /** pointer to a generic structure for future use */ struct pollfd *group_pfd; /** length of usable fds */ nfds_t pfd_len; }; /** * fbListenerTeardownSocket * * * * */ static void fbListenerTeardownSocket( fbListener_t *listener) { unsigned int i; if (listener->pfd_len) { for (i = 0; i < listener->pfd_len; i++) { if (listener->pfd_array[i].fd >= 0) { close(listener->pfd_array[i].fd); listener->pfd_array[i].fd = -1; } } g_slice_free1((MAX_CONNECTIONS * sizeof(struct pollfd)), listener->pfd_array); listener->pfd_len = 0; } } /** *fbListenerInitSocket * * * * */ static gboolean fbListenerInitSocket( fbListener_t *listener, GError **err) { int pfd[2]; int i = 0; struct pollfd *cpfd = NULL; struct addrinfo *ai = NULL; struct addrinfo *current = NULL; /* Create interrupt pipe */ if (pipe(pfd)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "fbListener error creating interrupt pipe: %s", strerror(errno)); return FALSE; } /* Look up the passive socket address */ if (!fbConnSpecLookupAI(listener->spec, TRUE, err)) { fbListenerTeardownSocket(listener); return FALSE; } ai = (struct addrinfo *)listener->spec->vai; current = ai; /* figure out how many addresses there are */ while (current) { i++; current = current->ai_next; } listener->pfd_array = (struct pollfd*)g_slice_alloc0(MAX_CONNECTIONS * sizeof(struct pollfd)); if (listener->pfd_array == NULL) { return FALSE; } listener->pfd_len = i+2; /* read interrupt pipe */ listener->pfd_array[0].fd = pfd[0]; listener->pfd_array[0].events = POLLIN; /* write interrupt pipe */ listener->pfd_array[1].fd = pfd[1]; i = 2; /* Create the passive socket */ do { cpfd = &listener->pfd_array[i]; /* * Kludge for SCTP. addrinfo doesn't accept SCTP hints. */ #if FB_ENABLE_SCTP if ((listener->spec->transport == FB_SCTP) || (listener->spec->transport == FB_DTLS_SCTP)) { ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = IPPROTO_SCTP; } #endif /* Create socket and bind it to the passive address */ cpfd->fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (cpfd->fd < 0) { i++; continue; } if (bind(cpfd->fd, ai->ai_addr, ai->ai_addrlen) == -1) { close(cpfd->fd); cpfd->fd = -1; i++; continue; } cpfd->events = POLLIN; /* Listen only on socket and sequenced packet sockets */ if ((ai->ai_socktype == SOCK_STREAM) #ifdef SOCK_SEQPACKET || (ai->ai_socktype == SOCK_SEQPACKET) #endif ) { if (listen(cpfd->fd, 1) < 0) { close(cpfd->fd); cpfd->fd = -1; i++; continue; } } i++; } while ((ai = ai->ai_next)); /* check for no listenable socket */ if (i == 2) { fbListenerTeardownSocket(listener); g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "couldn't create socket listening to %s:%s: %s", listener->spec->host ? listener->spec->host : "*", listener->spec->svc, strerror(errno)); return FALSE; } /* All done. */ return TRUE; } /** *fbListenerInitUDPSocket * * * * */ static gboolean fbListenerInitUDPSocket( fbListener_t *listener, GError **err) { void *ctx = NULL; fbCollector_t *collector = NULL; fBuf_t *fbuf = NULL; unsigned int i; /* Simulate accept on UDP socket */ /* Ask application for context */ if (listener->appinit) { if (!listener->appinit(listener, &ctx, listener->lsock, NULL, 0, err)){ return FALSE; } } /* Create collector on UDP socket */ switch (listener->spec->transport) { case FB_UDP: collector = fbCollectorAllocSocket(listener, ctx, listener->lsock, NULL, 0); break; #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: collector = fbCollectorAllocTLS(listener, ctx, listener->lsock, NULL, 0, err); break; #endif default: g_assert_not_reached(); } /* Check for collector alloc error */ if (!collector) return FALSE; /* Create a buffer with a cloned session around the collector */ fbuf = fBufAllocForCollection(fbSessionClone(listener->session),collector); /* add this fbuf for all file descriptors */ for (i = 2; i < listener->pfd_len; i++) { g_hash_table_insert(listener->fdtab, GINT_TO_POINTER(listener->pfd_array[i].fd), fbuf); } /* Add collector to the file descriptor table */ /*g_hash_table_insert(listener->fdtab, GINT_TO_POINTER(listener->lsock), fbuf);*/ /* No more passive socket */ /*listener->lsock = -1;*/ /* set mode to UDP */ listener->mode = -1; /* store this session so we can free it later */ listener->udp_session = fBufGetSession(fbuf); /* store the handle to the collector */ listener->collectorHandle = collector; /* All done. */ return TRUE; } /** *fbListenerAlloc * * * * */ fbListener_t *fbListenerAlloc( fbConnSpec_t *spec, fbSession_t *session, fbListenerAppInit_fn appinit, fbListenerAppFree_fn appfree, GError **err) { fbListener_t *listener = NULL; gboolean ownSocket; if (spec) { ownSocket = FALSE; } else { ownSocket = TRUE; } /* Allocate a new listener */ listener = g_slice_new0(fbListener_t); /* -1 for file descriptors means no fd */ listener->lsock = -1; listener->rip = -1; listener->wip = -1; if (ownSocket) { /* user handling own socket creation and connections */ listener->spec = NULL; } else { listener->spec = fbConnSpecCopy(spec); } /* Fill in what we can */ listener->session = session; listener->appinit = appinit; listener->appfree = appfree; /* allocate file descriptor table */ listener->fdtab = g_hash_table_new(g_direct_hash, g_direct_equal); if (!ownSocket) { /* Do transport-specific initialization */ switch (spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: #endif #endif case FB_TCP: #if HAVE_OPENSSL case FB_TLS_TCP: #endif if (!fbListenerInitSocket(listener, err)) { goto err; } break; case FB_UDP: #if HAVE_OPENSSL_DTLS case FB_DTLS_UDP: #endif /* FIXME this may leak on socket setup error for UDP. */ if (fbListenerInitSocket(listener, err)) { if (!fbListenerInitUDPSocket(listener, err)) { fbListenerTeardownSocket(listener); goto err; } } else { goto err; } break; default: #ifndef FB_ENABLE_SCTP if (spec->transport == FB_SCTP || spec->transport == FB_DTLS_SCTP){ g_error("Libfixbuf not enabled for SCTP Transport. " " Run configure with --with-sctp"); } #endif if (spec->transport == FB_TLS_TCP || spec->transport == FB_DTLS_SCTP || spec->transport == FB_DTLS_UDP) { g_error("Libfixbuf not enabled for this mode of transport. " " Run configure with --with-openssl"); } } } /* Return the initialized listener */ return listener; err: if (listener) { if (listener->fdtab) { g_hash_table_destroy(listener->fdtab); } g_slice_free(fbListener_t, listener); } /* No listener */ return NULL; } /** * fbListenerFreeBuffer * * * * */ static void fbListenerFreeBuffer( void *vfd __attribute__((unused)), fBuf_t *fbuf, /* void *vignore __attribute__((unused)) )*/ fBuf_t **lfbuf) { /* free the buffer; this will close the socket. */ /* fBufFree(fbuf);*/ /* we can't change the hash table while we are looping through it */ *lfbuf = fbuf; lfbuf++; } /** * fbListenerAppFree * * */ void fbListenerAppFree( fbListener_t *listener, void *ctx) { if (listener) { if (listener->appfree) { (listener->appfree)(ctx); } } } /** *fbListenerFree * * * * */ void fbListenerFree( fbListener_t *listener) { fBuf_t *tfbuf[MAX_BUFFER_FREE+1]; fBuf_t *lfbuf = NULL; fbSession_t *session = NULL; unsigned int loop = 0; while (loop < MAX_BUFFER_FREE) { tfbuf[loop] = NULL; loop++; } /* shut down passive socket */ fbListenerTeardownSocket(listener); /* free any open buffers we may have */ g_hash_table_foreach(listener->fdtab, (GHFunc)fbListenerFreeBuffer, tfbuf); loop = 0; lfbuf = tfbuf[0]; /* free first session */ if (listener->udp_session) { /* we need to get the session set on the fBuf - it should be the same as udp_session in the case that we haven't received anything*/ session = fBufGetSession(lfbuf); if (listener->udp_session != session) { fbSessionFree(listener->udp_session); } } if (listener->mode == -1) { /* for UDP there can be multiple FDs with the same fBuf */ /* And there should only be 1 fBuf for this listener */ fBufFree(lfbuf); } else { while (lfbuf && loop < MAX_BUFFER_FREE) { fBufFree(lfbuf); loop++; lfbuf = tfbuf[loop]; } } /* free the listener table */ g_hash_table_destroy(listener->fdtab); /* free the connection specifier */ fbConnSpecFree(listener->spec); /* free the listener itself */ g_slice_free(fbListener_t, listener); } /** *fbListenerWaitAddFD * * * * */ /*static void fbListenerWaitAddFD( void *vfd, void *vignore __attribute__((unused)), fbListenerWaitFDSet_t *lfdset) { int fd = GPOINTER_TO_INT(vfd); FD_SET(fd,&(lfdset->fds)); if (fd > lfdset->maxfd) lfdset->maxfd = fd; } */ /** * fbListenerWaitSearch * * * * */ /*static void fbListenerWaitSearch( void *vfd, void *fbuf, fbListenerWaitFDSet_t *lfdset) { int fd = GPOINTER_TO_INT(vfd); if (FD_ISSET(fd,&(lfdset->fds))) { lfdset->fbuf = fbuf; } }*/ /** * fbListenerAddPollFD * * */ static void fbListenerAddPollFD( struct pollfd *fd_array, nfds_t *array_len, int fd) { nfds_t i; nfds_t num_fds = *array_len; gboolean added = FALSE; /* use an old entry for this new entry */ for (i = 0; i < num_fds; i++) { if (fd_array[i].fd < 0) { fd_array[i].fd = fd; fd_array[i].events = POLLIN; added = TRUE; break; } } /* no free entries in the array, add a new one */ if (!added) { fd_array[num_fds].fd = fd; fd_array[num_fds].events = POLLIN; num_fds++; *array_len = num_fds; } } /** * fbListenerWaitAccept * * * * */ static fBuf_t *fbListenerWaitAccept( fbListener_t *listener, GError **err) { int asock; union { struct sockaddr so; struct sockaddr_in ip4; struct sockaddr_in6 ip6; } peer; socklen_t peerlen; void *ctx = NULL; fbCollector_t *collector = NULL; fBuf_t *fbuf = NULL; /* Accept the connection */ peerlen = sizeof(peer); asock = accept(listener->lsock, &(peer.so), &peerlen); if (asock < 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener accept error: %s", strerror(errno)); return NULL; } /* Okay, we have a socket. Ask the application for context. */ if (listener->appinit) { if (!listener->appinit(listener, &ctx, asock, &(peer.so), peerlen, err)) { close(asock); return NULL; } } /* Create a collector as appropriate */ switch (listener->spec->transport) { #if FB_ENABLE_SCTP case FB_SCTP: #endif case FB_TCP: collector = fbCollectorAllocSocket(listener, ctx, asock, &(peer.so), peerlen); break; #if HAVE_OPENSSL #if HAVE_OPENSSL_DTLS_SCTP case FB_DTLS_SCTP: #endif case FB_TLS_TCP: collector = fbCollectorAllocTLS(listener, ctx, asock, &(peer.so), peerlen, err); break; #endif default: g_assert_not_reached(); } /* Check for collector creation error */ if (!collector) return NULL; /* Create a buffer with a cloned session around the collector */ fbuf = fBufAllocForCollection(fbSessionClone(listener->session),collector); /* Make the buffer automatic */ fBufSetAutomaticMode(fbuf, TRUE); /* Add buffer to the file descriptor table */ g_hash_table_insert(listener->fdtab, GINT_TO_POINTER(asock), fbuf); /* don't add to array if fbListenerWaitNoCollectors was called */ if (listener->mode < 1) { /* add to poll array */ if (listener->pfd_len < MAX_CONNECTIONS) { fbListenerAddPollFD(listener->pfd_array, &listener->pfd_len,asock); } else { g_warning("Max connections %d reached.", MAX_CONNECTIONS); } } listener->lsock = asock; /* store the collector handle */ listener->collectorHandle = collector; /* All done. */ return fbuf; } /** * fbListenerRemove * * * * */ void fbListenerRemove( fbListener_t *listener, int fd) { unsigned int i; /* remove from hash table */ g_hash_table_remove(listener->fdtab, GINT_TO_POINTER(fd)); /* remove from poll array */ for (i = 0; i < listener->pfd_len; i++) { if (listener->pfd_array[i].fd == fd) { if (listener->lsock == fd) { /* unset lsock */ listener->lsock = 0; } close(listener->pfd_array[i].fd); listener->pfd_array[i].fd = -1; break; } } } /** * fbListenerWait * * * * */ fBuf_t *fbListenerWait( fbListener_t *listener, GError **err) { fBuf_t *fbuf = NULL; uint8_t byte; int got_sock = -1; int rc; unsigned int i; /* wait for data available on one of our file descriptors */ rc = poll(listener->pfd_array, listener->pfd_len, -1); if (rc < 0) { if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Interrupted listener wait"); return NULL; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener wait error: %s", strerror(errno)); return NULL; } } /* Loop through file descriptors */ for (i = 0; i < listener->pfd_len; i++) { struct pollfd *pfd = &listener->pfd_array[i]; if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) { /* hang up or error */ got_sock = pfd->fd; break; } if (!(pfd->revents & POLLIN)) { continue; } if (i == 0) { /* read or write interrupt */ /* consume and ignore return */ read(pfd->fd, &byte, sizeof(byte)); g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "External interrupt on pipe"); return NULL; } got_sock = pfd->fd; break; } /* quick solution - check if the fd is the same as last time */ if ((listener->lsock == got_sock) && listener->lastbuf) { return listener->lastbuf; } listener->lsock = got_sock; /* different than last time -> check to see if it's been seen before */ if ((fbuf =g_hash_table_lookup(listener->fdtab,GINT_TO_POINTER(got_sock)))) { listener->lastbuf = fbuf; if (listener->mode < 0) { /* if UDP set FD on collector for reading */ fbCollectorSetFD(fBufGetCollector(fbuf), got_sock); } return fbuf; } else { if (listener->mode >= 0) { /* new connection */ fbuf = fbListenerWaitAccept(listener, err); if (!fbuf) return NULL; listener->lastbuf = fbuf; return fbuf; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener wait error: invalid FD"); /* this is strange bc UDP fbufs are set in fblisteneralloc */ return NULL; } } } fBuf_t *fbListenerWaitNoCollectors( fbListener_t *listener, GError **err) { fBuf_t *fbuf = NULL; uint8_t byte; int rc; unsigned int i; /* set the mode to 1 so fbListenerWaitAccept doesn't add fd */ listener->mode = 1; /* wait for data available on one of our file descriptors */ rc = poll(listener->pfd_array, listener->pfd_len, -1); if (rc < 0) { if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Interrupted listener wait"); return NULL; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener wait error: %s", strerror(errno)); return NULL; } } /* Loop file descriptors */ for (i = 0; i < listener->pfd_len; i++) { struct pollfd *pfd = &listener->pfd_array[i]; if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) { listener->lsock = pfd->fd; break; } if (!(pfd->revents & POLLIN)) { continue; } if (i == 0) { /* read or write interrupt */ /* consume and ignore return */ read(pfd->fd, &byte, sizeof(byte)); g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "External interrupt on pipe"); return NULL; } listener->lsock = pfd->fd; break; } /* handle any pending accept, return the accepted buffer immediately. */ if (listener->mode >= 0) { return fbListenerWaitAccept(listener, err); } else { /* For UDP this doesn't really work, just return the data */ if ((fbuf = g_hash_table_lookup(listener->fdtab, GINT_TO_POINTER(listener->lsock)))) { fbCollectorSetFD(fBufGetCollector(fbuf), listener->lsock); return fbuf; } } /* this should never happen */ return NULL; } static void fbListenerInterruptCollectors( void *vfd __attribute__((unused)), void *fbuf, fbListenerWaitFDSet_t *lfdset __attribute__((unused))) { fBufInterruptSocket(fbuf); } /** * fbListenerInterrupt * * * * */ void fbListenerInterrupt( fbListener_t *listener) { uint8_t byte = 0xe7; /* send interrrupts to the collectors, then to the listener */ g_hash_table_foreach(listener->fdtab, (GHFunc)fbListenerInterruptCollectors, NULL); /* write and ignore return */ /*write(listener->wip, &byte, sizeof(byte)); write(listener->rip, &byte, sizeof(byte));*/ write(listener->pfd_array[0].fd, &byte, sizeof(byte)); write(listener->pfd_array[1].fd, &byte, sizeof(byte)); } /** * fbListenerGetConnSpec * * * * */ fbConnSpec_t *fbListenerGetConnSpec( fbListener_t *listener) { return listener->spec; } /** *fbListenerGetCollector * * gets the collector allocated to the listener * */ gboolean fbListenerGetCollector( fbListener_t *listener, fbCollector_t **collector, GError **err) { if (NULL == listener->collectorHandle) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "no collector available to be retrieved"); return FALSE; } *collector = listener->collectorHandle; return TRUE; } /* returns NULL or pointer to allocated group structure */ fbListenerGroup_t* fbListenerGroupAlloc( void) { fbListenerGroup_t *group = NULL; group = g_slice_new0( fbListenerGroup_t ); if (!group) { return NULL; } group->group_pfd = (struct pollfd*)g_slice_alloc0(MAX_CONNECTIONS* 5 *sizeof(struct pollfd)); group->head = NULL; return group; } /** * fbListenerGroupFree * * frees a listener group * */ void fbListenerGroupFree( fbListenerGroup_t *group) { if (group->group_pfd) { g_slice_free1((MAX_CONNECTIONS * 5 * sizeof(struct pollfd)), group->group_pfd); } g_slice_free(fbListenerGroup_t, group); } /** * fbListenerGroupAddListener * * @return 0 upon success. "1" if entry couldn't get created * maybe "2" if either of the incoming pointers is NULL */ int fbListenerGroupAddListener( fbListenerGroup_t *group, const fbListener_t *listener) { fbListenerEntry_t *entry = NULL; unsigned int i; if (!group || !listener) { return 2; } entry = g_slice_new0( fbListenerEntry_t ); if (!entry) { /* needs to be something like ERR_NO_MEM */ return 1; } entry->prev = NULL; entry->next = group->head; entry->listener = (fbListener_t*)listener; if (group->head) { group->head->prev = entry; } group->head = entry; /* add FDs */ for (i = 0; i < entry->listener->pfd_len; i++) { group->group_pfd[group->pfd_len].fd = entry->listener->pfd_array[i].fd; group->group_pfd[group->pfd_len].events = POLLIN; group->pfd_len++; } group->lastlist = entry; return 0; } /** * fbListenerGroupDeleteListener * * @return 0 on success. "1" if not found. "2" if a pointer is NULL */ int fbListenerGroupDeleteListener( fbListenerGroup_t *group, const fbListener_t *listener) { fbListenerEntry_t *entry = NULL; unsigned int i, k; if (!group || !listener) { return 2; } for (entry = group->head; entry; entry = entry->next) { if (entry->listener == listener) { if (entry->prev) { entry->prev->next = entry->next; } if (entry->next) { entry->next->prev = entry->prev; } /* remove FDs (close will happen later) */ for (i = 0; i < entry->listener->pfd_len; i++) { for (k = 0; k < group->pfd_len; k++) { if (entry->listener->pfd_array[i].fd == group->group_pfd[k].fd) { group->group_pfd[k].fd = -1; break; } } } if (entry == group->lastlist) { group->lastlist = group->head; } g_slice_free(fbListenerEntry_t, entry); return 0; } } return 1; } fbListenerGroupResult_t *fbListenerNewResult( fbListenerGroupResult_t **resultList, fbListener_t *listener) { fbListenerGroupResult_t *result = NULL; /* allocate new one */ result = g_slice_new0( fbListenerGroupResult_t ); /* set buffer to last one */ result->fbuf = listener->lastbuf; /* set listener */ result->listener = listener; /* put it on the list */ result->next = *resultList; *resultList = result; return result; } void fbListenerFreeGroupResult( fbListenerGroupResult_t *result) { fbListenerGroupResult_t *cr, *nr; for (cr = result; cr; cr = nr) { nr = cr->next; g_slice_free(fbListenerGroupResult_t, cr); } } fbListenerGroupResult_t* fbListenerGroupWait( fbListenerGroup_t *group, GError **err) { gboolean found; uint8_t byte; unsigned int i, k; int rc; int new_fd = -1; fBuf_t *fbuf = NULL; fbListenerEntry_t *entry = NULL; fbListenerGroupResult_t *resultHead = NULL; fbListenerGroupResult_t *result = NULL; g_assert(group); /* wait for data available on one of our file descriptors */ while (!resultHead) { rc = poll(group->group_pfd, group->pfd_len, -1); if (rc < 0) { if (errno == EINTR) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "Interrupted listener wait"); return NULL; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener wait error: %s", strerror(errno)); return NULL; } } /* Loop file descriptors */ for (i = 0; i < group->pfd_len; i++) { struct pollfd *pfd = &group->group_pfd[i]; found = FALSE; if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) { /* hang up or error */ new_fd = pfd->fd; } else if (!(pfd->revents & POLLIN)) { continue; } new_fd = pfd->fd; /* check to see if this belongs to the last listener */ if (new_fd == group->lastlist->listener->lsock) { result = fbListenerNewResult(&resultHead, group->lastlist->listener); continue; } /* find out which listener this belongs to */ for (entry = group->head; entry; entry = entry->next) { /* handle interrupt pipe read end */ for (k = 0; k < entry->listener->pfd_len; k++) { struct pollfd *cpfd = &entry->listener->pfd_array[k]; if (new_fd == cpfd->fd) { if (k == 0) { /* read or write interrupt */ /* consume and ignore return */ read(cpfd->fd, &byte, sizeof(byte)); g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "External interrupt on pipe"); return NULL; } if ((entry->listener->lsock == new_fd) && entry->listener->lastbuf) { result = fbListenerNewResult(&resultHead, entry->listener); found = TRUE; group->lastlist = entry; break; } entry->listener->lsock = new_fd; /* Look it up */ if ((fbuf = g_hash_table_lookup(entry->listener->fdtab, GINT_TO_POINTER(new_fd)))) { if (entry->listener->mode < 0) { fbCollectorSetFD(fBufGetCollector(fbuf), new_fd); } entry->listener->lastbuf = fbuf; result = fbListenerNewResult(&resultHead, entry->listener); group->lastlist = entry; found = TRUE; break; } else { if (entry->listener->mode >= 0) { /* TCP - call accept */ fbuf = fbListenerWaitAccept(entry->listener, err); entry->listener->lastbuf = fbuf; result = fbListenerNewResult(&resultHead, entry->listener); if (group->pfd_len < (MAX_CONNECTIONS * 5)) { fbListenerAddPollFD(group->group_pfd, &group->pfd_len, entry->listener->lsock); } else { g_warning("Maximum connections reached " "for Listener Group (%d)", group->pfd_len); } found = TRUE; group->lastlist = entry; break; } else { /* shouldn't happen */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IO, "listener wait error: invalid FD"); return NULL; } } } /* new_fd == cpfd->fd */ } /* listener->pfd_array for loop */ if (found) { break; } } /* listenergroup for loop */ if (!found) { /* close the old one, it doesn't belong to any listeners it most likely was closed on the listener */ close(pfd->fd); pfd->fd = -1; } } /* loop through fd's */ } /* !resultHead */ return resultHead; } /* Given a socket descriptor with an existing connection, return an fbuf * fBufNext can be called on it * Interrupting the accepting of new connections on this socket is the * responsibility of the caller, it cannot be done with * fbListenerInterrupt(). However, the collectors attached to this listener * can be interrupted by this call, which short circuits fBufNext(). * Call fbListenerInterrupt to stop the collectors, then stop the listener * socket on your own. */ fBuf_t *fbListenerOwnSocketCollectorTCP( fbListener_t *listener, int sock, GError **err) { fbCollector_t *collector = NULL; fBuf_t *fbuf = NULL; fbConnSpec_t connSpec; g_assert(listener); if (sock <= 2) { /* invalid socket */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN, "Invalid socket descriptor"); return NULL; } connSpec.transport = FB_TCP; listener->spec = &connSpec; collector = fbCollectorAllocSocket(listener, NULL, sock, NULL, 0); fbuf = fBufAllocForCollection(fbSessionClone(listener->session),collector); fBufSetAutomaticMode(fbuf, FALSE); /* Add buffer to the file descriptor table */ /* g_hash_table_insert(listener->fdtab, GINT_TO_POINTER(sock), fbuf);*/ listener->lsock = sock; /* store the collector handle */ listener->collectorHandle = collector; listener->spec = NULL; /* All done. */ return fbuf; } /* not even remotely tested yet */ fBuf_t *fbListenerOwnSocketCollectorTLS( fbListener_t *listener, int sock, GError **err) { fbCollector_t *collector = NULL; fBuf_t *fbuf = NULL; g_assert(listener); if (sock <= 2) { /* invalid socket */ return NULL; } listener->spec->transport = FB_TLS_TCP; /* collector = fbCollectorAllocTLS(listener, NULL, sock, NULL, 0, err);*/ fbuf = fBufAllocForCollection(fbSessionClone(listener->session),collector); fBufSetAutomaticMode(fbuf, FALSE); /* Add buffer to the file descriptor table */ /*g_hash_table_insert(listener->fdtab, GINT_TO_POINTER(sock), fbuf);*/ /* store the collector handle */ listener->collectorHandle = collector; listener->lsock = sock; (void)err; /* All done. */ return fbuf; } void fbListenerRemoveLastBuf( fBuf_t *fbuf, fbListener_t *listener) { if (listener->lastbuf == fbuf) { listener->lastbuf = NULL; } } gboolean fbListenerCallAppInit( fbListener_t *listener, fbUDPConnSpec_t *spec, GError **err) { if (listener->appinit) { if (!listener->appinit(listener, &(spec->ctx), listener->lsock, &(spec->peer.so), spec->peerlen, err)) { return FALSE; } } return TRUE; } fbSession_t *fbListenerSetPeerSession( fbListener_t *listener, fbSession_t *session) { fbSession_t *new_session = session; if (!new_session) { new_session = fbSessionClone(listener->session); } listener->session = new_session; fBufSetSession(listener->lastbuf, new_session); fbSessionSetTemplateBuffer(new_session, listener->lastbuf); return new_session; } libfixbuf-1.7.1/src/fbnetflow.c000644 000770 000024 00000163677 12605775773 020776 0ustar00emilyecoffmessagebus000000 000000 /** *@internal * * @file fbnetflow.c * * This implements a Netflow convertor for translating into IPFIX * within the fixbuf structure * * ------------------------------------------------------------------------ * Copyright (C) 2008-2015 Carnegie Mellon University. All Rights Reserved. * ------------------------------------------------------------------------ * Authors: Chris Inacio , Emily Sarneso * ------------------------------------------------------------------------ * @OPENSOURCE_HEADER_START@ * Use of the libfixbuf system and related source code is subject to the terms * of the following licenses: * * GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 * Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 * * NO WARRANTY * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER * PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY * PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN * "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY * KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT * LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, * MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE * OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, * SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY * TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF * WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. * LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF * CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON * CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE * DELIVERABLES UNDER THIS LICENSE. * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie * Mellon University, its trustees, officers, employees, and agents from * all claims or demands made against them (and any related losses, * expenses, or attorney's fees) arising out of, or relating to Licensee's * and/or its sub licensees' negligent use or willful misuse of or * negligent conduct or willful misconduct regarding the Software, * facilities, or other rights or assistance granted by Carnegie Mellon * University under this License, including, but not limited to, any * claims of product liability, personal injury, death, damage to * property, or violation of any laws or regulations. * * Carnegie Mellon University Software Engineering Institute authored * documents are sponsored by the U.S. Department of Defense under * Contract FA8721-05-C-0003. Carnegie Mellon University retains * copyrights in all material produced under this contract. The U.S. * Government retains a non-exclusive, royalty-free license to publish or * reproduce these documents, or allow others to do so, for U.S. * Government purposes only pursuant to the copyright license under the * contract clause at 252.227.7013. * * @OPENSOURCE_HEADER_END@ * ------------------------------------------------------------------------ * * @Author: $Author$ * @Date: $Date$ * @Version: $Revision$ * */ #define _FIXBUF_SOURCE_ #include #include "fbcollector.h" #include #ident "$Id$" #ifndef FB_NETFLOW_DEBUG # define FB_NETFLOW_DEBUG 0 #endif #define NF_MAX_SEQ_DIFF 100 #define NF_OUT_OF_ORDER 10 #define NF_REBOOT_SECS 60 * 1000 /* 1 min in milliseconds */ #if HAVE_ALIGNED_ACCESS_REQUIRED #define fb_ntohll(x) (x) #define fb_htonll(x) fb_ntohll(x) /** * this set of macros for reading and writing U16's and U32's * uses memcpy's to avoid tripping over alignment issues on * platforms that cannot do unaligned access (e.g. SPARC, Alpha, * etc). The next section, after the else, does not use memcpy's * and operates just fine on architectures that don't crash * from an unaligned access (x86, PowerPC, etc.) */ /** * READU16INC * * read U16 and increment * * read a U16 value from ptr, it assumes the pointer * is properly aligned and pointing at the correct * place; and then increment ptr appropriately * according to its size to adjust for reading a * U16; increments it 2-bytes * * does network to host translation */ #define READU16INC(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ memcpy(&ru16_t16val, ru16_t16ptr, sizeof(uint16_t)); \ assignee = g_ntohs(ru16_t16val); \ ptr += sizeof(*ru16_t16ptr) / sizeof(*ptr); \ } #define READU16(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ memcpy(&ru16_t16val, ru16_t16ptr, sizeof(uint16_t)); \ assignee = g_ntohs(ru16_t16val); \ } #define WRITEU16(ptr,value) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = g_htons(value); \ memcpy(ru16_t16ptr, &ru16_t16val, sizeof(uint16_t)); \ } /** * READU32INC * * read U32 and increment ptr * * read a U32 from the ptr given in ptr, it assumes * it is aligned and positioned correctly, then * increment the ptr appropriately based on its * size and having read a U32 to increment it * 4-bytes ahead * * does network to host translation */ #define READU32INC(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ memcpy(&ru32_t32val, ru32_t32ptr, sizeof(uint32_t)); \ assignee = g_ntohl(ru32_t32val); \ ptr += sizeof(*ru32_t32ptr) / sizeof(*ptr); \ } #define READU32(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ memcpy(&ru32_t32val, ru32_t32ptr, sizeof(uint32_t)); \ assignee = g_ntohl(ru32_t32val); \ } #define WRITEU32(ptr,value) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = g_htonl(value); \ memcpy(ru32_t32ptr, &ru32_t32val, sizeof(uint32_t)); \ } #else #define fb_ntohll(x) \ ((((uint64_t)g_ntohl((uint32_t)((x) & 0xffffffff))) << 32) \ | g_ntohl((uint32_t)(((x) >> 32) & 0xffffffff))) #define fb_htonll(x) fb_ntohll(x) /** * READU16INC * * read U16 and increment * * read a U16 value from ptr, it assumes the pointer * is properly aligned and pointing at the correct * place; and then increment ptr appropriately * according to its size to adjust for reading a * U16; increments it 2-bytes * * does network to host translation */ #define READU16INC(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ ru16_t16val = g_ntohs(*ru16_t16ptr); \ assignee = ru16_t16val; \ ptr += sizeof(*ru16_t16ptr) / sizeof(*ptr); \ } #define READU16(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ ru16_t16val = g_ntohs(*ru16_t16ptr); \ assignee = ru16_t16val; \ } #define WRITEU16(ptr,value) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ *ru16_t16ptr = g_htons(value); \ } /** * READU32INC * * read U32 and increment ptr * * read a U32 from the ptr given in ptr, it assumes * it is aligned and positioned correctly, then * increment the ptr appropriately based on its * size and having read a U32 to increment it * 4-bytes ahead * * does network to host translation */ #define READU32INC(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ ru32_t32val = g_ntohl(*ru32_t32ptr); \ assignee = ru32_t32val; \ ptr += sizeof(*ru32_t32ptr) / sizeof(*ptr); \ } #define READU32(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ ru32_t32val = g_ntohl(*ru32_t32ptr); \ assignee = ru32_t32val; \ } #define WRITEU32(ptr,value) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ *ru32_t32ptr = g_htonl(value); \ } #endif /** mini hash table for Netflow V9 */ typedef struct fbCollectorNetflowV9TemplateHash_st { /** id of the stored template, should be zeroed if not in use */ uint16_t templateId; /** length of the template in question, zero is reserved for an unused field */ uint16_t templateLength; /** boolean flag set if template ID represents an options template */ gboolean optionsTemplate; /** boolean flag set if we added sysuptime field to template */ gboolean addSysUpTime; } fbCollectorNetflowV9TemplateHash_t; typedef struct fbCollectorNetflowV9Session_st { /** template hash */ GHashTable *templateHash; /** potential missed packets */ uint32_t netflowMissed; /** current netflow seq num */ uint32_t netflowSeqNum; /** current ipfix seq num */ uint32_t ipfixSeqNum; } fbCollectorNetflowV9Session_t; /** defines the extra state needed to convert from NetflowV9 to IPFIX */ struct fbCollectorNetflowV9State_st { uint64_t sysUpTime; uint32_t observation_id; fbSession_t *sessionptr; fbCollectorNetflowV9Session_t *session; /* need to keep templates per domain */ GHashTable *domainHash; pthread_mutex_t ts_lock; }; /** * templateHashDestroyHelper * * helps destroy the template hash by translating between the * GLib GDestroyNotify function type definition and using the * GLib slice free function * * @param datum pointer to the structure to be destroyed * */ static void templateHashDestroyHelper ( gpointer datum) { g_slice_free(fbCollectorNetflowV9TemplateHash_t, datum); } static void domainHashDestroyHelper( gpointer datum) { if (((fbCollectorNetflowV9Session_t *)datum)->templateHash) { g_hash_table_destroy(((fbCollectorNetflowV9Session_t *)datum)->templateHash); } g_slice_free(fbCollectorNetflowV9Session_t, datum); } static guint fooHash ( gconstpointer key) { return (guint)((uintptr_t)key); } static gboolean fooEqual ( gconstpointer alpha, gconstpointer beta) { uintptr_t alphaInt = (uintptr_t)alpha; uintptr_t betaInt = (uintptr_t)beta; if (alphaInt == betaInt) { return TRUE; } return FALSE; } /*################################################# * * netflow v9 functions for the collector, used * to optionally read * *#################################################*/ /** * fbCollectorDecodeV9MsgVL * * parses the header of a V9 message and determines * how much needs to be read in order to complete * the message, (at least in theory) * * @param collector a pointer to the collector state * structure * @param hdr a pointer to the beginning of the buffer * to parse as a message (get converted back * into a uint8_t* and used as such) * @param b_len length of the buffer passed in for the * hdr * @param m_len length of the message header that still * needs to be read (always set to zero, since * this reads the entire message) * @param err a pointer to glib error structure, used * if an error occurs during processing the * stream * * * @return number of octets to read to complete * the message */ static gboolean fbCollectorDecodeV9MsgVL( fbCollector_t *collector, fbCollectorMsgVL_t *hdr, size_t b_len, uint16_t *m_len, GError **err) { uint16_t recordCount; uint8_t *dataBuf; uint8_t *bufOffset; uint64_t unix_secs; uint64_t sysuptime; int rc; unsigned int loop; uint16_t setLength; struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; struct setHeader_st { uint16_t setId; uint16_t setLength; } *setHeaderPtr; if (0x0009 != g_ntohs(hdr->n_version)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Illegal NetflowV9 Message version 0x%04x; " "input is probably not a NetflowV9 Message stream.", g_ntohs(hdr->n_version)); *m_len = 0; return FALSE; } /* so this is hopefully a netflow message; I should now be able to read the entire message, it can't be larger than 1 packet, (the question becomes, what's a packet size) */ recordCount = htons(hdr->n_len); dataBuf = (uint8_t *)hdr; bufOffset = dataBuf + sizeof(hdr); /* read the rest of the v9 header, ugly trick ahead: gonna read in the uptime, and then throw away the read and finish reading the rest of the header, dumping the uptime, because we don't really want it */ if ((unsigned int)((bufOffset-dataBuf) + 16) < b_len) { g_set_error(err,FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Error buffer too small to read NetflowV9 message header"); *m_len = 0; return FALSE; } if (TRUE == collector->bufferedStream) { rc = fread(bufOffset, 1, 4, collector->stream.fp); } else { rc = read(collector->stream.fd, bufOffset, 4); } READU32(bufOffset, sysuptime); if (4 != rc) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Could not complete read of the Netflow header"); *m_len = 0; return FALSE; } if (TRUE == collector->bufferedStream) { rc = fread(bufOffset, 1, 12, collector->stream.fp); } else { rc = read(collector->stream.fd, bufOffset, 12); } if (12 != rc) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Could not complete read of the Netflow header"); *m_len = 0; return FALSE; } READU32(bufOffset, unix_secs); bufOffset += 12; /* now calculate time to put in element 160 */ /* convert unix_secs to milliseconds then subtract sysuptime sysuptime = (milliseconds since reboot) */ transState->sysUpTime = (unix_secs * 1000) - sysuptime; transState->sysUpTime = fb_htonll(transState->sysUpTime); /* so we don't really care about what is in the different sets, at this point, we just want to scan through recordCount number of them and read the length from each, and sum it, then we get to rewind the file offset so that we can go record-by-record back out to the application */ for (loop = 0; loop < recordCount; loop++) { if ((unsigned int)((bufOffset-dataBuf) + 4) < b_len) { g_set_error(err,FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Error buffer to small to read NetflowV9 message"); *m_len = 0; return FALSE; } if (TRUE == collector->bufferedStream) { rc = fread(bufOffset, 1, 4, collector->stream.fp); } else { rc = read(collector->stream.fd, bufOffset, 4); } if (4 != rc) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Error reading set header in NetflowV9 message" " expected read of 4 received %d", rc); *m_len = 0; return FALSE; } setHeaderPtr = (struct setHeader_st *)bufOffset; bufOffset += 4; setLength = g_ntohs(setHeaderPtr->setLength); if ((unsigned int)((bufOffset-dataBuf) + setLength) < b_len) { g_set_error(err,FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Error buffer to small to read NetflowV9 message"); *m_len = 0; return FALSE; } if (TRUE == collector->bufferedStream) { rc = fread(bufOffset, 1, setLength, collector->stream.fp); } else { rc = read(collector->stream.fd, bufOffset, setLength); } if (setLength != rc) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Error reading NetflowV9 set payload"); *m_len = 0; return FALSE; } bufOffset += setLength; } *m_len = 0; return TRUE; } /** * fbCollectorMessageHeaderV9 * * this converts a NetFlow V9 header into something every so slightly * closer to an IPFIX header; it dumps the up time with a big memcpy * * @param collector pointer to the collector state structure * @param buffer pointer to the message buffer * @param b_len length of the buffer passed in * @param m_len pointer to the length of the resultant buffer * @param err pointer to a GLib error structure * * @return TRUE on success, FALSE on error */ static gboolean fbCollectorMessageHeaderV9 ( fbCollector_t *collector, uint8_t *buffer, size_t b_len, uint16_t *m_len, GError **err) { uint16_t tempRead16; uint64_t unix_secs; uint64_t sysuptime; struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; if (b_len < 20) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Invalid NetFlow V9 Header. Buffer Length too short. " "Length: %d", (unsigned int)b_len); return FALSE; } /* first make sure the message seems like a NetFlow V9 message */ tempRead16 = g_ntohs(*((uint16_t *)buffer)); if (0x0009 != tempRead16) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "invalid version number for NetFlow V9, expecting 0x0009," " received %#06x", tempRead16); return FALSE; } READU32((buffer + 4), sysuptime); READU32((buffer + 8), unix_secs); READU32((buffer + 16), collector->obdomain); collector->time = time(NULL); /* convert to milliseconds - subtract sysuptime to get time of reboot */ transState->sysUpTime = (unix_secs * 1000) - sysuptime; transState->sysUpTime = fb_htonll(transState->sysUpTime); /* memcpy is no good here because src & dst overlap */ memmove((buffer + 4), (buffer + 8), (b_len - 8)); /* return that we shortened the buffer */ *m_len = b_len - 4; return TRUE; } /** * netflowDataTemplateParse * * this parses a NetFlow V9 template and stores the results * into the template hash for this session. It only stores * the template ID and the length of the resulting record. * it will error out on malformed templates and data records * which are not common between IPFIX and NetFlow V9 * * @param collector pointer to the collector state record * @param dataBuf pointer to the buffer holding the template def * points after the set ID and set length * @param recordLength pointer to the set header length field * @param msgBuf pointer to the start of the netflow PDU * @param msgLen pointer to the length of the whole msg * @param err GError pointer to store the error if one occurs * * @return Number of Templates Parsed * */ static int netflowDataTemplateParse ( fbCollector_t *collector, uint8_t *dataBuf, uint16_t *recordLength, uint8_t *msgBuf, size_t *msgLen, GError **err) { uint16_t templateId = 0; uint16_t fieldCount = 0; uint8_t *bufPtr = dataBuf; uint16_t targetRecSize = 0; uint16_t recLength = g_ntohs(*recordLength); uint16_t lengthParsed = 4; /* to account for set header */ uint8_t *fieldCountPtr; uintptr_t bigTemplateId; unsigned int loop; uint16_t temp; int tmplcount = 0; uint8_t addReversePenFix = 0; gboolean addSysUpTime = FALSE; gpointer hashResult = NULL; struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; struct fbCollectorNetflowV9TemplateHash_st *newTemplate = NULL; fbCollectorNetflowV9Session_t *currentSession = transState->session; if ((recLength < 8) || 0 != (recLength % 4)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow template record is either too short or not a " "multiple of 4 octets, (recLength = %u)", recLength); return 0; } while ( lengthParsed < recLength ) { /* read the template ID */ READU16INC(bufPtr, templateId); fieldCountPtr = bufPtr; /* read the number of data records in the template */ READU16INC(bufPtr, fieldCount); /* lets keep a count of how far we've read into the rec */ lengthParsed += 4; /* subtract 8 from the record length to account for the set header,(type & length 16-bits each)-but this can contain more than 1! */ if (fieldCount > ((recLength - lengthParsed) / 4)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow V9 Field Count is greater than remaining " "record length"); return 0; } /* iterate through each type entry in the template record, make sure the IE model number is within what we can handle and then record the length to build up the length of each template number */ for (loop = 0; loop < fieldCount; loop++) { READU16(bufPtr, temp); if ( 0 == temp ) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow V9 template data record model type is not" " common with IPFIX IE model: Unknown element:%d", temp); return 0; } else if ( temp > 346 ) { /* convert Netflowv9 Arbitrary Element to IPFIX Generic */ /* except for 40005 & 33002 (event ids that are in infomodel)*/ if ( temp == 40005 ) { WRITEU16(bufPtr, FB_CISCO_ASA_EVENT_ID); } else if ( temp == 33002 ) { WRITEU16(bufPtr, FB_CISCO_ASA_EVENT_XTRA); } else if ( temp == 40001 ) { /* postNATSourceIPv4Address */ WRITEU16(bufPtr, 225); } else if ( temp == 40002 ) { /* postNATDestinationIPv4Address */ WRITEU16(bufPtr, 226); } else if ( temp == 40003 ) { /* postNAPTSourceTransportPort */ WRITEU16(bufPtr, 227); } else if ( temp == 40004 ) { /* postNAPTDestinationTransportPort */ WRITEU16(bufPtr, 228); } else { WRITEU16(bufPtr, FB_CISCO_GENERIC); } } /* because the IPFIX standard info model is broken, RFC 5102, we have to convert certain info model elements from their NetFlow v9 values into appropriate IPFIX numbers. (Cisco will be none too pleased) */ /* convert V9 out bytes field into IPFIX reverseOctetDeltaCount */ if (23 == temp) { WRITEU16(bufPtr, (IPFIX_ENTERPRISE_BIT | 1)); addReversePenFix = 1; } /* convert V9 out pkts field into IPFIX reversePacketDeltaCount */ if (24 == temp) { WRITEU16(bufPtr, (IPFIX_ENTERPRISE_BIT | 2)); addReversePenFix = 1; } if ((21 == temp) || (22 == temp)) { /* need at add element 160 for sysuptime */ addSysUpTime = TRUE; } bufPtr += sizeof(uint16_t); lengthParsed += sizeof(uint16_t); /* record how long each element is */ READU16INC(bufPtr, temp); targetRecSize += temp; lengthParsed += sizeof(uint16_t); /* if we're supposed to add the reverse PEN for a NetFlow V9 -> IPFIX info model fix, do it now */ if (0 != addReversePenFix) { addReversePenFix = 0; if (FB_MSGLEN_MAX <= (*msgLen + sizeof(uint32_t))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow V9 unable to convert information model" " elements, no space"); return 0; } /* make space for the extra 32-bit PEN */ memmove((bufPtr + sizeof(uint32_t)), bufPtr, (*msgLen - (bufPtr - msgBuf))); /* write the reverse PEN into the template */ WRITEU32(bufPtr, IPFIX_REVERSE_PEN); bufPtr += sizeof(uint32_t); lengthParsed += sizeof(uint32_t); /* update the length of this set in the set header */ WRITEU16(recordLength, (g_ntohs(*recordLength) + sizeof(uint32_t))); /* update the length that this record is; we error check this value later */ recLength += sizeof(uint32_t); /* also increase the msglen, to note the change */ *msgLen += sizeof(uint32_t); } } /* add the SysUpTime field (IPFIX element 160) to the template */ if (addSysUpTime) { if (FB_MSGLEN_MAX <= (*msgLen + sizeof(uint32_t))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow V9 unable to convert information model " "time elements, no space"); return 0; } memmove((bufPtr + sizeof(uint32_t)), bufPtr, (*msgLen - (bufPtr - msgBuf))); /* add (IPFIX info element 160) */ WRITEU16(bufPtr, 160); bufPtr += sizeof(uint16_t); /* length is 8 */ WRITEU16(bufPtr, 8); bufPtr += sizeof(uint16_t); lengthParsed += sizeof(uint32_t); /* modify the length of this message */ WRITEU16(recordLength,(g_ntohs(*recordLength) + sizeof(uint32_t))); recLength += sizeof(uint32_t); *msgLen += sizeof(uint32_t); /* change fieldcount to add this field */ WRITEU16(fieldCountPtr, fieldCount + 1); } newTemplate = g_slice_new(fbCollectorNetflowV9TemplateHash_t); if (NULL == newTemplate) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TMPL, "could not allocate NetFlow v9 template storage " "record"); return 0; } newTemplate->templateId = templateId; newTemplate->templateLength = targetRecSize; newTemplate->optionsTemplate = FALSE; if (addSysUpTime) { newTemplate->addSysUpTime = TRUE; } else { newTemplate->addSysUpTime = FALSE; } addSysUpTime = FALSE; /* put the template into the hash, check/replace the template that is there if this template number already exists */ if (currentSession->templateHash == NULL) { currentSession->templateHash = g_hash_table_new_full(fooHash, fooEqual, NULL, templateHashDestroyHelper); if (NULL == currentSession->templateHash) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "failure to allocate hash table for NetFlow " "session"); return FALSE; } } bigTemplateId = (uintptr_t)templateId; hashResult = g_hash_table_lookup(currentSession->templateHash, (gconstpointer)bigTemplateId); if (NULL != hashResult) { g_hash_table_replace(currentSession->templateHash, (gpointer)bigTemplateId, newTemplate); } else { g_hash_table_insert(currentSession->templateHash, (gpointer)bigTemplateId, newTemplate); } tmplcount++; #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "template inserted into hash: templateId %d," " templateSize: %d, Domain: %04x, SysUpTime %d, " "fieldCount: %d \n", templateId, targetRecSize, transState->observation_id, newTemplate->addSysUpTime, fieldCount); #endif targetRecSize = 0; /* running tmpl size needs reset */ } /* return the amount of templates we added so we can keep a track of the total number of records parsed */ return tmplcount; } /** * netflowOptionsTemplateParse * * this parses a NetFlow V9 options template and stores the results * into the template hash for this session. It only stores * the template ID and the length of the resulting record. * it will error out on malformed templates * * @param collector pointer to the collector state record * @param dataBuf pointer to the buffer holding the template def * points after the set ID and set length * @param recordLength a pointer to the length of the flowSet * @param err GError pointer to store the error if one occurs * * @return number of templates parsed * */ static int netflowOptionsTemplateParse ( fbCollector_t *collector, uint8_t *dataBuf, uint16_t *recordLength, GError **err) { uint16_t templateId = 0; uint8_t *recOffset = dataBuf; uint8_t *optScopeLenPtr; uint8_t *optLenPtr; uint16_t lengthParsed = 4; /* for set header */ uint16_t optScopeLen, optLen, type, fieldLen; uint16_t templateLength = 0; uintptr_t bigTemplateId; uint16_t recLength = g_ntohs(*recordLength); unsigned int loop; unsigned int fieldCount; gpointer hashResult = NULL; int tmplcount = 0; struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; struct fbCollectorNetflowV9TemplateHash_st *newTemplate = NULL; fbCollectorNetflowV9Session_t *currentSession = transState->session; while (lengthParsed < recLength) { fieldCount = 0; if ((recLength - lengthParsed) < 6) { /* not enough for an options header - probably extra padding */ return tmplcount; } /* read the template ID */ READU16INC(recOffset,templateId); lengthParsed += sizeof(uint16_t); /* keep a placeholder for the options Scope Length because we need to change it to number of Scope Elements for IPFIX */ optScopeLenPtr = recOffset; /* read the length of option scope bytes */ READU16INC(recOffset,optScopeLen); lengthParsed += sizeof(uint16_t); /* keep a placeholder for the options Length because we need to change it to number of elements */ optLenPtr = recOffset; /* read the length of the option bytes */ READU16INC(recOffset,optLen); lengthParsed += sizeof(uint16_t); if (!optLen && !optScopeLen) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Options Template has No Length. " "(optScopeLen %u, optLen %u).", optScopeLen, optLen); return 0; } #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "Options Tmpl ID:%d; ScopeLen %d; Len %d\n", templateId, optScopeLen, optLen); /* debug */ #endif /* check the option scope length + option length to check to make sure that this record is sane - just make sure there is enough room*/ if (recLength < (optScopeLen + optLen + lengthParsed)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Record Length is too short for options fields " "(recLength %u optScopeLen %u optLen %u len parsed %d)", recLength, optScopeLen, optLen, lengthParsed); return 0; } /* Get past Option Scope Elements */ for (loop = 0; loop < optScopeLen; loop += 4) { /* replace option scope type with messageScope info element*/ WRITEU16(recOffset,263); recOffset+=sizeof(uint16_t); READU16INC(recOffset,fieldLen); fieldCount++; lengthParsed += 4; templateLength += fieldLen; } /* IPFIX requires a scope count (otherwise - why is it an options tmpl?) */ /* Cisco doesn't require a scope count - so make sure we have 1 */ if (!fieldCount) { WRITEU16(optLenPtr,1); } else { /* In the IPFIX Options Template, Scope Field Count is actually the 3rd item in the Options header */ WRITEU16(optLenPtr,fieldCount); } /* Get past Options Elements */ for (loop = 0; loop < optLen; loop += 4) { READU16INC(recOffset,type); READU16INC(recOffset,fieldLen); lengthParsed += 4; fieldCount++; templateLength += fieldLen; } /* In IPFIX, Field Count is the total number of fields (including Scope Fields. */ WRITEU16(optScopeLenPtr,fieldCount); newTemplate = g_slice_new(fbCollectorNetflowV9TemplateHash_t); if (NULL == newTemplate) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TMPL, "could not allocate NetFlow v9 template storage record"); return FALSE; } newTemplate->templateId = templateId; newTemplate->templateLength = templateLength; newTemplate->optionsTemplate = TRUE; newTemplate->addSysUpTime = FALSE; /* if there is no TemplateHash this is the first template we are receiving in the current domain. Create a Hash for the domain.*/ if (currentSession->templateHash == NULL) { currentSession->templateHash = g_hash_table_new_full(fooHash, fooEqual, NULL, templateHashDestroyHelper); if (NULL == currentSession->templateHash) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "failure to allocate hash table for NetFlow " "session"); return FALSE; } } /* put the template into the hash, check/replace the template that is there if this template number already exists */ bigTemplateId = (uintptr_t)templateId; hashResult = g_hash_table_lookup(currentSession->templateHash, (gconstpointer)bigTemplateId); if (NULL != hashResult) { g_hash_table_replace(currentSession->templateHash, (gpointer)bigTemplateId, newTemplate); } else { g_hash_table_insert(currentSession->templateHash, (gpointer)bigTemplateId, newTemplate); } #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "Options template inserted into hash: templateId %d," " templateSize: %d, Domain: %04x, SysUpTime %d, " "fieldCount: %u \n", templateId, templateLength, transState->observation_id, newTemplate->addSysUpTime, fieldCount); #endif templateLength = 0; /* reset to 0 after each tmpl */ tmplcount++; } /* return the number of templates added to keep track of record count */ return tmplcount; } /** * fbCollectorPostProcV9 * * converts a buffer that was read as a netflow V9 * into a buffer that "conforms" to IPFIX for the * rest of fixbuf to process it * * @param collector pointer to the collector state structure * @param dataBuf pointer to the netflow PDU * @param bufLen the size from UDP of the message * @param err glib error set when FALSE is returned with an * informative message * * @return TRUE on success FALSE on error */ static gboolean fbCollectorPostProcV9( fbCollector_t *collector, uint8_t *dataBuf, size_t *bufLen, GError **err) { uint16_t recordCount; uint16_t recordCounter = 0; int i; uint8_t *msgOsetPtr = dataBuf; uint16_t padding = 0; uint16_t *lengthCountPtr = NULL; uint16_t *recLengthPtr = NULL; uint32_t netflowSeqNum; uint32_t ipfixRecordCount = 0; struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; uint32_t timeStamp; uint32_t obsDomain; uint16_t version; uint32_t *seqNumPtr; uint8_t tmpls_parsed; uint16_t setId; uint16_t recordLength; fbCollectorNetflowV9Session_t *currentSession = NULL; #if FB_NETFLOW_DEBUG == 1 uint16_t flowSet = 0; uint16_t dLoop; /* debug */ /* debug */ { uint8_t *d_tPtr8 = (uint8_t *)dataBuf; uint16_t *d_tPtr = (uint16_t *)dataBuf; uint16_t d_setid = g_ntohs(*d_tPtr); d_tPtr++; uint16_t d_setLen = g_ntohs(*d_tPtr); fprintf(stderr, "\nversion: %d count: %d\n", d_setid, d_setLen ); for (dLoop=0; dLoop < *bufLen; dLoop++) { fprintf(stderr, "0x%02x ", (d_tPtr8)[dLoop]); if (0 == (dLoop+1)%4 && 0 != dLoop) fprintf(stderr, "\n"); } } #endif /* FB_NETFLOW_DEBUG */ /* the buffer header has been partially converted into IPFIX, mostly meaning that the extra uptime has been dropped; now the count has to be converted into length, and all the different records need to be updated appropriately */ READU16(msgOsetPtr, version); WRITEU16(msgOsetPtr, 0x0a); msgOsetPtr += sizeof(uint16_t); lengthCountPtr = (uint16_t *)msgOsetPtr; READU16INC(msgOsetPtr, recordCount); READU32INC(msgOsetPtr, timeStamp); seqNumPtr = (uint32_t *)msgOsetPtr; READU32INC(msgOsetPtr, netflowSeqNum); #if FB_NETFLOW_DEBUG fprintf(stderr, "Sequence number %u\n", netflowSeqNum); #endif /* read the observation domain */ READU32INC(msgOsetPtr, obsDomain); pthread_mutex_lock(&transState->ts_lock); transState->observation_id = obsDomain; if (transState->sessionptr != collector->udp_head->session) { /* lookup template Hash Table per Domain */ transState->session = g_hash_table_lookup(transState->domainHash, collector->udp_head->session); if (transState->session == NULL) { transState->session = g_slice_new0(fbCollectorNetflowV9Session_t); g_hash_table_insert(transState->domainHash, (gpointer)collector->udp_head->session, transState->session); } transState->sessionptr = collector->udp_head->session; } currentSession = transState->session; /* seq num logic */ if (currentSession->netflowSeqNum != netflowSeqNum) { int seq_diff = netflowSeqNum - currentSession->netflowSeqNum; #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "NetFlow V9 sequence number mismatch for domain 0x%04x, " "expecting 0x%04x received 0x%04x", obsDomain, currentSession->netflowSeqNum, netflowSeqNum); #endif if (currentSession->netflowSeqNum) { if (seq_diff > 0) { if (seq_diff > NF_MAX_SEQ_DIFF) { /* check for reboot */ if (transState->sysUpTime > NF_REBOOT_SECS) { /* probably not a reboot so account for missed */ currentSession->netflowMissed += seq_diff; } /* else - reboot? don't add to missed count */ } else { currentSession->netflowMissed += seq_diff; } currentSession->netflowSeqNum = netflowSeqNum; } else { /* out of order or reboot? */ if ((currentSession->netflowSeqNum - netflowSeqNum) > NF_OUT_OF_ORDER) { /* this may be a reboot - it's pretty out of seq. */ currentSession->netflowSeqNum = netflowSeqNum; } else { /* this is in accepted range for out of sequence */ /* account for not missing. don't reset sequence number */ /* But subtract one so when we add one below, it evens out */ if (currentSession->netflowMissed) { currentSession->netflowMissed -= 1; } currentSession->netflowSeqNum -= 1; } } } else { /* this is the first one we received in this session */ currentSession->netflowSeqNum = netflowSeqNum; } } /* iterate through the flowsets */ /* a flowset can contain more than 1 record */ /* recordLength is the TOTAL Length of the flowset - not each record */ while ( msgOsetPtr < (dataBuf + *bufLen) ) { /* read the set ID, and adjust the reserved ones from Netflow to IPFIX */ READU16INC(msgOsetPtr, setId); recLengthPtr = (uint16_t*)msgOsetPtr; READU16INC(msgOsetPtr, recordLength); #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "FlowSet %u; SetId %u; Length %u\n", ++flowSet, setId, recordLength); /* debug */ #endif if (recordLength < 4) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Invalid Netflow %s Record Length (%u < 4)", ((1 == setId) ? "Options" : "Data"), recordLength); pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /* Check to make sure we won't overrun buffer - Add 4 for set header */ if (recordLength > ((dataBuf + *bufLen + 4) - msgOsetPtr)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "Malformed NetFlow Record: %s Length (%d) is " "larger than remaining buffer length (%ld)", (1 == setId) ? "Options" : "Record", recordLength, ((dataBuf + *bufLen + 4) - msgOsetPtr)); pthread_mutex_unlock(&transState->ts_lock); return FALSE; } if (0 == setId) { /* TEMPLATE RECORD */ /* Template SET ID = 0 in netflow, 2 in IPFIX */ WRITEU16(msgOsetPtr-2*sizeof(uint16_t), 2); tmpls_parsed = netflowDataTemplateParse(collector, msgOsetPtr, recLengthPtr, dataBuf, bufLen, err); if (!tmpls_parsed) { pthread_mutex_unlock(&transState->ts_lock); return FALSE; } recordCounter += tmpls_parsed; /* adjust the message pointer to skip over the payload of the template record, read the size from the record because it may have been updated in the template parse call (take into account that the pointer is 4-bytes into the record already (type & length)) */ msgOsetPtr += (g_ntohs(*recLengthPtr) - (2 * sizeof(uint16_t))); } else if (1 == setId) { /* OPTIONS TEMPLATE */ /* Template SET ID = 3 for IPFIX */ WRITEU16(msgOsetPtr-2*sizeof(uint16_t),3); tmpls_parsed = netflowOptionsTemplateParse(collector, msgOsetPtr, recLengthPtr, err); if (!tmpls_parsed) { /* Needs to contain at least 1 */ pthread_mutex_unlock(&transState->ts_lock); return FALSE; } recordCounter += tmpls_parsed; /* adjust the message pointer to skip over the payload of the template record (take into account that the pointer is 4-bytes into the record already (type & length)) */ msgOsetPtr += recordLength - (2 * sizeof(uint16_t)); } else if (setId < 256) { /* data records must be 256 or higher */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow record type (%u) is not supported", setId); pthread_mutex_unlock(&transState->ts_lock); return FALSE; } else { /* DATA */ struct fbCollectorNetflowV9TemplateHash_st *derTemplate = NULL; uint16_t numberRecordsInSet = 0; uintptr_t bigSetId = (uintptr_t) setId; if (NULL == currentSession->templateHash) { /* return if this is the last FlowSet in the packet */ if ((dataBuf + *bufLen) <= (msgOsetPtr - 4 + recordLength)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "No Templates Present for this session." " %u Flows Lost.", recordCount-recordCounter); currentSession->netflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /* else, remove these bytes from the packet */ #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "remove data set with no template\n"); #endif g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "No Templates Present for this session."); msgOsetPtr -= 4; memmove(msgOsetPtr, (msgOsetPtr + recordLength), *bufLen - ((msgOsetPtr + recordLength) - dataBuf)); *bufLen -= recordLength; } else if ((derTemplate = g_hash_table_lookup(currentSession->templateHash, (gconstpointer)bigSetId)) == NULL) { if ((dataBuf + *bufLen) <= (msgOsetPtr - 4 + recordLength)) { /* return if this is the last FlowSet in the packet */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "No Template 0x%02x Present for this Session." " %u Flows Lost.", setId, (recordCount-recordCounter)); currentSession->netflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /* else, remove these bytes from the packet */ #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "remove data set with no template\n"); #endif g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "No Template 0x%02x Present for Session", setId); msgOsetPtr -= 4; memmove((msgOsetPtr), (msgOsetPtr + recordLength), *bufLen - ((msgOsetPtr + recordLength) - dataBuf)); *bufLen -= recordLength; } else { numberRecordsInSet = (recordLength - 4) / derTemplate->templateLength; /* 4 for set id and length */ padding = ((recordLength - 4) % derTemplate->templateLength); #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "number of data records in set %02x is %d (0x%x)\n", setId, numberRecordsInSet, numberRecordsInSet); #endif if (numberRecordsInSet == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow Data Record with 0 Records"); pthread_mutex_unlock(&transState->ts_lock); return FALSE; } recordCounter += numberRecordsInSet; ipfixRecordCount += numberRecordsInSet; /* now check if need to add sysuptime to the record */ if (derTemplate->addSysUpTime) { for (i = 0; i < numberRecordsInSet; i++) { msgOsetPtr += derTemplate->templateLength; if (FB_MSGLEN_MAX <= (*bufLen + sizeof(uint64_t))) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow V9 unable to convert " "information model " "time elements, no space"); pthread_mutex_unlock(&transState->ts_lock); return FALSE; } memmove((msgOsetPtr + sizeof(uint64_t)), msgOsetPtr, (*bufLen - (msgOsetPtr - dataBuf))); /* add sysUpTime to flow record */ memcpy(msgOsetPtr, &(transState->sysUpTime), sizeof(uint64_t)); msgOsetPtr += sizeof(uint64_t); *bufLen += sizeof(uint64_t); } msgOsetPtr += padding; *recLengthPtr = g_htons(recordLength + (numberRecordsInSet * sizeof(uint64_t))); } else { /* subtract 4 since we already incremented msgOsetPtr 4 for id & length */ msgOsetPtr += recordLength - 4; } } } } /* fixup the length value (from record count)*/ *lengthCountPtr = g_htons(msgOsetPtr - dataBuf); if ((msgOsetPtr - dataBuf) < *bufLen) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "NetFlow Record Length Mismatch: (buffer has " "%u, processed %u)", (unsigned int)(*bufLen), ntohs(*lengthCountPtr)); currentSession->netflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /* fixup the sequence number */ *seqNumPtr = g_htonl(currentSession->ipfixSeqNum); /* increment the ipfix record count with the number of relevent records we observed*/ currentSession->ipfixSeqNum += ipfixRecordCount; /* increment the sequence number for the netflow side */ currentSession->netflowSeqNum++; if (recordCount != recordCounter) { #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "NetFlow V9 Record Count Discrepancy. " "Reported: %d. Found: %d.", recordCount, recordCounter); #endif } #if FB_NETFLOW_DEBUG == 1 /* debug */ { uint8_t *d_tPtr8 = (uint8_t *)dataBuf; uint16_t *d_tPtr = (uint16_t *)dataBuf; uint16_t d_setid = g_ntohs(*d_tPtr); d_tPtr++; uint16_t d_setLen = g_ntohs(*d_tPtr); fprintf(stderr, "\nversion: %d count: %d\n", d_setid, d_setLen ); for (dLoop=0; dLoop < *bufLen; dLoop++) { fprintf(stderr, "0x%02x ", (d_tPtr8)[dLoop]); if (0 == (dLoop+1)%4 && 0 != dLoop) fprintf(stderr, "\n"); } } #endif pthread_mutex_unlock(&transState->ts_lock); return TRUE; } /** * fbCollectorTransCloseV9 * * frees the state included as part of the collector when the * Netflow V9 translator is enabled * * @param collector, pointer to the collector state structure * */ static void fbCollectorTransCloseV9( fbCollector_t *collector) { struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; /* this should destroy each entry in the template */ g_hash_table_destroy(transState->domainHash); transState->domainHash = NULL; pthread_mutex_destroy(&transState->ts_lock); if (NULL != collector->translatorState) { g_free(collector->translatorState); } collector->translatorState = NULL; return; } /** * fbCollectorTimeoutNetflowSession * * this timeouts sessions when we haven't seen messages for > 30 mins. * * @param collector pointer to collector state. * @param session pointer to session to timeout. * */ static void fbCollectorTimeOutSessionV9( fbCollector_t *collector, fbSession_t *session) { struct fbCollectorNetflowV9State_st *transState = (struct fbCollectorNetflowV9State_st *)collector->translatorState; fbCollectorNetflowV9Session_t *nfsession = NULL; if (transState == NULL) { return; } pthread_mutex_lock(&transState->ts_lock); nfsession = g_hash_table_lookup(transState->domainHash, session); if (nfsession == NULL) { /* don't need to free! */ pthread_mutex_unlock(&transState->ts_lock); return; } /* remove this session, free the state */ g_hash_table_remove(transState->domainHash, session); if (session == transState->sessionptr) { transState->sessionptr = NULL; transState->session = NULL; } pthread_mutex_unlock(&transState->ts_lock); } /** *fbCollectorSetNetflowV9Translator * * this sets the collector input translator * to convert NetFlowV9 into IPFIX for the * given collector * * @param collector pointer to the collector state * to perform Netflow V9 conversion on * @param err GError structure that holds the error * message if an error occurs * * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetNetflowV9Translator( fbCollector_t *collector, GError **err) { GHashTable *hashTable = NULL; struct fbCollectorNetflowV9State_st *nflowState = g_malloc(sizeof(struct fbCollectorNetflowV9State_st)); if (NULL == nflowState) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TRANSMISC, "failure to allocate Netflow V9 translator state"); return FALSE; } hashTable = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, domainHashDestroyHelper); if (NULL == hashTable) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NETFLOWV9, "failure to allocate sequence no. hash table for " "Netflow Session"); return FALSE; } #if FB_NETFLOW_DEBUG == 1 fprintf(stderr, "Hash table address is %p for collector %p\n", hashTable, collector); /* debug */ #endif nflowState->domainHash = hashTable; nflowState->observation_id = 0; nflowState->sessionptr = NULL; pthread_mutex_init(&nflowState->ts_lock, NULL); return fbCollectorSetTranslator(collector, fbCollectorPostProcV9, fbCollectorDecodeV9MsgVL, fbCollectorMessageHeaderV9, fbCollectorTransCloseV9, fbCollectorTimeOutSessionV9, nflowState, err); } /** * fbCollectorGetNetflowMissed * * This returns the number of potential missed export packets * If peer is set, we search for a match and return the number of missed * packets for that ip/obdomain pair. If peer is not set then we just * return the most recent UDP connection stats. If peer is set and we don't * have a match, we just return 0. * we can't return the number of missed flow records since Netflow v9 * increases sequence numbers by the number of export packets it has sent, * NOT the number of flow records (like IPFIX and netflow v5 does). * * @param collector * @param peer address of exporter to lookup * @param peerlen sizeof(peer) * @param obdomain observation domain of peer exporter * @return number of missed packets * */ uint32_t fbCollectorGetNetflowMissed( fbCollector_t *collector, struct sockaddr *peer, size_t peerlen, uint32_t obdomain) { struct fbCollectorNetflowV9State_st *ts = NULL; fbUDPConnSpec_t *udp = NULL; fbSession_t *session = NULL; fbCollectorNetflowV9Session_t *ts_session = NULL; uint32_t missed = 0; if (!collector) { return 0; } if (peer) { udp = collector->udp_head; while (udp) { /* loop through and find the match */ if (udp->obdomain == obdomain) { if (!memcmp(&(udp->peer), peer, (peerlen > udp->peerlen) ? udp->peerlen : peerlen)) { /* we have a match - set session */ session = udp->session; break; } } udp = udp->next; } } else { /* set to most recent */ session = collector->udp_head->session; } if (!session) { return 0; } ts = (struct fbCollectorNetflowV9State_st *)collector->translatorState; if (ts == NULL) { g_warning("NFv9 Translator not set on collector."); return 0; } pthread_mutex_lock(&ts->ts_lock); if (ts->sessionptr != session) { /* lookup template Hash Table per Domain */ ts_session = g_hash_table_lookup(ts->domainHash, session); } else { ts_session = ts->session; } if (ts_session) { missed = ts_session->netflowMissed; } pthread_mutex_unlock(&ts->ts_lock); return missed; } libfixbuf-1.7.1/src/fbsession.c000644 000770 000024 00000104756 12545036674 020765 0ustar00emilyecoffmessagebus000000 000000 /* ** fbsession.c ** IPFIX Transport Session state container ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #ident "$Id" struct fbSession_st { /** Information model. */ fbInfoModel_t *model; /** Current observation domain ID. */ uint32_t domain; /** * Internal template table. Maps template ID to internal template. */ GHashTable *int_ttab; /** * External template table for current observation domain. * Maps template ID to external template. */ GHashTable *ext_ttab; uint16_t *tmpl_pair_array; uint16_t num_tmpl_pairs; /* Initial callback function to allow an application to assign template pairs for transcoding purposes. */ fbNewTemplateCallback_fn new_template_callback; /* Callback added to allow application to add context to a particular template */ fbTemplateCtxCallback2_fn tmpl_ctx_callback; void *tmpl_app_ctx; /** * Mutex to guard the ext_ttab when using Spread. Spread listens for new * group memberships. On a new membership, the Spread transport will send * all external templates to the new member privately. During this * process, the external template table cannot be modified, hence the * write lock on ext_ttab. */ #if HAVE_SPREAD pthread_mutex_t ext_ttab_wlock; /** * Group External Template Table. * Maps group to the external template table */ GHashTable *grp_ttab; /** * Group Sequence Number Table * Maps group to sequence number (only looks at first group in list) */ GHashTable *grp_seqtab; /** * Current Group */ unsigned int group; /** * Need to keep track of all groups session knows about */ sp_groupname_t *all_groups; /** * Number of groups session knows about. */ int num_groups; #endif /** * Domain external template table. * Maps domain to external template table. */ GHashTable *dom_ttab; /** * Last/next sequence number in current observation domain. */ uint32_t sequence; /** * Domain last/next sequence number table. * Maps domain to sequence number. */ GHashTable *dom_seqtab; /** * Buffer instance to write template dynamics to. */ fBuf_t *tdyn_buf; /** * Flag to set when an internal template is added or removed. The flag is * unset when SetInternalTemplate is called. This ensures the internal * template set to the most up-to-date template */ int intTmplTableChanged; /** * Flag to set when an external template is added or removed. The flag is * unset when SetExportTemplate is called. This ensures the internal * template set to the most up-to-date template */ int extTmplTableChanged; /** * Pointer to collector that was created with session */ fbCollector_t *collector; /** * Error description for fbSessionExportTemplates() */ GError *tdyn_err; }; fbSession_t *fbSessionAlloc( fbInfoModel_t *model) { fbSession_t *session = NULL; /* Create a new session */ session = g_slice_new0(fbSession_t); memset( session, 0, sizeof( fbSession_t ) ); /* Store reference to information model */ session->model = model; /* Allocate internal template table */ session->int_ttab = g_hash_table_new(g_direct_hash, g_direct_equal); #if HAVE_SPREAD /* this lock is needed only if Spread is enabled */ pthread_mutex_init( &session->ext_ttab_wlock, 0 ); #endif /* Reset session externals (will allocate domain template tables, etc.) */ fbSessionResetExternal(session); session->tmpl_pair_array = NULL; session->num_tmpl_pairs = 0; session->new_template_callback = NULL; /* All done */ return session; } void fbSessionAddTemplateCallback( fbSession_t *session, fbNewTemplateCallback_fn callback) { session->new_template_callback = callback; } fbNewTemplateCallback_fn fbSessionTemplateCallback( fbSession_t *session) { return session->new_template_callback; } /** * This function is used by fbSessionAddTemplateCtxWrapper(). It * wraps an old-style fbTemplateCtxFree_fn into an * fbTemplateCtxFree2_fn. It works by having * fbSessionTemplateCallbackWrapper() set the template's app_ctx to the * old-style function, setting the free callback to this function, and * this function call's the free function stashed in the app_ctx. */ static void fbTemplateCtxFreeWrapper( void *tmpl_ctx, void *app_ctx) { fbTemplateCtxFree_fn free_fn = (fbTemplateCtxFree_fn)app_ctx; free_fn(tmpl_ctx); } /** * This function is used by fbSessionAddTemplateCtxCallback(). It * wraps an fbTemplateCtxCallback_fn into an * fbTemplateCtxCallback2_fn. It works by having * fbSessionAddTemplateCtxCallback() stash the old-style callback * function in the app_ctx pointer, setting the actual callback to * this function. This function then wraps and calls the old-style * callback. */ static void fbSessionTemplateCallbackWrapper( fbSession_t *session, uint16_t tid, fbTemplate_t *tmpl, void *app_ctx, void **tmpl_ctx, fbTemplateCtxFree2_fn *free_fn) { /* Place to stash the old-style free function */ fbTemplateCtxFree_fn wrapped_free_fn = NULL; /* Retrieve the old-style callback and call it. */ fbTemplateCtxCallback_fn wrapped_fn = (fbTemplateCtxCallback_fn)app_ctx; wrapped_fn(session, tid, tmpl, tmpl_ctx, &wrapped_free_fn); if (wrapped_free_fn == NULL) { /* If the user provided no free function, propagate that */ *free_fn = NULL; } else { /* If the user provided an old-style free function, stash it * in the template's app_ctx, and set the free_function to our * wrapper free function. */ *free_fn = fbTemplateCtxFreeWrapper; tmpl->app_ctx = (void *)wrapped_free_fn; } } void fbSessionAddTemplateCtxCallback2( fbSession_t *session, fbTemplateCtxCallback2_fn callback, void *app_ctx) { session->tmpl_ctx_callback = callback; session->tmpl_app_ctx = app_ctx; } void fbSessionAddTemplateCtxCallback( fbSession_t *session, fbTemplateCtxCallback_fn callback) { /* Set the callback to the fbTemplateCtxCallback_fn wrapper * callback, and set the old-style callback as its argument */ session->tmpl_ctx_callback = fbSessionTemplateCallbackWrapper; session->tmpl_app_ctx = (void *)callback; } fbTemplateCtxCallback2_fn fbSessionTemplateCtxCallback( fbSession_t *session) { return session->tmpl_ctx_callback; } void *fbSessionTemplateCtxCallbackAppCtx( fbSession_t *session) { return session->tmpl_app_ctx; } void fbSessionAddTemplatePair( fbSession_t *session, uint16_t ext_tid, uint16_t int_tid) { gboolean madeTable = FALSE; if (!session->tmpl_pair_array) { session->tmpl_pair_array = (uint16_t*)g_slice_alloc0( sizeof(uint16_t) * (UINT16_MAX + 1)); madeTable = TRUE; } if ((ext_tid == int_tid) || (int_tid == 0)) { session->tmpl_pair_array[ext_tid] = int_tid; session->num_tmpl_pairs++; return; } /* external and internal tids are different */ /* only add the template pair if the internal template exists */ if (fbSessionGetTemplate(session, TRUE, int_tid, NULL)) { session->tmpl_pair_array[ext_tid] = int_tid; session->num_tmpl_pairs++; } else { if (madeTable) { g_slice_free1(sizeof(uint16_t) * UINT16_MAX, session->tmpl_pair_array); session->tmpl_pair_array = NULL; } } } void fbSessionRemoveTemplatePair( fbSession_t *session, uint16_t ext_tid) { if (!session->tmpl_pair_array) { return; } if (session->tmpl_pair_array[ext_tid]) { session->num_tmpl_pairs--; if (!session->num_tmpl_pairs) { /* this was the last one, free the array */ g_slice_free1(sizeof(uint16_t) * UINT16_MAX, session->tmpl_pair_array); session->tmpl_pair_array = NULL; return; } } session->tmpl_pair_array[ext_tid] = 0; } uint16_t fbSessionLookupTemplatePair( fbSession_t *session, uint16_t ext_tid) { /* if there are no current pairs, just return ext_tid because that means * we should decode the entire external template */ if (!session->tmpl_pair_array) { return ext_tid; } return session->tmpl_pair_array[ext_tid]; } static void fbSessionFreeOneTemplate( void *vtid __attribute__((unused)), fbTemplate_t *tmpl, fbSession_t *session) { fBufRemoveTemplateTcplan(session->tdyn_buf, tmpl); fbTemplateRelease(tmpl); } static void fbSessionResetOneDomain( void *vdomain __attribute__((unused)), GHashTable *ttab, fbSession_t *session) { g_hash_table_foreach(ttab, (GHFunc)fbSessionFreeOneTemplate, session); } void fbSessionResetExternal( fbSession_t *session) { /* Clear out the old domain template table if we have one */ if (session->dom_ttab) { /* Release all the external templates (will free unless shared) */ g_hash_table_foreach(session->dom_ttab, (GHFunc)fbSessionResetOneDomain, session); /* Nuke the domain template table */ g_hash_table_destroy(session->dom_ttab); } /* Allocate domain template table */ session->dom_ttab = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_hash_table_destroy); /* Null out stale external template table */ #if HAVE_SPREAD pthread_mutex_lock( &session->ext_ttab_wlock ); session->ext_ttab = NULL; pthread_mutex_unlock( &session->ext_ttab_wlock ); #else session->ext_ttab = NULL; #endif /* Clear out the old sequence number table if we have one */ if (session->dom_seqtab) { g_hash_table_destroy(session->dom_seqtab); } /* Allocate domain sequence number table */ session->dom_seqtab = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); /* Zero sequence number and domain */ session->sequence = 0; session->domain = 0; #if HAVE_SPREAD if (session->grp_ttab) { g_hash_table_destroy(session->grp_ttab); } /*Allocate group template table */ session->grp_ttab = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_hash_table_destroy); if (session->grp_seqtab) { g_hash_table_destroy(session->grp_seqtab); } session->grp_seqtab = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); /** Group 0 just means if we never sent a template on a group - * we will multicast to every group we know about */ session->group = 0; #endif /* Set domain to 0 (initializes external template table) */ fbSessionSetDomain(session, 0); } void fbSessionFree( fbSession_t *session) { fbSessionResetExternal(session); g_hash_table_foreach(session->int_ttab, (GHFunc)fbSessionFreeOneTemplate, session); g_hash_table_destroy(session->int_ttab); g_hash_table_destroy(session->dom_ttab); if (session->dom_seqtab) { g_hash_table_destroy(session->dom_seqtab); } if (session->tmpl_pair_array) { g_slice_free1(sizeof(uint16_t) * UINT16_MAX, session->tmpl_pair_array); session->tmpl_pair_array = NULL; } #if HAVE_SPREAD if (session->grp_ttab) { g_hash_table_destroy(session->grp_ttab); } if (session->grp_seqtab) { g_hash_table_destroy(session->grp_seqtab); } #endif g_slice_free(fbSession_t, session); } void fbSessionSetDomain( fbSession_t *session, uint32_t domain) { /* Short-circuit identical domain if not initializing */ if (session->ext_ttab && (domain == session->domain)) return; /* Update external template table; create if necessary. */ #if HAVE_SPREAD pthread_mutex_lock( &session->ext_ttab_wlock ); #endif session->ext_ttab = g_hash_table_lookup( session->dom_ttab, GUINT_TO_POINTER(domain) ); if (!session->ext_ttab) { session->ext_ttab = g_hash_table_new(g_direct_hash, g_direct_equal); g_hash_table_insert(session->dom_ttab, GUINT_TO_POINTER(domain), session->ext_ttab); } #if HAVE_SPREAD pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif /* Stash current sequence number */ g_hash_table_insert(session->dom_seqtab, GUINT_TO_POINTER(session->domain), GUINT_TO_POINTER(session->sequence)); /* Get new sequence number */ session->sequence = GPOINTER_TO_UINT( g_hash_table_lookup(session->dom_seqtab,GUINT_TO_POINTER(domain))); /* Stash new domain */ session->domain = domain; } #if HAVE_SPREAD void fbSessionSetGroupParams( fbSession_t *session, sp_groupname_t *groups, int num_groups) { session->all_groups = groups; session->num_groups = num_groups; } unsigned int fbSessionGetGroupOffset( fbSession_t *session, char *group) { int loop; for (loop = 0; loop < session->num_groups; loop++){ if (strcmp(group, session->all_groups[loop].name) == 0) { return (loop + 1); } } return 0; } void fbSessionSetPrivateGroup( fbSession_t *session, char *group, char *privgroup) { int loop, group_offset = 0; char **g; GError **err = NULL; if (group == NULL || privgroup == NULL) { return; } for (loop = 0; loop < session->num_groups; loop++) { if (strncmp(group, session->all_groups[loop].name, strlen(session->all_groups[loop].name)) == 0) { group_offset = loop + 1; } } if (group_offset == 0){ g_warning("Private Group requesting membership from UNKNOWN group"); return; } if (fBufGetExporter(session->tdyn_buf) && session->group > 0) { if (!fBufEmit(session->tdyn_buf, err)) { g_warning("Could not emit buffer %s", (*err)->message); g_clear_error(err); } } /*Update external template table; create if necessary. */ pthread_mutex_lock(&session->ext_ttab_wlock); session->ext_ttab = g_hash_table_lookup(session->grp_ttab, GUINT_TO_POINTER(group_offset)); if (!session->ext_ttab) { session->ext_ttab = g_hash_table_new(g_direct_hash, g_direct_equal); g_hash_table_insert(session->grp_ttab, GUINT_TO_POINTER(group_offset), session->ext_ttab); } pthread_mutex_unlock(&session->ext_ttab_wlock); g_hash_table_insert(session->grp_seqtab, GUINT_TO_POINTER(session->group), GUINT_TO_POINTER(session->sequence)); /* Get new sequence number */ session->sequence = GPOINTER_TO_UINT( g_hash_table_lookup(session->grp_seqtab, GUINT_TO_POINTER(group_offset))); session->group = group_offset; g = &privgroup; if (fBufGetExporter(session->tdyn_buf)) { fBufSetExportGroups(session->tdyn_buf, g, 1, err); } fbSessionExportTemplates(session, err); } /** * fbSessionAddTemplatesMulticast * * */ gboolean fbSessionAddTemplatesMulticast( fbSession_t *session, char **groups, gboolean internal, uint16_t tid, fbTemplate_t *tmpl, GError **err) { int n = 0; unsigned int group_offset; GHashTable *ttab; uint16_t next_tid = 0; if (groups == NULL) { return FALSE; } if (fBufGetExporter(session->tdyn_buf) && session->group > 0) { /* we are now going to multicast tmpls so we need to emit records currently in the buffer */ if (!fBufEmit(session->tdyn_buf, err)) { return FALSE; } } if (tid == FB_TID_AUTO) { if (next_tid == 0) next_tid = FB_TID_MIN_DATA; while (fbSessionGetTemplate(session, internal, next_tid, NULL)) { next_tid++; if (next_tid == 0) next_tid = FB_TID_MIN_DATA; } tid = next_tid++; } /*Update external template table per group; create if necessary. */ while (groups[n]) { group_offset = fbSessionGetGroupOffset(session, groups[n]); if (group_offset == 0) { g_warning("Spread Group Not Recognized."); return FALSE; } pthread_mutex_lock(&session->ext_ttab_wlock); session->ext_ttab = g_hash_table_lookup(session->grp_ttab, GUINT_TO_POINTER(group_offset)); if (!session->ext_ttab) { session->ext_ttab = g_hash_table_new(g_direct_hash,g_direct_equal); g_hash_table_insert(session->grp_ttab, GUINT_TO_POINTER(group_offset), session->ext_ttab); } pthread_mutex_unlock(&session->ext_ttab_wlock); g_hash_table_insert(session->grp_seqtab, GUINT_TO_POINTER(session->group), GUINT_TO_POINTER(session->sequence)); /* Get new sequence number */ session->sequence = GPOINTER_TO_UINT( g_hash_table_lookup(session->grp_seqtab, GUINT_TO_POINTER(group_offset))); /* keep new group */ session->group = group_offset; /* Select a template table to add the template to */ ttab = internal ? session->int_ttab : session->ext_ttab; /* Revoke old template, ignoring missing template error. */ if (!fbSessionRemoveTemplate(session, internal, tid, err)) { if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) { g_clear_error(err); } else { return FALSE; } } /* Insert template into table */ #if HAVE_SPREAD if (!internal) pthread_mutex_lock( &session->ext_ttab_wlock ); #endif g_hash_table_insert(ttab, GUINT_TO_POINTER((unsigned int)tid), tmpl); #if HAVE_SPREAD if (!internal) pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif fbTemplateRetain(tmpl); if (internal) { /* we don't really multicast internal tmpls - we only have one internal tmpl table - so once is enough */ return TRUE; } n++; } /* Now set session to group 1 before we multicast */ group_offset = fbSessionGetGroupOffset(session, groups[0]); pthread_mutex_lock(&session->ext_ttab_wlock); session->ext_ttab = g_hash_table_lookup(session->grp_ttab, GUINT_TO_POINTER(group_offset)); pthread_mutex_unlock(&session->ext_ttab_wlock); g_hash_table_insert(session->grp_seqtab, GUINT_TO_POINTER(session->group), GUINT_TO_POINTER(session->sequence)); /* Get sequence number - since it's the first group in list */ session->sequence = GPOINTER_TO_UINT( g_hash_table_lookup(session->grp_seqtab, GUINT_TO_POINTER(group_offset))); /* keep new group */ session->group = group_offset; if (fBufGetExporter(session->tdyn_buf)) { if (!fBufAppendTemplate(session->tdyn_buf, tid, tmpl, FALSE, err)) return 0; fBufSetExportGroups(session->tdyn_buf, groups, n, err); } return TRUE; } /** * fbSessionSetGroup * * */ void fbSessionSetGroup( fbSession_t *session, char *group) { unsigned int group_offset; GError **err = NULL; if (group == NULL && session->ext_ttab) { /* ext_ttab should already be setup and we are multicasting so no need to setup any tables */ return; } group_offset = fbSessionGetGroupOffset(session, group); if (group_offset == 0) { g_warning("Spread Group Not Recognized."); return; } /* short-circut identical group if not initializing */ if (session->ext_ttab && (session->group == group_offset)) return; if (fBufGetExporter(session->tdyn_buf) && session->group > 0) { /* Group is changing - meaning tmpls changing - emit now */ if (!fBufEmit(session->tdyn_buf, err)) { g_warning("Could not emit buffer before setting group: %s", (*err)->message); g_clear_error(err); } } /*Update external template table; create if necessary. */ if (fBufGetExporter(session->tdyn_buf)) { /* Only need to do this for exporters */ /* Collector's templates aren't managed per group */ pthread_mutex_lock(&session->ext_ttab_wlock); session->ext_ttab = g_hash_table_lookup(session->grp_ttab, GUINT_TO_POINTER(group_offset)); if (!session->ext_ttab) { session->ext_ttab =g_hash_table_new(g_direct_hash, g_direct_equal); g_hash_table_insert(session->grp_ttab, GUINT_TO_POINTER(group_offset), session->ext_ttab); } pthread_mutex_unlock(&session->ext_ttab_wlock); } g_hash_table_insert(session->grp_seqtab, GUINT_TO_POINTER(session->group), GUINT_TO_POINTER(session->sequence)); /* Get new sequence number */ session->sequence = GPOINTER_TO_UINT( g_hash_table_lookup(session->grp_seqtab, GUINT_TO_POINTER(group_offset))); /* keep new group */ session->group = group_offset; } unsigned int fbSessionGetGroup( fbSession_t *session) { return session->group; } #endif uint32_t fbSessionGetDomain( fbSession_t *session) { return session->domain; } uint16_t fbSessionAddTemplate( fbSession_t *session, gboolean internal, uint16_t tid, fbTemplate_t *tmpl, GError **err) { GHashTable *ttab = NULL; static uint16_t next_ext_tid = 0; static uint16_t next_int_tid = UINT16_MAX; /* Select a template table to add the template to */ ttab = internal ? session->int_ttab : session->ext_ttab; /* prevent infinite loop when template tables are full */ if (g_hash_table_size(ttab) == (UINT16_MAX - FB_TID_MIN_DATA)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TMPL, "Template table is full, no IDs left"); return 0; } /* Automatically assign a new template ID */ if (tid == FB_TID_AUTO) { if (internal) { if (next_int_tid == (FB_TID_MIN_DATA - 1)) { next_int_tid = UINT16_MAX; } while (fbSessionGetTemplate(session, internal, next_int_tid, NULL)) { next_int_tid--; if (next_int_tid == (FB_TID_MIN_DATA - 1)) { next_int_tid = UINT16_MAX; } } tid = next_int_tid--; } else { if (next_ext_tid == 0) next_ext_tid = FB_TID_MIN_DATA; while (fbSessionGetTemplate(session, internal, next_ext_tid, NULL)) { next_ext_tid++; if (next_ext_tid == 0) next_ext_tid = FB_TID_MIN_DATA; } tid = next_ext_tid++; } } /* Revoke old template, ignoring missing template error. */ if (!fbSessionRemoveTemplate(session, internal, tid, err)) { if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) { g_clear_error(err); } else { return 0; } } /* Write template to dynamics buffer */ if (fBufGetExporter(session->tdyn_buf) && !internal) { if (!fBufAppendTemplate(session->tdyn_buf, tid, tmpl, FALSE, err)) return 0; } /* Insert template into table */ #if HAVE_SPREAD if (!internal) pthread_mutex_lock( &session->ext_ttab_wlock ); #endif g_hash_table_insert(ttab, GUINT_TO_POINTER((unsigned int)tid), tmpl); if (internal) { session->intTmplTableChanged = 1; } else { session->extTmplTableChanged = 1; } #if HAVE_SPREAD if (!internal) pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif fbTemplateRetain(tmpl); return tid; } gboolean fbSessionRemoveTemplate( fbSession_t *session, gboolean internal, uint16_t tid, GError **err) { GHashTable *ttab = NULL; fbTemplate_t *tmpl = NULL; gboolean ok = TRUE; /* Select a template table to remove the template from */ ttab = internal ? session->int_ttab : session->ext_ttab; /* Get the template to remove */ tmpl = fbSessionGetTemplate(session, internal, tid, err); if (!tmpl) return FALSE; /* Write template withdrawal to dynamics buffer */ if (fBufGetExporter(session->tdyn_buf) && !internal) { ok = fBufAppendTemplate(session->tdyn_buf, tid, tmpl, TRUE, err); } /* Remove template */ #if HAVE_SPREAD if (!internal) pthread_mutex_lock( &session->ext_ttab_wlock ); #endif g_hash_table_remove(ttab, GUINT_TO_POINTER((unsigned int)tid)); if (internal) { session->intTmplTableChanged = 1; } else { session->extTmplTableChanged = 1; } fbSessionRemoveTemplatePair(session, tid); fBufRemoveTemplateTcplan(session->tdyn_buf, tmpl); #if HAVE_SPREAD if (!internal) pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif fbTemplateRelease(tmpl); return ok; } fbTemplate_t *fbSessionGetTemplate( fbSession_t *session, gboolean internal, uint16_t tid, GError **err) { GHashTable *ttab; fbTemplate_t *tmpl; /* Select a template table to get the template from */ ttab = internal ? session->int_ttab : session->ext_ttab; #if HAVE_SPREAD if (!internal) pthread_mutex_lock( &session->ext_ttab_wlock ); #endif tmpl = g_hash_table_lookup(ttab, GUINT_TO_POINTER((unsigned int)tid)); #if HAVE_SPREAD if (!internal) pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif /* Check for missing template */ if (!tmpl) { if (internal) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TMPL, "Missing internal template %04hx", tid); } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TMPL, "Missing external template %08x:%04hx", session->domain, tid); } return NULL; } return tmpl; } gboolean fbSessionExportTemplate( fbSession_t *session, uint16_t tid, GError **err) { fbTemplate_t *tmpl = NULL; /* short-circuit on no template dynamics buffer */ if (!fBufGetExporter(session->tdyn_buf)) return TRUE; /* look up template */ if (!(tmpl = fbSessionGetTemplate(session, FALSE, tid, err))) return FALSE; /* export it */ return fBufAppendTemplate(session->tdyn_buf, tid, tmpl, FALSE, err); } static void fbSessionExportOneTemplate( void *vtid, fbTemplate_t *tmpl, fbSession_t *session) { uint16_t tid = (uint16_t)GPOINTER_TO_UINT(vtid); if (fBufGetExporter(session->tdyn_buf)) { if (session->tdyn_err) return; if (!fBufAppendTemplate(session->tdyn_buf, tid, tmpl, FALSE, &session->tdyn_err)) { if (!session->tdyn_err) { g_set_error(&session->tdyn_err, FB_ERROR_DOMAIN, FB_ERROR_IO, "Unspecified template export error"); } } } } gboolean fbSessionExportTemplates( fbSession_t *session, GError **err) { gboolean ret = TRUE; #if HAVE_SPREAD pthread_mutex_lock( &session->ext_ttab_wlock ); #endif g_clear_error(&(session->tdyn_err)); if (session->ext_ttab) { g_hash_table_foreach(session->ext_ttab, (GHFunc)fbSessionExportOneTemplate, session); if (session->tdyn_err) { g_propagate_error(err, session->tdyn_err); ret = FALSE; } } #if HAVE_SPREAD pthread_mutex_unlock( &session->ext_ttab_wlock ); #endif return ret; } static void fbSessionCloneOneTemplate( void *vtid, fbTemplate_t *tmpl, fbSession_t *session) { uint16_t tid = (uint16_t)GPOINTER_TO_UINT(vtid); GError *err = NULL; if (!fbSessionAddTemplate(session, TRUE, tid, tmpl, &err)) { g_warning("Session clone internal template copy failed: %s", err->message); } } fbSession_t *fbSessionClone( fbSession_t *base) { fbSession_t *session = NULL; /* Create a new session using the information model from the base */ session = fbSessionAlloc(base->model); /* Add each internal template from the base session to the new session */ g_hash_table_foreach(base->int_ttab, (GHFunc)fbSessionCloneOneTemplate, session); /* Need to copy over callbacks because in the UDP case we won't have access to the session until after we call fBufNext and by that time it's too late and we've already missed some templates */ session->new_template_callback = base->new_template_callback; session->tmpl_ctx_callback = base->tmpl_ctx_callback; session->tmpl_app_ctx = base->tmpl_app_ctx; /* copy collector reference */ session->collector = base->collector; /* Return the new session */ return session; } uint32_t fbSessionGetSequence( fbSession_t *session) { return session->sequence; } void fbSessionSetSequence( fbSession_t *session, uint32_t sequence) { session->sequence = sequence; } void fbSessionSetTemplateBuffer( fbSession_t *session, fBuf_t *fbuf) { session->tdyn_buf = fbuf; } fbInfoModel_t *fbSessionGetInfoModel( fbSession_t *session) { return session->model; } void fbSessionClearIntTmplTableFlag( fbSession_t *session) { session->intTmplTableChanged = 0; } void fbSessionClearExtTmplTableFlag( fbSession_t *session) { session->extTmplTableChanged = 0; } int fbSessionIntTmplTableFlagIsSet( fbSession_t *session) { return session->intTmplTableChanged; } int fbSessionExtTmplTableFlagIsSet( fbSession_t *session) { return session->extTmplTableChanged; } void fbSessionSetCollector( fbSession_t *session, fbCollector_t *collector) { session->collector = collector; } fbCollector_t *fbSessionGetCollector( fbSession_t *session) { return session->collector; } libfixbuf-1.7.1/src/fbsflow.c000644 000770 000024 00000163415 12545036674 020431 0ustar00emilyecoffmessagebus000000 000000 /** *@internal * * @file fbsflow.c * * This implements a SFlow convertor for translating into IPFIX * within the fixbuf structure * * ------------------------------------------------------------------------ * Copyright (C) 2008-2015 Carnegie Mellon University. All Rights Reserved. * ------------------------------------------------------------------------ * Authors: Emily Sarneso * ------------------------------------------------------------------------ * @OPENSOURCE_HEADER_START@ * Use of the libfixbuf system and related source code is subject to the terms * of the following licenses: * * GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 * Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 * * NO WARRANTY * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER * PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY * PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN * "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY * KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT * LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, * MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE * OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, * SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY * TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF * WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. * LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF * CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON * CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE * DELIVERABLES UNDER THIS LICENSE. * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie * Mellon University, its trustees, officers, employees, and agents from * all claims or demands made against them (and any related losses, * expenses, or attorney's fees) arising out of, or relating to Licensee's * and/or its sub licensees' negligent use or willful misuse of or * negligent conduct or willful misconduct regarding the Software, * facilities, or other rights or assistance granted by Carnegie Mellon * University under this License, including, but not limited to, any * claims of product liability, personal injury, death, damage to * property, or violation of any laws or regulations. * * Carnegie Mellon University Software Engineering Institute authored * documents are sponsored by the U.S. Department of Defense under * Contract FA8721-05-C-0003. Carnegie Mellon University retains * copyrights in all material produced under this contract. The U.S. * Government retains a non-exclusive, royalty-free license to publish or * reproduce these documents, or allow others to do so, for U.S. * Government purposes only pursuant to the copyright license under the * contract clause at 252.227.7013. * * @OPENSOURCE_HEADER_END@ * ------------------------------------------------------------------------ * * @Author: $Author$ * @Date: $Date$ * @Version: $Revision$ * */ #define _FIXBUF_SOURCE_ #include #include "fbcollector.h" #include #include #ident "$Id$" #ifndef FB_SFLOW_DEBUG # define FB_SFLOW_DEBUG 0 #endif #define SFLOW_TID 0xEEEE #define SFLOW_OPT_TID 0xEEEF #define SF_MAX_SEQ_DIFF 100 #define SF_OUT_OF_ORDER 10 #define SF_REBOOT_SECS 60 * 1000 /* 1 min in milliseconds */ #define FB_SFLOW_ETHER 1 #define FB_SFLOW_IPv4 0x0800 #define FB_SFLOW_IPv6 0x86DD #define FB_SFLOW_8021Q 0x8100 #define FB_SFLOW_MPLS 0x8847 #if HAVE_ALIGNED_ACCESS_REQUIRED #define fb_ntohll(x) (x) #define fb_htonll(x) fb_ntohll(x) /** * this set of macros for reading and writing U16's and U32's * uses memcpy's to avoid tripping over alignment issues on * platforms that cannot do unaligned access (e.g. SPARC, Alpha, * etc). The next section, after the else, does not use memcpy's * and operates just fine on architectures that don't crash * from an unaligned access (x86, PowerPC, etc.) */ /** * READU16INC * * read U16 and increment * * read a U16 value from ptr, it assumes the pointer * is properly aligned and pointing at the correct * place; and then increment ptr appropriately * according to its size to adjust for reading a * U16; increments it 2-bytes * * does network to host translation */ #define READU16INC(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ memcpy(&ru16_t16val, ru16_t16ptr, sizeof(uint16_t)); \ assignee = g_ntohs(ru16_t16val); \ ptr += sizeof(*ru16_t16ptr) / sizeof(*ptr); \ } #define READU16(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ memcpy(&ru16_t16val, ru16_t16ptr, sizeof(uint16_t)); \ assignee = g_ntohs(ru16_t16val); \ } #define WRITEU16(ptr,value) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = g_htons(value); \ memcpy(ru16_t16ptr, &ru16_t16val, sizeof(uint16_t)); \ } /** * READU32INC * * read U32 and increment ptr * * read a U32 from the ptr given in ptr, it assumes * it is aligned and positioned correctly, then * increment the ptr appropriately based on its * size and having read a U32 to increment it * 4-bytes ahead * * does network to host translation */ #define READU32INC(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ memcpy(&ru32_t32val, ru32_t32ptr, sizeof(uint32_t)); \ assignee = g_ntohl(ru32_t32val); \ ptr += sizeof(*ru32_t32ptr) / sizeof(*ptr); \ } #define READU32(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ memcpy(&ru32_t32val, ru32_t32ptr, sizeof(uint32_t)); \ assignee = g_ntohl(ru32_t32val); \ } #define WRITEU32(ptr,value) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = g_htonl(value); \ memcpy(ru32_t32ptr, &ru32_t32val, sizeof(uint32_t)); \ } #else #define fb_ntohll(x) \ ((((uint64_t)g_ntohl((uint32_t)((x) & 0xffffffff))) << 32) \ | g_ntohl((uint32_t)(((x) >> 32) & 0xffffffff))) #define fb_htonll(x) fb_ntohll(x) /** * READU16INC * * read U16 and increment * * read a U16 value from ptr, it assumes the pointer * is properly aligned and pointing at the correct * place; and then increment ptr appropriately * according to its size to adjust for reading a * U16; increments it 2-bytes * * does network to host translation */ #define READU16INC(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ ru16_t16val = g_ntohs(*ru16_t16ptr); \ assignee = ru16_t16val; \ ptr += sizeof(*ru16_t16ptr) / sizeof(*ptr); \ } #define READU16(ptr,assignee) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ uint16_t ru16_t16val = 0; \ ru16_t16val = g_ntohs(*ru16_t16ptr); \ assignee = ru16_t16val; \ } #define WRITEU16(ptr,value) { \ uint16_t *ru16_t16ptr = (uint16_t *)(ptr); \ *ru16_t16ptr = g_htons(value); \ } /** * READU32INC * * read U32 and increment ptr * * read a U32 from the ptr given in ptr, it assumes * it is aligned and positioned correctly, then * increment the ptr appropriately based on its * size and having read a U32 to increment it * 4-bytes ahead * * does network to host translation */ #define READU32INC(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ ru32_t32val = g_ntohl(*ru32_t32ptr); \ assignee = ru32_t32val; \ ptr += sizeof(*ru32_t32ptr) / sizeof(*ptr); \ } #define READU32(ptr,assignee) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ uint32_t ru32_t32val = 0; \ ru32_t32val = g_ntohl(*ru32_t32ptr); \ assignee = ru32_t32val; \ } #define WRITEU32(ptr,value) { \ uint32_t *ru32_t32ptr = (uint32_t *)(ptr); \ *ru32_t32ptr = g_htonl(value); \ } #endif static fbInfoElementSpec_t sflow_spec[] = { { "sourceIPv6Address", 0, 0 }, { "destinationIPv6Address", 0, 0 }, { "ipNextHopIPv6Address", 0, 0 }, { "bgpNextHopIPv6Address", 0, 0 }, { "collectorIPv6Address", 0, 0 }, { "collectionTimeMilliseconds", 0, 0 }, { "systemInitTimeMilliseconds", 0, 0 }, { "collectorIPv4Address", 0, 0 }, { "protocolIdentifier", 0, 0 }, { "ipClassOfService", 0, 0 }, { "sourceIPv4PrefixLength", 0, 0 }, { "destinationIPv4PrefixLength", 0, 0 }, { "sourceIPv4Address", 0, 0 }, { "destinationIPv4Address", 0, 0 }, { "octetTotalCount", 4, 0 }, { "packetTotalCount", 4, 0 }, { "ingressInterface", 0, 0 }, { "egressInterface", 0, 0 }, { "sourceMacAddress", 0, 0 }, { "destinationMacAddress", 0, 0 }, { "ipNextHopIPv4Address", 0, 0 }, { "bgpSourceAsNumber", 0, 0 }, { "bgpDestinationAsNumber", 0, 0 }, { "bgpNextHopIPv4Address", 0, 0 }, { "samplingPacketInterval", 0, 0 }, { "samplingPopulation", 0, 0 }, { "droppedPacketTotalCount", 4, 0 }, { "selectorId", 4, 0 }, { "vlanId", 0, 0 }, { "sourceTransportPort", 0, 0 }, { "destinationTransportPort", 0, 0 }, { "tcpControlBits", 2, 0 }, { "dot1qVlanId", 0, 0 }, { "postDot1qVlanId", 0, 0 }, { "dot1qPriority", 0, 0 }, FB_IESPEC_NULL }; typedef struct fbSFlowRecord_st{ /* IPv6 or raw packet data */ uint8_t sourceIPv6Address[16]; uint8_t destinationIPv6Address[16]; /* extended router data */ uint8_t nextHopIPv6Address[16]; /* extended gateway data */ uint8_t bgpNextHopIPv6Address[16]; /* flow header data */ uint8_t collectorIPv6Address[16]; uint64_t collectionTimeMilliseconds; uint64_t systemUpTime; uint32_t collectorIPv4Address; /* IPv4/6 data or raw packet data */ uint8_t protocolIdentifier; uint8_t ipClassOfService; /* format 1002 next hop src/dst mask */ uint8_t sourceIPv4PrefixLength; uint8_t destinationIPv4PrefixLength; /* IPv4 or raw packet data */ uint32_t sourceIPv4Address; uint32_t destinationIPv4Address; /* flow header data */ uint32_t octetTotalCount; uint32_t packetTotalCount; uint32_t ingressInterface; uint32_t egressInterface; /* ethernet frame data, ip, or raw packet data */ uint8_t sourceMacAddress[6]; uint8_t destinationMacAddress[6]; /* extended router data */ uint32_t nextHopIPv4Address; /* extended gateway data */ uint32_t bgpSourceAsNumber; uint32_t bgpDestinationAsNumber; uint32_t bgpNextHopIPv4Address; /* flow sample fields */ uint32_t samplingPacketInterval; uint32_t samplingPopulation; uint32_t droppedPacketTotalCount; uint32_t selectorId; /* IPv4/6 data or raw packet data */ uint16_t vlanId; uint16_t sourceTransportPort; uint16_t destinationTransportPort; uint16_t tcpControlBits; /* extended switch data */ uint16_t dot1qVlanId; uint16_t postDot1qVlanId; uint8_t dot1qPriority; } fbSFlowRecord_t; static fbInfoElementSpec_t sflow_ctr_spec[] = { { "collectorIPv6Address", 0, 0 }, { "collectionTimeMilliseconds", 0, 0 }, { "systemInitTimeMilliseconds", 0, 0 }, { "collectorIPv4Address", 0, 0 }, { "ingressInterface", 0, 0 }, { "octetTotalCount", 0, 0 }, { "ingressInterfaceType", 0, 0 }, { "packetTotalCount", 4, 0 }, { "ingressMulticastPacketTotalCount", 4, 0 }, { "ingressBroadcastPacketTotalCount", 4, 0 }, { "notSentPacketTotalCount", 4, 0 }, { "droppedPacketTotalCount", 4, 0 }, { "postOctetTotalCount", 0, 0 }, { "ignoredPacketTotalCount", 4, 0 }, { "postPacketTotalCount", 4, 0 }, { "egressBroadcastPacketTotalCount", 4, 0 }, { "selectorId", 4, 0 }, FB_IESPEC_NULL }; typedef struct fbSFlowCounterRecord_st { uint8_t ipv6[16]; uint64_t ctime; uint64_t sysuptime; uint32_t ipv4; uint32_t ingress; uint64_t inoct; uint32_t ingressType; uint32_t inpkt; uint32_t inmulti; uint32_t inbroad; uint32_t indiscard; uint32_t inerr; uint64_t outoct; uint32_t inunknown; uint32_t outpkt; uint32_t outbroad; uint32_t agentid; } fbSFlowCounterRecord_t; /** * IPv4 header structure, without options. */ typedef struct fbHdrIPv4_st{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN /** IP header length in 32-bit words. */ unsigned int ip_hl:4, /** IP version. Always 4 for IPv4 packets.*/ ip_v:4; #elif G_BYTE_ORDER == G_BIG_ENDIAN /** IP version. Always 4 for IPv4 packets.*/ unsigned int ip_v:4, /** IP header length in 32-bit words. */ ip_hl:4; #else #error Cannot determine byte order while defining IP header structure. #endif /** Type of Service */ uint8_t ip_tos; /** Total IP datagram length including header in bytes */ uint16_t ip_len; /** Fragment identifier */ uint16_t ip_id; /** Fragment offset and flags */ uint16_t ip_off; /** Time to live in routing hops */ uint8_t ip_ttl; /** Protocol identifier */ uint8_t ip_p; /** Header checksum */ uint16_t ip_sum; /** Source IPv4 address */ uint32_t ip_src; /** Destination IPv4 address */ uint32_t ip_dst; } fbHdrIPv4_t; /** * IPv6 header structure. */ typedef struct fbHdrIPv6_st { /** Version, traffic class, and flow ID. Use YF_VCF6_ macros to access. */ uint32_t ip6_vcf; /** * Payload length. Does NOT include IPv6 header (40 bytes), but does * include subsequent extension headers, upper layer headers, and payload. */ uint16_t ip6_plen; /** Next header identifier. Use YF_PROTO_ macros. */ uint8_t ip6_nxt; /** Hop limit */ uint8_t ip6_hlim; /** Source IPv6 address */ uint8_t ip6_src[16]; /** Destination IPv6 address */ uint8_t ip6_dst[16]; } fbHdrIPv6_t; typedef struct fbCollectorSFlowSession_st { /** potential sflow samples missed */ uint32_t sflowMissed; /** current sFlow seq num */ uint32_t sflowSeqNum; /** Flow Sample seq number */ uint32_t sflowFlowSeqNum; /** Counter Sample seq number */ uint32_t sflowCounterSeqNum; } fbCollectorSFlowSession_t; /** defines the extra state needed to convert from sFlow to IPFIX */ struct fbCollectorSFlowState_st { uint64_t ptime; uint32_t observation_id; uint32_t samples; fbCollectorSFlowSession_t *session; fbSession_t *exsession; fbSession_t *cosession; fbInfoModel_t *model; fBuf_t *fbuf; uint8_t *ipfixBuffer; GHashTable *domainHash; pthread_mutex_t ts_lock; }; static void sessionDestroyHelper( gpointer datum) { g_slice_free(fbCollectorSFlowSession_t, datum); } static gboolean sflowAppendRec( fbCollector_t *collector, fbSFlowRecord_t *sflowrec, GError **err) { struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; /* appending new record */ if (!fBufSetExportTemplate(transState->fbuf, SFLOW_TID, err)) { return FALSE; } if (!fBufAppend(transState->fbuf, (uint8_t*)sflowrec, sizeof(fbSFlowRecord_t), err)) { /* error appending */ return FALSE; } return TRUE; } static gboolean sflowAppendOptRec( fbCollector_t *collector, fbSFlowCounterRecord_t *sflowrec, GError **err) { struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; /* appending new record */ if (!fBufSetInternalTemplate(transState->fbuf, SFLOW_OPT_TID, err)) { return FALSE; } if (!fBufSetExportTemplate(transState->fbuf, SFLOW_OPT_TID, err)) { return FALSE; } if (!fBufAppend(transState->fbuf, (uint8_t*)sflowrec, sizeof(fbSFlowCounterRecord_t), err)) { /* error appending */ return FALSE; } if (!fBufSetInternalTemplate(transState->fbuf, SFLOW_TID, err)) { return FALSE; } return TRUE; } static fbExporter_t *sflowAllocExporter( uint8_t *dataBuf, fBuf_t *fbuf, GError **err) { fbExporter_t *exp = NULL; exp = fbExporterAllocBuffer(dataBuf, 65496); if (fbuf) { fBufSetExporter(fbuf, exp); if (!fBufSetInternalTemplate(fbuf, SFLOW_TID, err)) { return NULL; } if (!fBufSetExportTemplate(fbuf, SFLOW_TID, err)) { return NULL; } } return exp; } static gboolean sflowDecodeRawHeader( fbSFlowRecord_t *sflowrec, uint8_t *header, uint32_t headerlen, uint32_t protocol, GError **err) { uint16_t type = 0; size_t iph_len = 0; uint8_t *data = header; uint16_t datalen = headerlen; gboolean v6 = TRUE; #if FB_SFLOW_DEBUG fprintf(stderr, "PROTOCOL is %u\n", protocol); #endif switch (protocol) { case (FB_SFLOW_ETHER) : if (headerlen < 14) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Header too small for Ethernet L2 Header"); return FALSE; } memcpy(sflowrec->sourceMacAddress, data, 6); data += 6; memcpy(sflowrec->destinationMacAddress, data, 6); data += 6; READU16INC(data, type); datalen -= 14; break; case 11: /* IP v4 */ type = FB_SFLOW_IPv4; break; case 12: /* IP v6 */ type = FB_SFLOW_IPv6; break; case 13: /*MPLS*/ break; default: g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "No support for Header protocol %d", protocol); return FALSE; } #if FB_SFLOW_DEBUG fprintf(stderr, "TYPE is %d\n", type); #endif if (type == FB_SFLOW_8021Q) { if (datalen < 4) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Header too small for 802.1q Header"); return FALSE; } READU16INC(data, sflowrec->vlanId); sflowrec->vlanId = sflowrec->vlanId & 0x0FFF; #if FB_SFLOW_DEBUG fprintf(stderr, "vlan is %d\n", sflowrec->vlanId); #endif READU16INC(data, type); datalen -= 4; } if (type == FB_SFLOW_IPv4) { const fbHdrIPv4_t *iph = (const fbHdrIPv4_t *)data; if (datalen < 1) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Header too small for IPv4 Header"); return FALSE; } iph_len = iph->ip_hl * 4; if (datalen < iph_len) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Header too small for Full IPv4 Header"); return FALSE; } sflowrec->sourceIPv4Address = g_ntohl(iph->ip_src); sflowrec->destinationIPv4Address = g_ntohl(iph->ip_dst); sflowrec->ipClassOfService = iph->ip_tos; sflowrec->protocolIdentifier = iph->ip_p; #if FB_SFLOW_DEBUG fprintf(stderr, "IPv4 proto %d\n", sflowrec->protocolIdentifier); #endif datalen -= iph_len; data += iph_len; } else if (type == FB_SFLOW_IPv6) { const fbHdrIPv6_t *iph = (const fbHdrIPv6_t *)data; uint8_t hdr_next; size_t hdr_len = 40; if (datalen < hdr_len) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Header too small for IPv6 Header"); return FALSE; } memcpy(sflowrec->sourceIPv6Address, &(iph->ip6_src), 16); memcpy(sflowrec->destinationIPv6Address, &(iph->ip6_dst), 16); sflowrec->ipClassOfService = ((iph->ip6_vcf & 0x0FF00000) >> 20); hdr_next = iph->ip6_nxt; while (v6) { data += hdr_len; iph_len += hdr_len; datalen -= hdr_len; switch (hdr_next) { case 56: /* No Next Header */ return TRUE; case 44: /* Frag */ hdr_len = 8; if (datalen < 8) { return TRUE; } /* next header identifier */ hdr_next = *data; break; case 0: case 60: case 43: if (datalen < 2) { return TRUE; } hdr_next = *data; hdr_len = (*(data + 1) * 8) + 8; if (hdr_len > datalen) { return TRUE; } break; default: v6 = FALSE; sflowrec->protocolIdentifier = hdr_next; #if FB_SFLOW_DEBUG fprintf(stderr,"IPv6 proto %d\n", sflowrec->protocolIdentifier); #endif break; } } datalen -= iph_len; } else { /* not IP */ return TRUE; } /* Layer 4 */ if (sflowrec->protocolIdentifier == 6) { /* TCP */ if (datalen < 13) { return TRUE; } READU16INC(data, sflowrec->sourceTransportPort); READU16INC(data, sflowrec->destinationTransportPort); /* skip seq nos*/ data += 8; READU16INC(data, sflowrec->tcpControlBits); sflowrec->tcpControlBits = sflowrec->tcpControlBits & 0x0FFF; #if FB_SFLOW_DEBUG fprintf(stderr, "TCP sp %d, dp %d, flags %02x\n", sflowrec->sourceTransportPort, sflowrec->destinationTransportPort, sflowrec->tcpControlBits); #endif } else if (sflowrec->protocolIdentifier == 17) { /* UDP */ if (datalen < 8) { return TRUE; } READU16INC(data, sflowrec->sourceTransportPort); READU16INC(data, sflowrec->destinationTransportPort); #if FB_SFLOW_DEBUG fprintf(stderr,"UDP sp %d, dp %d\n", sflowrec->sourceTransportPort, sflowrec->destinationTransportPort); #endif } return TRUE; } /* * sflowDecodeFlowHeaders * * this decodes formats 2,3,4. * * */ static void sflowDecodeFlowHeaders( fbSFlowRecord_t *sflowrec, uint8_t *header, uint32_t headerlen, uint16_t format, GError **err) { uint8_t *data = header; uint32_t sp, dp, proto, flags, tos; if (format == 2) { /* Ethernet header */ READU32INC(data, sflowrec->octetTotalCount); memcpy(sflowrec->sourceMacAddress, data, 6); data += 8; memcpy(sflowrec->destinationMacAddress, data, 6); data += 8; } else if (format == 3) { /* IPv4 Data */ READU32INC(data, sflowrec->octetTotalCount); READU32INC(data, proto); READU32INC(data, sflowrec->sourceIPv4Address); READU32INC(data, sflowrec->destinationIPv4Address); READU32INC(data, sp); READU32INC(data, dp); READU32INC(data, flags); READU32INC(data, tos); sflowrec->protocolIdentifier = (uint16_t)proto; sflowrec->sourceTransportPort = (uint16_t)sp; sflowrec->destinationTransportPort = (uint16_t)dp; sflowrec->tcpControlBits = (uint16_t)flags; sflowrec->ipClassOfService = (uint16_t)tos; } else if (format == 4) { /* IPv6 Data */ READU32INC(data, sflowrec->octetTotalCount); READU32INC(data, proto); memcpy(sflowrec->sourceIPv6Address, data, 16); data += 16; memcpy(sflowrec->destinationIPv6Address, data, 16); data += 16; READU32INC(data, sp); READU32INC(data, dp); READU32INC(data, flags); READU32INC(data, tos); sflowrec->protocolIdentifier = (uint16_t)proto; sflowrec->sourceTransportPort =(uint16_t)sp; sflowrec->destinationTransportPort = (uint16_t)dp; sflowrec->tcpControlBits = (uint16_t)flags; sflowrec->ipClassOfService = (uint16_t)tos; } } /*################################################# * * SFlow functions for the collector, used * to optionally read * *#################################################*/ /** * fbCollectorDecodeSFlowMsgVL * * parses the header of a SFlow message and determines * how much needs to be read in order to complete * the message, (at least in theory) * * @param collector a pointer to the collector state * structure * @param hdr a pointer to the beginning of the buffer * to parse as a message (get converted back * into a uint8_t* and used as such) * @param b_len length of the buffer passed in for the * hdr * @param m_len length of the message header that still * needs to be read (always set to zero, since * this reads the entire message) * @param err a pointer to glib error structure, used * if an error occurs during processing the * stream * * * @return number of octets to read to complete * the message */ static gboolean fbCollectorDecodeSFlowMsgVL( fbCollector_t *collector, fbCollectorMsgVL_t *hdr, size_t b_len, uint16_t *m_len, GError **err) { *m_len = 0; return TRUE; } /** * fbCollectorMessageHeaderSFlow * * this converts a sFlow header into something every so slightly * closer to an IPFIX header; it dumps the up time with a big memcpy * * @param collector pointer to the collector state structure * @param buffer pointer to the message buffer * @param b_len length of the buffer passed in * @param m_len pointer to the length of the resultant buffer * @param err pointer to a GLib error structure * * @return TRUE on success, FALSE on error */ static gboolean fbCollectorMessageHeaderSFlow ( fbCollector_t *collector, uint8_t *buffer, size_t b_len, uint16_t *m_len, GError **err) { uint32_t tempRead32; uint32_t ip_version; struct timeval ct; struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; if (b_len < 28) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid sFlow Header. Buffer Length too short. " "Length: %d", (unsigned int)b_len); return FALSE; } /* first make sure the message seems like a sFlow message */ READU32(buffer, tempRead32); #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "version is %u\n", tempRead32); #endif /* FB_SFLOW_DEBUG */ /* only accept version 5 */ if (tempRead32 != 5) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "invalid version number for sFlow, expecting 5," " received %u", tempRead32); return FALSE; } READU32((buffer + 4), ip_version); if (ip_version != 1 && ip_version != 2) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid IP version number, expecting 1 or 2," " received %u", ip_version); return FALSE; } gettimeofday(&ct, NULL); transState->ptime = ((uint64_t)ct.tv_sec * 1000) + ((uint64_t)ct.tv_usec / 1000); collector->time = time(NULL); *m_len = b_len; return TRUE; } /** * sflowFlowSampleParse * * * @param collector pointer to the collector state record * @param dataBuf pointer to the buffer holding the template def * points after the set ID and set length * @param sflowrec pointer to new sflow rec * @param err GError pointer to store the error if one occurs * @param expanded TRUE if it's an expanded flow sample, FALSE if not * @return Number of Templates Parsed * */ static int sflowFlowSampleParse ( fbCollector_t *collector, uint8_t **data, size_t *datalen, fbSFlowRecord_t *sflowrec, gboolean expanded, GError **err) { uint32_t index, type; uint32_t numrecs; uint32_t flows = 0; uint32_t flowformat; uint32_t enterprise; uint32_t flowlength; uint32_t protocol, framelen; uint32_t var32; uint16_t format; uint8_t *dataBuf = *data; if (expanded) { /* header is 44 but we already read seq num */ if (*datalen < 40) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Expanded Flow Sample Header"); return 0; } } else { if (*datalen < 28) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Flow Sample Header"); return 0; } } if (expanded) { READU32INC(dataBuf, type); *datalen -= 4; } READU32INC(dataBuf, index); READU32INC(dataBuf, sflowrec->samplingPacketInterval); READU32INC(dataBuf, sflowrec->samplingPopulation); READU32INC(dataBuf, sflowrec->droppedPacketTotalCount); if (expanded) { *datalen -= 4; dataBuf += 4; } READU32INC(dataBuf, sflowrec->ingressInterface); if (expanded) { *datalen -= 4; dataBuf += 4; } READU32INC(dataBuf, sflowrec->egressInterface); /* number of flow records */ READU32INC(dataBuf, numrecs); #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "Internal %u, Egress %u, Expanded %d, numrecs %u, datalen %zu\n", sflowrec->ingressInterface, sflowrec->egressInterface, expanded, numrecs, *datalen); #endif *datalen -= 28; while (flows < numrecs) { if (*datalen < 4) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Flow Record Header."); return 0; } READU32INC(dataBuf, flowformat); enterprise = (flowformat & 0xFFFFF000) >> 12; format = (flowformat & 0xFFF); if (enterprise != 0) { #if FB_SFLOW_DEBUG fprintf(stderr, "INVALID flow: ent %u\n", enterprise); #endif g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid Flow Enterprise Number (%d)", enterprise); return 0; } READU32INC(dataBuf, flowlength); *datalen -= 8; #if FB_SFLOW_DEBUG fprintf(stderr, "Ent %u, Format %u, Length %u, datalen: %zu\n", enterprise, format, flowlength, *datalen); #endif if (*datalen < flowlength) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer (%zu) too small for Flow Record (%u)", *datalen, flowlength); return 0; } /* Sampled packets always = 1 */ sflowrec->packetTotalCount = 1; switch (format) { case 1: READU32(dataBuf, protocol); READU32(dataBuf + 4, framelen); /* after framelen is removed payload and length of header */ /* raw packet header */ if (!sflowDecodeRawHeader(sflowrec, dataBuf+16, flowlength-16, protocol, err)) { #if FB_SFLOW_DEBUG fprintf(stderr, "RAW HEADER DECODE Error: %s\n", (*err)->message); #endif g_clear_error(err); } sflowrec->octetTotalCount = framelen; break; case 2: case 3: case 4: sflowDecodeFlowHeaders(sflowrec, dataBuf, flowlength, format, err); break; case 1001: READU32(dataBuf, var32); sflowrec->dot1qVlanId = (uint16_t)var32; READU32(dataBuf+4, var32); sflowrec->dot1qPriority = (uint8_t)var32; READU32(dataBuf+8, var32); sflowrec->postDot1qVlanId = (uint16_t)var32; break; case 1002: /* read IP version 1=v4 2=v6 */ READU32(dataBuf, var32); if (var32 == 1) { READU32(dataBuf+4, sflowrec->nextHopIPv4Address); READU32(dataBuf+8, var32); sflowrec->sourceIPv4PrefixLength = (uint8_t)var32; READU32(dataBuf+12, var32); sflowrec->destinationIPv4PrefixLength = (uint8_t)var32; } else if (var32 == 2) { memcpy(sflowrec->nextHopIPv6Address, dataBuf+4, 16); READU32(dataBuf+20, var32); sflowrec->sourceIPv4PrefixLength = (uint8_t)var32; READU32(dataBuf+24, var32); sflowrec->destinationIPv4PrefixLength =(uint8_t)var32; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "malformed extended router data (format 1002). " "Invalid version %d", var32); return 0; } break; case 1003: READU32(dataBuf, var32); if (var32 == 1) { READU32(dataBuf+4, sflowrec->bgpNextHopIPv4Address); /* router AS */ READU32(dataBuf+12, sflowrec->bgpSourceAsNumber); /* Peer AS */ READU32(dataBuf+20, var32); if (var32) { /* get the first one */ READU32(dataBuf+32, sflowrec->bgpDestinationAsNumber); } } else if (var32 == 2) { memcpy(sflowrec->bgpNextHopIPv6Address, dataBuf+4, 16); /* router AS */ READU32(dataBuf+24, sflowrec->bgpSourceAsNumber); /* Peer AS */ READU32(dataBuf+32, var32); if (var32) { /* get the first one */ READU32(dataBuf+44, sflowrec->bgpDestinationAsNumber); } } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "malformed extended gateway data (format 1003). " "Invalid version %d", var32); return 0; } break; default: break; } dataBuf += flowlength; *datalen -= flowlength; flows++; } /* sflowAppendRec */ if (!sflowAppendRec(collector, sflowrec, err)) { return 0; } *data = dataBuf; return numrecs; } static int sflowCounterSampleParse ( fbCollector_t *collector, uint8_t **data, size_t *datalen, fbSFlowCounterRecord_t *sflowrec, gboolean expanded, GError **err) { uint32_t index, type; uint32_t numrecs; uint32_t recs = 0; uint32_t counterformat; uint32_t enterprise; uint32_t counterlength; uint16_t format; uint8_t *dataBuf = *data; gboolean append = FALSE; if (expanded) { /* header is 16 but we already read seq num */ if (*datalen < 12) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Expanded Counter Sample Header"); return 0; } READU32INC(dataBuf, type); *datalen -= 4; } else { if (*datalen < 8) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Counter Sample Header"); return 0; } } READU32INC(dataBuf, index); /* number of counter records */ READU32INC(dataBuf, numrecs); #if FB_SFLOW_DEBUG fprintf(stderr, "COUNTER SAMPLE!!!! (%u Records)\n", numrecs); #endif *datalen -= 8; while (recs < numrecs) { if (*datalen < 8) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Counter Record Header"); return 0; } READU32INC(dataBuf, counterformat); enterprise = (counterformat & 0xFFFFF000) >> 12; format = (counterformat & 0xFFF); if (enterprise != 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid Enterprise Number in Counter Record (%d)", enterprise); return 0; } *datalen -= 8; READU32INC(dataBuf, counterlength); if (*datalen < counterlength) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer (%zu) too small for Counter Data (%u)", *datalen, counterlength); return 0; } if (format == 1) { READU32(dataBuf, sflowrec->ingress); READU32(dataBuf+4, sflowrec->ingressType); memcpy(&sflowrec->inoct, dataBuf+24, 8); sflowrec->inoct = fb_ntohll(sflowrec->inoct); READU32(dataBuf+32, sflowrec->inpkt); READU32(dataBuf+36, sflowrec->inmulti); READU32(dataBuf+40, sflowrec->inbroad); READU32(dataBuf+44, sflowrec->indiscard); READU32(dataBuf+48, sflowrec->inerr); READU32(dataBuf+52, sflowrec->inunknown); memcpy(&sflowrec->outoct, dataBuf+56, 8); sflowrec->outoct = fb_ntohll(sflowrec->outoct); READU32(dataBuf+64, sflowrec->outpkt); READU32(dataBuf+72, sflowrec->outbroad); append = TRUE; } dataBuf += counterlength; *datalen -= counterlength; recs++; } /* sflowAppendRec */ if (append) { if (!sflowAppendOptRec(collector, sflowrec, err)) { return 0; } } *data = dataBuf; return numrecs; } /** * fbCollectorPostProcSFlow * * converts a buffer that was read as sflow * into a buffer that "conforms" to IPFIX for the * rest of fixbuf to process it * * @param collector pointer to the collector state structure * @param dataBuf pointer to the netflow PDU * @param bufLen the size from UDP of the message * @param err glib error set when FALSE is returned with an * informative message * * @return TRUE on success FALSE on error */ static gboolean fbCollectorPostProcSFlow( fbCollector_t *collector, uint8_t *dataBuf, size_t *bufLen, GError **err) { int flows = 0; int counters = 0; uint8_t *msgOsetPtr = dataBuf; fbExporter_t *sfexp = NULL; size_t msgParsed = *bufLen; uint32_t sflowSeqNum; uint32_t innerSeqNum; uint32_t numSamples; uint32_t sampleCount = 0; uint32_t sampleFormat; uint32_t enterprise; uint16_t format; struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; uint32_t timeStamp; uint32_t obsDomain; uint32_t version; uint32_t sampleLength; gboolean newbuffer = FALSE; fbCollectorSFlowSession_t *currentSession = NULL; fbSFlowRecord_t sflowrec; fbSFlowCounterRecord_t sflowctr; size_t msglen = 0; memset(&sflowrec, 0, sizeof(sflowrec)); memset(&sflowctr, 0, sizeof(sflowctr)); pthread_mutex_lock(&transState->ts_lock); memset(transState->ipfixBuffer, 0, 65535); if (!transState->fbuf) { transState->fbuf = fBufAllocForExport(transState->exsession, NULL); newbuffer = TRUE; } sfexp = sflowAllocExporter(transState->ipfixBuffer, transState->fbuf, err); if (!sfexp) { pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /* we already know this is version 5, so skip */ msgOsetPtr += 4; /* get ip version */ READU32INC(msgOsetPtr, version); if (version == 1) { /* ipv4 */ READU32INC(msgOsetPtr, sflowrec.collectorIPv4Address); msgParsed -= 12; } else { /* ipv6 */ memcpy(sflowrec.collectorIPv6Address, msgOsetPtr, 16); msgOsetPtr+=16; msgParsed -= 24; } READU32INC(msgOsetPtr, obsDomain); READU32INC(msgOsetPtr, sflowSeqNum); #if FB_SFLOW_DEBUG fprintf(stderr, "Sequence number %u\n", sflowSeqNum); #endif if (transState->cosession != collector->udp_head->session) { /* lookup template Hash Table per Domain */ transState->session = g_hash_table_lookup(transState->domainHash, collector->udp_head->session); if (transState->session == NULL) { transState->session = g_slice_new0(fbCollectorSFlowSession_t); g_hash_table_insert(transState->domainHash, (gpointer)collector->udp_head->session, transState->session); newbuffer = TRUE; } transState->cosession = collector->udp_head->session; } currentSession = transState->session; transState->observation_id = obsDomain; if (newbuffer) { if (!fbSessionExportTemplates(transState->exsession, err)) { pthread_mutex_unlock(&transState->ts_lock); return FALSE; } /*fBufSetAutomaticMode(transState->fbuf, FALSE);*/ fBufEmit(transState->fbuf, err); msglen = fbExporterGetMsgLen(sfexp); #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "EXPORTED TEMPLATES %u\n", msglen); #endif memcpy(dataBuf, transState->ipfixBuffer, msglen); *bufLen = msglen; pthread_mutex_unlock(&transState->ts_lock); return TRUE; } /* switch uptime in ms */ READU32INC(msgOsetPtr, timeStamp); /* seq num logic */ if (currentSession->sflowSeqNum != sflowSeqNum) { int seq_diff = sflowSeqNum - currentSession->sflowSeqNum; #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "sFlow sequence number mismatch for agent 0x%04x, " "expecting 0x%04x received 0x%04x", obsDomain, currentSession->sflowSeqNum, sflowSeqNum); #endif if (currentSession->sflowSeqNum) { if (seq_diff > 0) { if (seq_diff > SF_MAX_SEQ_DIFF) { /* check for reboot */ if (timeStamp > SF_REBOOT_SECS) { /* probably not a reboot so account for missed */ currentSession->sflowMissed += seq_diff; } /* else - reboot? don't add to missed count */ } else { currentSession->sflowMissed += seq_diff; } currentSession->sflowSeqNum = sflowSeqNum; } else { /* out of order or reboot? */ if ((currentSession->sflowSeqNum - sflowSeqNum) > SF_OUT_OF_ORDER) { /* this may be a reboot - it's pretty out of seq. */ currentSession->sflowSeqNum = sflowSeqNum; } else { /* this is in accepted range for out of sequence */ /* account for not missing. don't reset sequence number */ /* But subtract one so when we add one below, it evens out */ if (currentSession->sflowMissed) { currentSession->sflowMissed -= 1; } currentSession->sflowSeqNum -= 1; } } } else { /* this is the first one we received in this session */ currentSession->sflowSeqNum = sflowSeqNum; } } /* iterate through the samples */ READU32INC(msgOsetPtr, numSamples); msgParsed -= 16; while (sampleCount < numSamples ) { if (msgParsed < 8) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for Sample Header"); currentSession->sflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } READU32INC(msgOsetPtr, sampleFormat); /* top 20 bits are enterprise */ enterprise = (sampleFormat & 0xFFFFF000) >> 12; format = (sampleFormat & 0xFFF); READU32INC(msgOsetPtr, sampleLength); msgParsed -= 8; #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "Enterprise %u; Format %u; Length %u\n", enterprise, format, sampleLength); /* debug */ #endif if (enterprise != 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid sFlow enterprise number (%u)", enterprise); currentSession->sflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } if (msgParsed < sampleLength) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Buffer too small for sample length (%u)", sampleLength); currentSession->sflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } READU32INC(msgOsetPtr, innerSeqNum); msgParsed -= 4; #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "innerseqnum %u\n", innerSeqNum); #endif if (format == 1 || format == 3) { /* flow sample */ if (innerSeqNum != currentSession->sflowFlowSeqNum) { #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "sFlow Sample sequence number mismatch for agent 0x%04x, " "expecting 0x%04x received 0x%04x", obsDomain, currentSession->sflowFlowSeqNum, innerSeqNum); #endif currentSession->sflowFlowSeqNum = innerSeqNum; } } else { if (innerSeqNum != currentSession->sflowCounterSeqNum) { #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "sFlow Counter sequence number mismatch for agent 0x%04x, " "expecting 0x%04x received 0x%04x", obsDomain, currentSession->sflowCounterSeqNum, innerSeqNum); #endif currentSession->sflowCounterSeqNum = innerSeqNum; } } sflowrec.selectorId = obsDomain; sflowrec.systemUpTime = (uint64_t)timeStamp; sflowrec.collectionTimeMilliseconds = transState->ptime; switch (format) { case 1: /* Flow Sample */ flows = sflowFlowSampleParse(collector, &msgOsetPtr, &msgParsed, &sflowrec, FALSE, err); currentSession->sflowFlowSeqNum++; break; case 2: sflowctr.agentid = obsDomain; sflowctr.sysuptime = (uint64_t)timeStamp; sflowctr.ctime = transState->ptime; if (version == 1) { sflowctr.ipv4 = sflowrec.collectorIPv4Address; } else { memcpy(sflowctr.ipv6, sflowrec.collectorIPv6Address, 16); } counters = sflowCounterSampleParse(collector, &msgOsetPtr, &msgParsed, &sflowctr, FALSE, err); currentSession->sflowCounterSeqNum++; break; case 3: flows = sflowFlowSampleParse(collector, &msgOsetPtr, &msgParsed, &sflowrec, TRUE, err); currentSession->sflowFlowSeqNum++; break; case 4: sflowctr.agentid = obsDomain; sflowctr.sysuptime = (uint64_t)timeStamp; sflowctr.ctime = transState->ptime; if (version == 1) { sflowctr.ipv4 = sflowrec.collectorIPv4Address; } else { memcpy(sflowctr.ipv6, sflowrec.collectorIPv6Address, 16); } counters = sflowCounterSampleParse(collector, &msgOsetPtr, &msgParsed, &sflowctr, TRUE, err); currentSession->sflowCounterSeqNum++; break; default: g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Invalid sFlow Format (%d)", format); currentSession->sflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } if (!flows && !counters) { /* error ocurred */ currentSession->sflowSeqNum++; pthread_mutex_unlock(&transState->ts_lock); return FALSE; } sampleCount++; } /* there is possibly extra filling at the end of the packet */ /* warn and ignore! */ if (msgParsed) { #ifndef FB_SUPPRESS_LOGS g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "sFlow Record Length Mismatch: (buffer has " "%zu, leftover %zu)", *bufLen, msgParsed); #endif } /* increment the sequence number for the netflow side */ currentSession->sflowSeqNum++; fBufEmit(transState->fbuf, err); msglen = fbExporterGetMsgLen(sfexp); memcpy(dataBuf, transState->ipfixBuffer, msglen); *bufLen = msglen; fbExporterClose(sfexp); pthread_mutex_unlock(&transState->ts_lock); return TRUE; } /** * fbCollectorTransCloseSFlow * * frees the state included as part of the collector when the * SFlow translator is enabled * * @param collector, pointer to the collector state structure * */ static void fbCollectorTransCloseSFlow( fbCollector_t *collector) { struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; if (transState == NULL) { return; } if (transState->fbuf) { fBufFree(transState->fbuf); } if (transState->model) { fbInfoModelFree(transState->model); } g_slice_free1(65535, transState->ipfixBuffer); /* this should destroy each entry in the template */ g_hash_table_destroy(transState->domainHash); transState->domainHash = NULL; pthread_mutex_destroy(&transState->ts_lock); if (NULL != collector->translatorState) { g_slice_free1(sizeof(struct fbCollectorSFlowState_st), collector->translatorState); } collector->translatorState = NULL; return; } /** * fbCollectorTimeoutSessionSFlow * * this timeouts sessions when we haven't seen messages for > 30 mins. * * @param collector pointer to collector state. * @param session pointer to session to timeout. * */ static void fbCollectorTimeOutSessionSFlow( fbCollector_t *collector, fbSession_t *session) { struct fbCollectorSFlowState_st *transState = (struct fbCollectorSFlowState_st *)collector->translatorState; fbCollectorSFlowSession_t *sfsession = NULL; if (transState == NULL) { return; } pthread_mutex_lock(&transState->ts_lock); sfsession = g_hash_table_lookup(transState->domainHash, session); if (sfsession == NULL) { /* don't need to free! */ pthread_mutex_unlock(&transState->ts_lock); return; } /* remove this session, free the state */ g_hash_table_remove(transState->domainHash, session); if (session == transState->cosession) { transState->cosession = NULL; transState->session = NULL; } pthread_mutex_unlock(&transState->ts_lock); } /** *fbCollectorSetSFlowTranslator * * this sets the collector input translator * to convert SFlow into IPFIX for the * given collector * * @param collector pointer to the collector state * to perform SFlow conversion on * @param err GError structure that holds the error * message if an error occurs * * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetSFlowTranslator( fbCollector_t *collector, GError **err) { struct fbCollectorSFlowState_st *sflowState = g_slice_alloc0(sizeof(struct fbCollectorSFlowState_st)); GHashTable *hashTable = NULL; fbInfoModel_t *model = fbInfoModelAlloc(); fbTemplate_t *sftmpl = NULL; fbSession_t *sfsess = NULL; if (NULL == sflowState) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_TRANSMISC, "Failure to allocate sFlow translator state"); return FALSE; } hashTable = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, sessionDestroyHelper); if (NULL == hashTable) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_SFLOW, "Failed to allocate sequence number hash table " "for sFlow translator."); return FALSE; } sflowState->domainHash = hashTable; sftmpl = fbTemplateAlloc(model); if (!fbTemplateAppendSpecArray(sftmpl, sflow_spec, 0xffffffff, err)) { return FALSE; } sfsess = fbSessionAlloc(model); if (!fbSessionAddTemplate(sfsess, TRUE, SFLOW_TID, sftmpl, err)) { return FALSE; } if (!fbSessionAddTemplate(sfsess, FALSE, SFLOW_TID, sftmpl, err)) { return FALSE; } /* Options (counter) template */ sftmpl = fbTemplateAlloc(model); if (!fbTemplateAppendSpecArray(sftmpl, sflow_ctr_spec, 0xffffffff, err)) { return FALSE; } fbTemplateSetOptionsScope(sftmpl, 1); if (!fbSessionAddTemplate(sfsess, TRUE, SFLOW_OPT_TID, sftmpl, err)) { return FALSE; } if (!fbSessionAddTemplate(sfsess, FALSE, SFLOW_OPT_TID, sftmpl, err)) { return FALSE; } #if FB_SFLOW_DEBUG == 1 fprintf(stderr, "Hash table address is %p for collector %p\n", hashTable, collector); /* debug */ #endif sflowState->session = NULL; sflowState->observation_id = 0; sflowState->exsession = sfsess; sflowState->model = model; sflowState->ipfixBuffer = g_slice_alloc0(65535); pthread_mutex_init(&sflowState->ts_lock, NULL); return fbCollectorSetTranslator(collector, fbCollectorPostProcSFlow, fbCollectorDecodeSFlowMsgVL, fbCollectorMessageHeaderSFlow, fbCollectorTransCloseSFlow, fbCollectorTimeOutSessionSFlow, sflowState, err); } /** * fbCollectorGetSFlowMissed * * This returns the number of potential missed export packets * packets for the ip/obdomain (agentId) of the sFlow exporter. * If there is no match, we just return 0. * * @param collector * @param peer address of exporter to lookup * @param peerlen sizeof(peer) * @param obdomain agentId of peer exporter * @return number of missed packets * */ uint32_t fbCollectorGetSFlowMissed( fbCollector_t *collector, struct sockaddr *peer, size_t peerlen, uint32_t obdomain) { struct fbCollectorSFlowState_st *ts = NULL; fbUDPConnSpec_t *udp = NULL; fbSession_t *session = NULL; fbCollectorSFlowSession_t *sfsession = NULL; uint32_t missed = 0; if (!collector) { return 0; } if (peer) { udp = collector->udp_head; while (udp) { /* loop through and find the match */ if (udp->obdomain == obdomain) { if (!memcmp(&(udp->peer), peer, (peerlen > udp->peerlen) ? udp->peerlen : peerlen)) { /* we have a match - set session */ session = udp->session; break; } } udp = udp->next; } } else { /* set to most recent */ session = collector->udp_head->session; } if (!session) { return 0; } ts = (struct fbCollectorSFlowState_st *)collector->translatorState; if (ts == NULL) { g_warning("sFlow translator not set on collector."); return 0; } pthread_mutex_lock(&ts->ts_lock); if (ts->cosession != session) { /* lookup template Hash Table per Domain */ sfsession = g_hash_table_lookup(ts->domainHash, session); } else { sfsession = ts->session; } if (sfsession) { missed = sfsession->sflowMissed; } pthread_mutex_unlock(&ts->ts_lock); return missed; } libfixbuf-1.7.1/src/fbtemplate.c000644 000770 000024 00000025513 12545036674 021106 0ustar00emilyecoffmessagebus000000 000000 /* ** fbtemplate.c ** IPFIX Template implementation ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #ident "$Id$" void fbTemplateDebug( const char *label, uint16_t tid, fbTemplate_t *tmpl) { int i; fprintf(stderr, "%s template %04x [%p] iec=%u sc=%u len=%u\n", label, tid, tmpl, tmpl->ie_count, tmpl->scope_count, tmpl->ie_len); for (i = 0; i < tmpl->ie_count; i++) { fprintf(stderr,"\t%2u ", i); fbInfoElementDebug(TRUE, tmpl->ie_ary[i]); } } fbTemplate_t *fbTemplateAlloc( fbInfoModel_t *model) { fbTemplate_t *tmpl = NULL; /* create a new template */ tmpl = g_slice_new0(fbTemplate_t); /* fill it in */ tmpl->model = model; tmpl->tmpl_len = 4; tmpl->active = FALSE; /* allocate indices table */ tmpl->indices = g_hash_table_new((GHashFunc)fbInfoElementHash, (GEqualFunc)fbInfoElementEqual); return tmpl; } void fbTemplateRetain( fbTemplate_t *tmpl) { /* Increment reference count */ ++(tmpl->ref_count); } void fbTemplateRelease( fbTemplate_t *tmpl) { /* Decrement reference count */ --(tmpl->ref_count); /* Free if not referenced */ fbTemplateFreeUnused(tmpl); } void fbTemplateFreeUnused( fbTemplate_t *tmpl) { if (tmpl->ref_count <= 0) { fbTemplateFree(tmpl); } } void fbTemplateFree( fbTemplate_t *tmpl) { int i; if (tmpl->ctx_free) { tmpl->ctx_free(tmpl->tmpl_ctx, tmpl->app_ctx); } /* destroy index table if present */ if (tmpl->indices) g_hash_table_destroy(tmpl->indices); /* destroy IE array */ for (i = 0; i < tmpl->ie_count; i++) { g_slice_free(fbInfoElement_t, tmpl->ie_ary[i]); } g_free(tmpl->ie_ary); /* destroy offset cache if present */ if (tmpl->off_cache) g_free(tmpl->off_cache); /* destroy template */ g_slice_free(fbTemplate_t, tmpl); } static fbInfoElement_t *fbTemplateExtendElements( fbTemplate_t *tmpl) { if (tmpl->ie_count) { tmpl->ie_ary = g_renew(fbInfoElement_t*, tmpl->ie_ary, ++(tmpl->ie_count)); } else { tmpl->ie_ary = g_new(fbInfoElement_t*, 1); ++(tmpl->ie_count); } tmpl->ie_ary[tmpl->ie_count - 1] = g_slice_new0(fbInfoElement_t); return tmpl->ie_ary[tmpl->ie_count - 1]; } static void fbTemplateExtendIndices( fbTemplate_t *tmpl, fbInfoElement_t *tmpl_ie) { void *ign0, *ign1; /* search indices table for multiple IE index */ while (g_hash_table_lookup_extended(tmpl->indices, tmpl_ie, &ign0, &ign1)) { ++(tmpl_ie->midx); } /* increment template lengths */ tmpl->tmpl_len += tmpl_ie->ent ? 8 : 4; if (tmpl_ie->len == FB_IE_VARLEN) { tmpl->is_varlen = TRUE; tmpl->ie_len += 1; if (tmpl_ie->num == FB_IE_BASIC_LIST) { tmpl->ie_internal_len += sizeof(fbBasicList_t); } else if (tmpl_ie->num == FB_IE_SUBTEMPLATE_LIST) { tmpl->ie_internal_len += sizeof(fbSubTemplateList_t); } else if (tmpl_ie->num == FB_IE_SUBTEMPLATE_MULTILIST) { tmpl->ie_internal_len += sizeof(fbSubTemplateMultiList_t); } else { tmpl->ie_internal_len += sizeof(fbVarfield_t); } } else { tmpl->ie_len += tmpl_ie->len; tmpl->ie_internal_len += tmpl_ie->len; } /* Add index of this information element to the indices table */ g_hash_table_insert(tmpl->indices, tmpl_ie, GUINT_TO_POINTER(tmpl->ie_count - 1)); } gboolean fbTemplateAppend( fbTemplate_t *tmpl, fbInfoElement_t *ex_ie, GError **err) { fbInfoElement_t *tmpl_ie; /* grow information element array */ tmpl_ie = fbTemplateExtendElements(tmpl); /* copy information element out of the info model */ if (!fbInfoElementCopyToTemplate(tmpl->model, ex_ie, tmpl_ie)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NOELEMENT, "No such information element %08x:%04x", ex_ie->ent, ex_ie->num); return FALSE; } /* Handle index and counter updates */ fbTemplateExtendIndices(tmpl, tmpl_ie); /* All done */ return TRUE; } gboolean fbTemplateAppendSpec( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags, GError **err) { fbInfoElement_t *tmpl_ie; /* Short-circuit on app flags mismatch */ if (spec->flags && !((spec->flags & flags) == spec->flags)) { return TRUE; } /* grow information element array */ tmpl_ie = fbTemplateExtendElements(tmpl); /* copy information element out of the info model */ if (!fbInfoElementCopyToTemplateByName(tmpl->model, spec->name, spec->len_override, tmpl_ie)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_NOELEMENT, "No such information element %s", spec->name); return FALSE; } /* Handle index and counter updates */ fbTemplateExtendIndices(tmpl, tmpl_ie); /* All done */ return TRUE; } gboolean fbTemplateAppendSpecArray( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags, GError **err) { for (; spec->name; spec++) { if (!fbTemplateAppendSpec(tmpl, spec, flags, err)) { return FALSE; } } return TRUE; } void fbTemplateSetOptionsScope( fbTemplate_t *tmpl, uint16_t scope_count) { /* Cannot set options scope if we've already done so */ g_assert(!tmpl->scope_count); /* Cannot set scope count higher than IE count */ g_assert(tmpl->ie_count && tmpl->ie_count >= tmpl->scope_count); /* scope count of zero means make the last IE the end of scope */ tmpl->scope_count = scope_count ? scope_count : tmpl->ie_count; /* account for scope count in output */ tmpl->tmpl_len += 2; } gboolean fbTemplateContainsElement( fbTemplate_t *tmpl, const fbInfoElement_t *ex_ie) { int i; if ( ex_ie == NULL || tmpl == NULL ) { return FALSE; } for (i = 0; i < tmpl->ie_count; i++) { if (fbInfoElementEqual(ex_ie, tmpl->ie_ary[i])) return TRUE; } return FALSE; } gboolean fbTemplateContainsElementByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec) { return fbTemplateContainsElement( tmpl, fbInfoModelGetElementByName(tmpl->model, spec->name)); } gboolean fbTemplateContainsAllElementsByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec) { for (; spec->name; spec++) { if (!fbTemplateContainsElementByName(tmpl, spec)) return FALSE; } return TRUE; } gboolean fbTemplateContainsAllFlaggedElementsByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags) { for (; spec->name; spec++) { if (spec->flags && !((spec->flags & flags) == spec->flags)) { continue; } if (!fbTemplateContainsElementByName(tmpl, spec)) return FALSE; } return TRUE; } uint32_t fbTemplateCountElements( fbTemplate_t *tmpl) { return tmpl->ie_count; } fbInfoElement_t* fbTemplateGetIndexedIE( fbTemplate_t *tmpl, uint32_t IEindex) { if (IEindex < tmpl->ie_count) { return tmpl->ie_ary[IEindex]; } else { return NULL; } } uint32_t fbTemplateGetOptionsScope( fbTemplate_t *tmpl) { return tmpl->scope_count; } void *fbTemplateGetContext( fbTemplate_t *tmpl) { return tmpl->tmpl_ctx; } libfixbuf-1.7.1/src/fbuf.c000644 000770 000024 00000426322 12545036674 017710 0ustar00emilyecoffmessagebus000000 000000 /** *@internal * ** fbuf.c ** IPFIX Message buffer implementation ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell, Dan Ruef, Emily Ecoff ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #define _FIXBUF_SOURCE_ #include #ident "$Id$" #define FB_MTU_MIN 32 #define FB_TCPLAN_NULL -1 #define FB_MAX_TEMPLATE_LEVELS 10 /* Debugger switches. We'll want to stick these in autoinc at some point. */ #define FB_DEBUG_TC 0 #define FB_DEBUG_TMPL 0 #define FB_DEBUG_WR 0 #define FB_DEBUG_RD 0 #define FB_DEBUG_LWR 0 #define FB_DEBUG_LRD 0 typedef struct fbTranscodePlan_st { fbTemplate_t *s_tmpl; fbTemplate_t *d_tmpl; int32_t *si; } fbTranscodePlan_t; typedef struct fbDLL_st fbDLL_t; struct fbDLL_st { fbDLL_t *next; fbDLL_t *prev; }; typedef struct fbTCPlanEntry_st fbTCPlanEntry_t; struct fbTCPlanEntry_st { fbTCPlanEntry_t *next; fbTCPlanEntry_t *prev; fbTranscodePlan_t *tcplan; }; /** *detachHeadOfDLL * * takes the head off of the dynamic linked list * * @param head * @param tail * @param toRemove * * */ static void detachHeadOfDLL( fbDLL_t **head, fbDLL_t **tail, fbDLL_t **toRemove) { /* assign the out pointer to the head */ *toRemove = *head; /* move the head pointer to pointer to the next element*/ *head = (*head)->next; /* if the new head's not NULL, set its prev to NULL */ if (*head) { (*head)->prev = NULL; } else { /* if it's NULL, it means there are no more elements, if * there's a tail pointer, set it to NULL too */ if (tail) { *tail = NULL; } } } /** *attachHeadToDLL * * puts a new element to the head of the dynamic linked list * * @param head * @param tail * @param newEntry * */ static void attachHeadToDLL( fbDLL_t **head, fbDLL_t **tail, fbDLL_t *newEntry) { /* if this is NOT the first entry in the list */ if (*head) { /* typical linked list attachements */ newEntry->next = *head; newEntry->prev = NULL; (*head)->prev = newEntry; *head = newEntry; } else { /* the new entry is the only entry now, set head to it */ *head = newEntry; newEntry->prev = NULL; newEntry->next = NULL; /* if we're keeping track of tail, assign that too */ if (tail) { *tail = newEntry; } } } /** *moveThisEntryToHeadOfDLL * * moves an entry within the dynamically linked list to the head of the list * * @param head - the head of the dynamic linked list * @param tail - unused * @param thisEntry - list element to move to the head * */ static void moveThisEntryToHeadOfDLL( fbDLL_t **head, fbDLL_t **tail __attribute__((unused)), fbDLL_t *thisEntry) { if (thisEntry == *head) { return; } if (thisEntry->prev) { thisEntry->prev->next = thisEntry->next; } if (thisEntry->next) { thisEntry->next->prev = thisEntry->prev; } thisEntry->prev = NULL; thisEntry->next = *head; (*head)->prev = thisEntry; *head = thisEntry; } /** *detachThisEntryOfDLL * * removes an entry from the dynamically linked list * * @param head * @param tail * @param entry * */ static void detachThisEntryOfDLL( fbDLL_t **head, fbDLL_t **tail, fbDLL_t *entry) { /* entry already points to the entry to remove, so we're good * there */ /* if it's NOT the head of the list, patch up entry->prev */ if (entry->prev != NULL) { entry->prev->next = entry->next; } else { /* if it's the head, reassign the head */ *head = entry->next; } /* if it's NOT the tail of the list, patch up entry->next */ if (entry->next != NULL) { entry->next->prev = entry->prev; } else { /* it is the last entry in the list, if we're tracking the * tail, reassign */ if (tail) { *tail = entry->prev; } } /* finish detaching by setting the next and prev pointers to * null */ entry->prev = NULL; entry->next = NULL; } struct fBuf_st { /** Transport session. Contains template and sequence number state. */ fbSession_t *session; /** Exporter. Writes messages to a remote endpoint on flush. */ fbExporter_t *exporter; /** Collector. Reads messages from a remote endpoint on demand. */ fbCollector_t *collector; /** Cached transcoder plan */ fbTCPlanEntry_t *latestTcplan; /** Current internal template. */ fbTemplate_t *int_tmpl; /** Current external template. */ fbTemplate_t *ext_tmpl; /** Current internal template ID. */ uint16_t int_tid; /** Current external template ID. */ uint16_t ext_tid; /** Current special set ID. */ uint16_t spec_tid; /** Automatic insert flag - tid of options tmpl */ uint16_t auto_insert_tid; /** Automatic mode flag */ gboolean automatic; /** Export time in seconds since 0UTC 1 Jan 1970 */ uint32_t extime; /** Record counter. */ uint32_t rc; /** length of buffer passed from app */ size_t buflen; /** * Current position pointer. * Pointer to the next byte in the buffer to be written or read. */ uint8_t *cp; /** * Pointer to first byte in the buffer in the current message. * NULL if there is no current message. */ uint8_t *msgbase; /** * Message end position pointer. * Pointer to first byte in the buffer after the current message. */ uint8_t *mep; /** * Pointer to first byte in the buffer in the current message. * NULL if there is no current message. */ uint8_t *setbase; /** * Set end position pointer. * Valid only after a call to fBufNextSetHeader() (called by fBufNext()). */ uint8_t *sep; /** Message buffer. */ uint8_t buf[FB_MSGLEN_MAX+1]; }; int transcodeCount = 0; /*================================================================== * * Debugger Functions * *==================================================================*/ #define FB_REM_MSG(_fbuf_) (_fbuf_->mep - _fbuf_->cp) #define FB_REM_SET(_fbuf_) (_fbuf_->sep - _fbuf_->cp) #if FB_DEBUG_WR || FB_DEBUG_RD || FB_DEBUG_TC static uint32_t fBufDebugHexLine( GString *str, const char *lpfx, uint8_t *cp, uint32_t lineoff, uint32_t buflen) { uint32_t cwr = 0, twr = 0; /* stubbornly refuse to print nothing */ if (!buflen) return 0; /* print line header */ g_string_append_printf(str, "%s %04x:", lpfx, lineoff); /* print hex characters */ for (twr = 0; twr < 16; twr++) { if (buflen) { g_string_append_printf(str, " %02hhx", cp[twr]); cwr++; buflen--; } else { g_string_append(str, " "); } } /* print characters */ g_string_append_c(str, ' '); for (twr = 0; twr < cwr; twr++) { if (cp[twr] > 32 && cp[twr] < 128) { g_string_append_c(str, cp[twr]); } else { g_string_append_c(str, '.'); } } g_string_append_c(str, '\n'); return cwr; } static void fBufDebugHex( const char *lpfx, uint8_t *buf, uint32_t len) { GString *str = g_string_new(""); uint32_t cwr = 0, lineoff = 0; do { cwr = fBufDebugHexLine(str, lpfx, buf, lineoff, len); buf += cwr; len -= cwr; lineoff += cwr; } while (cwr == 16); fprintf(stderr,"%s", str->str); g_string_free(str, TRUE); } #endif #if FB_DEBUG_WR || FB_DEBUG_RD #if FB_DEBUG_TC static void fBufDebugTranscodePlan( fbTranscodePlan_t *tcplan) { int i; fprintf(stderr, "transcode plan %p -> %p\n", tcplan->s_tmpl, tcplan->d_tmpl); for (i = 0; i < tcplan->d_tmpl->ie_count; i++) { fprintf(stderr, "\td[%2u]=s[%2d]\n", i, tcplan->si[i]); } } static void fBufDebugTranscodeOffsets( fbTemplate_t *tmpl, uint16_t *offsets) { int i; fprintf(stderr, "offsets %p\n", tmpl); for (i = 0; i < tmpl->ie_count; i++) { fprintf(stderr, "\to[%2u]=%4x\n", i, offsets[i]); } } #endif static void fBufDebugBuffer( const char *label, fBuf_t *fbuf, size_t len, gboolean reverse) { uint8_t *xcp = fbuf->cp - len; uint8_t *rcp = reverse ? xcp : fbuf->cp; fprintf(stderr, "%s len %5lu mp %5u (0x%04x) sp %5u mr %5u sr %5u\n", label, len, rcp - fbuf->msgbase, rcp - fbuf->msgbase, fbuf->setbase ? (rcp - fbuf->setbase) : 0, fbuf->mep - fbuf->cp, fbuf->sep ? (fbuf->sep - fbuf->cp) : 0); fBufDebugHex(label, rcp, len); } #endif /*================================================================== * * Transcoder Functions * *==================================================================*/ #define FB_TC_SBC_OFF(_need_) \ if (s_rem < (_need_)) { \ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, \ "End of message. " \ "Underrun on transcode offset calculation " \ "(need %lu bytes, %lu available)", \ (unsigned long)(_need_), (unsigned long)s_rem); \ goto err; \ } #define FB_TC_DBC_DEST(_need_, _op_, _dest_) \ if (*d_rem < (_need_)) { \ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, \ "End of message. " \ "Overrun on %s (need %lu bytes, %lu available)", \ (_op_), (unsigned long)(_need_), (unsigned long)*d_rem);\ _dest_; \ } #define FB_TC_DBC(_need_, _op_) \ FB_TC_DBC_DEST((_need_), (_op_), return FALSE) #define FB_TC_DBC_ERR(_need_, _op_) \ FB_TC_DBC_DEST((_need_), (_op_), goto err) /** * fbTranscodePlan * * @param fbuf * @param s_tmpl * @param d_tmpl * */ static fbTranscodePlan_t *fbTranscodePlan( fBuf_t *fbuf, fbTemplate_t *s_tmpl, fbTemplate_t *d_tmpl) { void *sik, *siv; uint32_t i; fbTCPlanEntry_t *entry; fbTranscodePlan_t *tcplan; /* check to see if plan is cached */ if (fbuf->latestTcplan) { entry = fbuf->latestTcplan; while (entry) { tcplan = entry->tcplan; if (tcplan->s_tmpl == s_tmpl && tcplan->d_tmpl == d_tmpl) { moveThisEntryToHeadOfDLL((fbDLL_t**)(void*)&(fbuf->latestTcplan), NULL, (fbDLL_t*)entry); return tcplan; } entry = entry->next; } } entry = g_slice_new0(fbTCPlanEntry_t); /* create new transcode plan and cache it */ entry->tcplan = g_slice_new0(fbTranscodePlan_t); tcplan = entry->tcplan; /* fill in template refs */ tcplan->s_tmpl = s_tmpl; tcplan->d_tmpl = d_tmpl; tcplan->si = g_new0(int32_t, d_tmpl->ie_count); /* for each destination element */ for (i = 0; i < d_tmpl->ie_count; i++) { /* find source index */ if (g_hash_table_lookup_extended(s_tmpl->indices, d_tmpl->ie_ary[i], &sik, &siv)) { tcplan->si[i] = GPOINTER_TO_INT(siv); } else { tcplan->si[i] = FB_TCPLAN_NULL; } } attachHeadToDLL((fbDLL_t**)(void*)&(fbuf->latestTcplan), NULL, (fbDLL_t*)entry); return tcplan; } /** * fbTranscodeFreeVarlenOffsets * * @param s_tmpl * @param offsets * */ static void fbTranscodeFreeVarlenOffsets( fbTemplate_t *s_tmpl, uint16_t *offsets) { if (s_tmpl->is_varlen) g_free(offsets); } /** * * Macros for decode reading */ #if HAVE_ALIGNED_ACCESS_REQUIRED #define FB_READ_U16(_val_, _ptr_) { \ uint16_t _x; \ memcpy(&_x, _ptr_, sizeof(uint16_t)); \ _val_ = g_ntohs(_x); \ } #define FB_READ_U32(_val_, _ptr_) { \ uint32_t _x; \ memcpy(&_x, _ptr_, sizeof(uint32_t)); \ _val_ = g_ntohl(_x); \ } #define FB_WRITE_U16(_ptr_, _val_) { \ uint16_t _x = g_htons(_val_); \ memcpy(_ptr_, &_x, sizeof(uint16_t)); \ } #define FB_WRITE_U32(_ptr_, _val_) { \ uint32_t _x = g_htonl(_val_); \ memcpy(_ptr_, &_x, sizeof(uint32_t)); \ } #else #define FB_READ_U16(_val_, _ptr_) { \ _val_ = g_ntohs(*((uint16_t *)_ptr_)); \ } #define FB_READ_U32(_val_, _ptr_) { \ _val_ = g_ntohl(*((uint32_t *)_ptr_)); \ } #define FB_WRITE_U16(_ptr_, _val_) \ *(uint16_t *)(_ptr_) = g_htons(_val_) #define FB_WRITE_U32(_ptr_, _val_) \ *(uint32_t *)(_ptr_) = g_htonl(_val_) #endif #define FB_READ_U8(_val_, _ptr_) \ _val_ = *(_ptr_) #define FB_WRITE_U8(_ptr_, _val_) \ (*(_ptr_)) = _val_ #define FB_READINC_U8(_val_, _ptr_) { \ FB_READ_U8(_val_, _ptr_); \ ++(_ptr_); \ } #define FB_READINC_U16(_val_, _ptr_) { \ FB_READ_U16(_val_, _ptr_); \ (_ptr_) += sizeof(uint16_t); \ } #define FB_READINC_U32(_val_, _ptr_) { \ FB_READ_U32(_val_, _ptr_); \ (_ptr_) += sizeof(uint32_t); \ } #define FB_WRITEINC_U8(_ptr_, _val_) { \ FB_WRITE_U8(_ptr_, _val_); \ ++(_ptr_); \ } #define FB_WRITEINC_U16(_ptr_, _val_) { \ FB_WRITE_U16(_ptr_, _val_); \ (_ptr_) += sizeof(uint16_t); \ } #define FB_WRITEINC_U32(_ptr_, _val_) { \ FB_WRITE_U32(_ptr_, _val_); \ (_ptr_) += sizeof(uint32_t); \ } #define FB_READINCREM_U8(_val_, _ptr_, _rem_) { \ FB_READINC_U8(_val_, _ptr_); \ --(_rem_); \ } #define FB_READINCREM_U16(_val_, _ptr_, _rem_) { \ FB_READINC_U16(_val_, _ptr_); \ (_rem_) -= sizeof(uint16_t); \ } #define FB_READINCREM_U32(_val_, _ptr_, _rem_) { \ FB_READINC_U32(_val_, _ptr_); \ (_rem_) -= sizeof(uint32_t); \ } #define FB_WRITEINCREM_U8(_ptr_, _val_, _rem_) { \ FB_WRITEINC_U8(_ptr_, _val_); \ --(_rem_); \ } #define FB_WRITEINCREM_U16(_ptr_, _val_, _rem_) { \ FB_WRITEINC_U16(_ptr_, _val_); \ (_rem_) -= sizeof(uint16_t); \ } #define FB_WRITEINCREM_U32(_ptr_, _val_, _rem_) { \ FB_WRITEINC_U32(_ptr_, _val_); \ (_rem_) -= sizeof(uint32_t); \ } #define FB_READ_LIST_LENGTH(_len_, _ptr_) { \ FB_READINC_U8(_len_, _ptr_); \ if ((_len_) == 255) { \ FB_READINC_U16(_len_, _ptr_); \ } \ } #define FB_READ_LIST_LENGTH_REM(_len_, _ptr_, _rem_) { \ FB_READINCREM_U8(_len_, _ptr_, _rem_); \ if ((_len_) == 255) { \ FB_READINCREM_U16(_len_, _ptr_, _rem_); \ } \ } /** * fbTranscodeOffsets * * @param s_tmpl * @param s_base * @param s_rem * @param decode * @param offsets_out * @param err - glib2 GError structure that returns the message on failure * * @return * */ static ssize_t fbTranscodeOffsets( fbTemplate_t *s_tmpl, uint8_t *s_base, uint32_t s_rem, gboolean decode, uint16_t **offsets_out, GError **err) { fbInfoElement_t *s_ie; uint8_t *sp; uint16_t *offsets; uint32_t s_len, i; /* short circuit - return offset cache if present in template */ if (s_tmpl->off_cache) { if (offsets_out) *offsets_out = s_tmpl->off_cache; return s_tmpl->off_cache[s_tmpl->ie_count]; } /* create new offsets array */ offsets = g_new0(uint16_t, s_tmpl->ie_count + 1); /* populate it */ for (i = 0, sp = s_base; i < s_tmpl->ie_count; i++) { offsets[i] = sp - s_base; s_ie = s_tmpl->ie_ary[i]; if (s_ie->len == FB_IE_VARLEN) { if (decode) { FB_TC_SBC_OFF((*sp == 255) ? 3 : 1); FB_READ_LIST_LENGTH_REM(s_len, sp, s_rem); FB_TC_SBC_OFF(s_len); sp += s_len; s_rem -= s_len; } else { if (s_ie->num == FB_IE_BASIC_LIST) { FB_TC_SBC_OFF(sizeof(fbBasicList_t)); sp += sizeof(fbBasicList_t); s_rem -= sizeof(fbBasicList_t); } else if (s_ie->num == FB_IE_SUBTEMPLATE_LIST) { FB_TC_SBC_OFF(sizeof(fbSubTemplateList_t)); sp += sizeof(fbSubTemplateList_t); s_rem -= sizeof(fbSubTemplateList_t); } else if (s_ie->num == FB_IE_SUBTEMPLATE_MULTILIST) { FB_TC_SBC_OFF(sizeof(fbSubTemplateMultiList_t)); sp += sizeof(fbSubTemplateMultiList_t); s_rem -= sizeof(fbSubTemplateMultiList_t); } else { FB_TC_SBC_OFF(sizeof(fbVarfield_t)); sp += sizeof(fbVarfield_t); s_rem -= sizeof(fbVarfield_t); } } } else { FB_TC_SBC_OFF(s_ie->len); sp += s_ie->len; s_rem -= s_ie->len; } } /* get EOR offset */ s_len = offsets[i] = sp - s_base; /* cache offsets if possible */ if (!s_tmpl->is_varlen && offsets_out) { s_tmpl->off_cache = offsets; } /* return offsets if possible */ if (offsets_out) { *offsets_out = offsets; } else { *offsets_out = NULL; fbTranscodeFreeVarlenOffsets(s_tmpl, offsets); } /* return EOR offset */ return s_len; err: g_free(offsets); return -1; } /** * fbTranscodeZero * * * * * */ static gboolean fbTranscodeZero( uint8_t **dp, uint32_t *d_rem, uint32_t len, GError **err) { /* Check for write overrun */ FB_TC_DBC(len, "zero transcode"); /* fill zeroes */ memset(*dp, 0, len); /* maintain counters */ *dp += len; *d_rem -= len; return TRUE; } #if G_BYTE_ORDER == G_BIG_ENDIAN /** * fbTranscodeFixedBigEndian * * * * * */ static gboolean fbTranscodeFixedBigEndian( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t s_len, uint32_t d_len, uint32_t flags, GError **err) { FB_TC_DBC(d_len, "fixed transcode"); if (s_len == d_len) { memcpy(*dp, sp, d_len); } else if (s_len > d_len) { if (flags & FB_IE_F_ENDIAN) { memcpy(*dp, sp + (s_len - d_len), d_len); } else { memcpy(*dp, sp, d_len); } } else { memset(*dp, 0, d_len); if (flags & FB_IE_F_ENDIAN) { memcpy(*dp + (d_len - s_len), sp, s_len); } else { memcpy(*dp, sp, s_len); } } /* maintain counters */ *dp += d_len; *d_rem -= d_len; return TRUE; } #define fbEncodeFixed fbTranscodeFixedBigEndian #define fbDecodeFixed fbTranscodeFixedBigEndian #else /** * fbTranscodeSwap * * * * * */ static void fbTranscodeSwap( uint8_t *a, uint32_t len) { uint32_t i; uint8_t t; for (i = 0; i < len/2; i++) { t = a[i]; a[i] = a[(len-1)-i]; a[(len-1)-i] = t; } } /** * fbEncodeFixedLittleEndian * * * * * */ static gboolean fbEncodeFixedLittleEndian( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t s_len, uint32_t d_len, uint32_t flags, GError **err) { FB_TC_DBC(d_len, "fixed LE encode"); if (s_len == d_len) { memcpy(*dp, sp, d_len); } else if (s_len > d_len) { if (flags & FB_IE_F_ENDIAN) { memcpy(*dp, sp, d_len); } else { memcpy(*dp, sp + (s_len - d_len), d_len); } } else { memset(*dp, 0, d_len); if (flags & FB_IE_F_ENDIAN) { memcpy(*dp, sp, s_len); } else { memcpy(*dp + (d_len - s_len), sp, s_len); } } /* swap bytes at destination if necessary */ if (d_len > 1 && (flags & FB_IE_F_ENDIAN)) { fbTranscodeSwap(*dp, d_len); } /* maintain counters */ *dp += d_len; *d_rem -= d_len; return TRUE; } /** * fbDecodeFixedLittleEndian * * * * * */ static gboolean fbDecodeFixedLittleEndian( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t s_len, uint32_t d_len, uint32_t flags, GError **err) { FB_TC_DBC(d_len, "fixed LE decode"); if (s_len == d_len) { memcpy(*dp, sp, d_len); } else if (s_len > d_len) { if (flags & FB_IE_F_ENDIAN) { memcpy(*dp, sp + (s_len - d_len), d_len); } else { memcpy(*dp, sp, d_len); } } else { memset(*dp, 0, d_len); if (flags & FB_IE_F_ENDIAN) { memcpy(*dp + (d_len - s_len), sp, s_len); } else { memcpy(*dp, sp, s_len); } } /* swap bytes at destination if necessary */ if (d_len > 1 && (flags & FB_IE_F_ENDIAN)) { fbTranscodeSwap(*dp, d_len); } /* maintain counters */ *dp += d_len; *d_rem -= d_len; return TRUE; } #define fbEncodeFixed fbEncodeFixedLittleEndian #define fbDecodeFixed fbDecodeFixedLittleEndian #endif /** * fbEncodeVarfield * * * * * */ static gboolean fbEncodeVarfield( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { uint32_t d_len; fbVarfield_t *sv; #if HAVE_ALIGNED_ACCESS_REQUIRED fbVarfield_t sv_local; sv = &sv_local; memcpy(sv, sp, sizeof(fbVarfield_t)); #else sv = (fbVarfield_t *)sp; #endif /* calculate total destination length */ d_len = sv->len + ((sv->len < 255) ? 1 : 3); /* Check buffer bounds */ FB_TC_DBC(d_len, "variable-length encode"); /* emit IPFIX variable length */ if (sv->len < 255) { FB_WRITEINC_U8(*dp, sv->len); } else { FB_WRITEINC_U8(*dp, 255); FB_WRITEINC_U16(*dp, sv->len); } /* emit buffer contents */ if (sv->len && sv->buf) memcpy(*dp, sv->buf, sv->len); /* maintain counters */ *dp += sv->len; *d_rem -= d_len; return TRUE; } /** * fbDecodeVarfield * * decodes a variable length IPFIX element into its C structure location * * @param sp source pointer * @param dp destination pointer * @param d_rem destination amount remaining * @param flags unused * @param err glib2 error structure to return error information * * @return true on success, false on error, check err return param for details * */ static gboolean fbDecodeVarfield( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { uint16_t s_len; fbVarfield_t *dv; #if HAVE_ALIGNED_ACCESS_REQUIRED fbVarfield_t dv_local; dv = &dv_local; #else dv = (fbVarfield_t *)*dp; #endif /* calculate total source length */ FB_READ_LIST_LENGTH(s_len, sp); /* Okay. We know how long the source is. Check buffer bounds. */ FB_TC_DBC(sizeof(fbVarfield_t), "variable-length decode"); /* Do transcode. Don't copy; fbVarfield_t's semantics allow us just to return a pointer into the read buffer. */ dv->len = (uint32_t)s_len; dv->buf = s_len ? sp : NULL; #if HAVE_ALIGNED_ACCESS_REQUIRED memcpy(*dp, dv, sizeof(fbVarfield_t)); #endif /* maintain counters */ *dp += sizeof(fbVarfield_t); *d_rem -= sizeof(fbVarfield_t); return TRUE; } /*static gboolean fbDecodeFixedToVarlen( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { return FALSE; } static gboolean fbEncodeFixedToVarlen( uint8_t *sp, uint16_t s_len, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { uint32_t d_len; uint16_t sll; d_len = s_len + ((s_len < 255) ? 1 : 3); FB_TC_DBC(d_len, "fixed to variable lengthed encode"); if (s_len < 255) { **dp = (uint8_t)s_len; *dp += 1; } else { **dp = 255; sll = g_htons(s_len); memcpy(*dp + 1, &sll, sizeof(uint16_t)); *dp += 3; } if (s_len) { memcpy(*dp, sp, s_len); *dp += s_len; *d_rem -= d_len; } return TRUE; } static gboolean fbDecodeVarlenToFixed( uint8_t *sp, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { return FALSE; } static gboolean fbEncodeVarlenToFixed( uint8_t *sp, uint16_t d_len, uint8_t **dp, uint32_t *d_rem, uint32_t flags __attribute__((unused)), GError **err) { uint16_t lenDiff; fbVarfield_t *sVar = (fbVarfield_t*)sp; FB_TC_DBC(d_len, "varlen to fixed encode"); if (sVar->len < d_len) { lenDiff = d_len - sVar->len; memset(*dp, 0, lenDiff); memcpy(*dp + lenDiff, sVar->buf, sVar->len); } else { copy d_len bytes, truncating the varfield at d_len memcpy(*dp, sVar->buf, d_len); } if (d_len > 1 && (flags & FB_IE_F_ENDIAN)) { fbTranscodeSwap(*dp, d_len); } *dp += d_len; *d_rem -= d_len; return TRUE; } */ static gboolean validBasicList( fbBasicList_t *basicList, GError **err) { if (!basicList) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Null basic list pointer passed to encode"); return FALSE; } else if (!basicList->infoElement) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Null information element in basic list passed to encode"); return FALSE; } else if (basicList->numElements && !basicList->dataLength) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive num elements, but zero data length in basiclist"); return FALSE; } else if (basicList->dataLength && !basicList->dataPtr) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive data length but null data pointer in basiclist"); return FALSE; } return TRUE; } static gboolean validSubTemplateList( fbSubTemplateList_t *STL, GError **err) { if (!STL) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Null sub template list pointer passed to encode"); return FALSE; } else if (!STL->tmpl || !STL->tmplID) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Invalid template pointer %p or ID %d passed to STL encode", STL->tmpl, STL->tmplID); return FALSE; } else if (STL->numElements && !STL->dataLength.length) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive num elements, but zero data length in STL"); return FALSE; } else if (STL->dataLength.length && !STL->dataPtr) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive data length but null data pointer in STL"); return FALSE; } return TRUE; } static gboolean validSubTemplateMultiList( fbSubTemplateMultiList_t *sTML, GError **err) { if (!sTML) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Null sub template multi list pointer passed to encode"); return FALSE; } else if (sTML->numElements && !sTML->firstEntry) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive num elements, but NULL first Entry in STML"); return FALSE; } return TRUE; } static gboolean validSubTemplateMultiListEntry( fbSubTemplateMultiListEntry_t *entry, GError **err) { if (!entry) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Null sub template multi list entry pointer"); return FALSE; } else if (!entry->tmpl || !entry->tmplID) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Invalid template pointer %p or ID %d passed to STML encode", entry->tmpl, entry->tmplID); return FALSE; } else if (entry->dataLength && !entry->dataPtr) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Positive data length but null data pointer in STML"); return FALSE; } return TRUE; } /* parses the data according to the external template to determine the number of bytes in the src for this template instance this function is intended to be used in decoding and assumes the values are still in NETWORK byte order data: pointer to the data that came accross the wire ext_tmpl: external template...what the data looks like on arrival bytesInSrc: number of bytes in incoming data used by the ext_tmpl */ static void bytesUsedBySrcTemplate( const uint8_t *data, const fbTemplate_t *ext_tmpl, uint16_t *bytesInSrc) { fbInfoElement_t *ie; const uint8_t *srcWalker = data; uint16_t len; int i; if (!ext_tmpl->is_varlen) { *bytesInSrc = ext_tmpl->ie_len; return; } for (i = 0; i < ext_tmpl->ie_count; i++) { ie = ext_tmpl->ie_ary[i]; if (ie->len == FB_IE_VARLEN) { FB_READ_LIST_LENGTH(len, srcWalker); srcWalker += len; } else { srcWalker += ie->len; } } *bytesInSrc = srcWalker - data; } static gboolean fbTranscode( fBuf_t *fbuf, gboolean decode, uint8_t *s_base, uint8_t *d_base, size_t *s_len, size_t *d_len, GError **err); static gboolean fbEncodeBasicList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fbDecodeBasicList( fbInfoModel_t *model, uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fbEncodeSubTemplateList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fbDecodeSubTemplateList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fbEncodeSubTemplateMultiList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fbDecodeSubTemplateMultiList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err); static gboolean fBufSetDecodeSubTemplates( fBuf_t *fbuf, uint16_t ext_tid, uint16_t int_tid, GError **err); static gboolean fBufSetEncodeSubTemplates( fBuf_t *fbuf, uint16_t ext_tid, uint16_t int_tid, GError **err); static gboolean fBufResetExportTemplate( fBuf_t *fbuf, uint16_t tid, GError **err); static gboolean fbEncodeBasicList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { uint16_t totalLength; uint16_t headerLength; uint16_t dataLength = 0; uint16_t ie_len; uint16_t ie_num; uint8_t *lengthPtr = NULL; uint16_t i; gboolean enterprise = FALSE; uint8_t *prevDst = NULL; fbBasicList_t *basicList; uint8_t *thisItem = NULL; gboolean retval = FALSE; #if HAVE_ALIGNED_ACCESS_REQUIRED fbBasicList_t basicList_local; basicList = &basicList_local; memcpy(basicList, src, sizeof(fbBasicList_t)); #else basicList = (fbBasicList_t*)src; #endif if (!validBasicList(basicList, err)) { return FALSE; } /* we need to check the buffer bounds throughout the function at each stage then decrement d_rem as we go */ /* header is 5 bytes: 1 for the semantic 2 for the field id 2 for the field length */ headerLength = 5; ie_len = basicList->infoElement->len; /* get the info element number */ ie_num = basicList->infoElement->num; /* check for enterprise value in the information element, to set bit Need to know if IE is enterprise before adding totalLength for fixed length IE's */ if (basicList->infoElement->ent) { enterprise = TRUE; ie_num |= 0x8000; headerLength += 4; } /* enter the total bytes */ if (ie_len == FB_IE_VARLEN) { /* check for room for the header */ FB_TC_DBC(headerLength, "basic list encode header"); (*d_rem) -= headerLength; } else { /* fixed length info element. */ dataLength = basicList->numElements * ie_len; totalLength = headerLength + dataLength; /* we know how long the entire list will be, test its length */ FB_TC_DBC(totalLength, "basic list encode fixed list"); (*d_rem) -= totalLength; } /* encode as variable length field */ FB_TC_DBC(3, "basic list variable length encode header"); FB_WRITEINCREM_U8(*dst, 255, *d_rem); /* Mark location of length */ lengthPtr = *dst; (*dst) += 2; (*d_rem) -= 2; /* Mark beginning of element */ prevDst = *dst; /* add the semantic field */ FB_WRITEINC_U8(*dst, basicList->semantic); /* write the element number */ FB_WRITEINC_U16(*dst, ie_num); /* add the info element length */ FB_WRITEINC_U16(*dst, ie_len); /* if enterprise specific info element, add the enterprise number */ if (enterprise) { /* we alredy check room above (headerLength) for enterprise field */ FB_WRITEINC_U32(*dst, basicList->infoElement->ent); } if (basicList->numElements) { /* add the data */ if (ie_len == FB_IE_VARLEN) { /* all future length checks will be done by the called encoding functions */ thisItem = basicList->dataPtr; ie_num = basicList->infoElement->num; switch (ie_num) { case FB_IE_BASIC_LIST: for (i = 0; i < basicList->numElements; i++) { if (!fbEncodeBasicList(thisItem, dst, d_rem, fbuf, err)) { goto err; } thisItem += sizeof(fbBasicList_t); } break; case FB_IE_SUBTEMPLATE_LIST: for (i = 0; i < basicList->numElements; i++) { if (!fbEncodeSubTemplateList(thisItem, dst, d_rem, fbuf, err)) { goto err; } thisItem += sizeof(fbSubTemplateList_t); } break; case FB_IE_SUBTEMPLATE_MULTILIST: for (i = 0; i < basicList->numElements; i++) { if (!fbEncodeSubTemplateMultiList(thisItem, dst, d_rem, fbuf, err)) { goto err; } thisItem += sizeof(fbSubTemplateMultiList_t); } break; default: /* add the varfields, adding up the length field */ for (i = 0; i < basicList->numElements; i++) { if (!fbEncodeVarfield(thisItem, dst, d_rem, 0, err)) { goto err; } thisItem += sizeof(fbVarfield_t); } } } else { /* fixed length info element, just copy the data we already know there's enough room for it */ memcpy(*dst, basicList->dataPtr, dataLength); (*dst) += dataLength; } } retval = TRUE; err: totalLength = (uint16_t)((*dst) - prevDst); FB_WRITE_U16(lengthPtr, totalLength); return retval; } static gboolean fbDecodeBasicList( fbInfoModel_t *model, uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { uint16_t srcLen; uint16_t elementLen; uint16_t ie_num; fbInfoElement_t tempElement; fbBasicList_t *basicList; uint8_t *srcWalker = NULL; uint8_t *thisItem = NULL; fbVarfield_t *thisVarfield = NULL; uint16_t len; int i; #if HAVE_ALIGNED_ACCESS_REQUIRED fbBasicList_t basicList_local; basicList = &basicList_local; memcpy(basicList, *dst, sizeof(fbBasicList_t)); #else basicList = (fbBasicList_t*)*dst; #endif /* check buffer bounds */ if (d_rem) { FB_TC_DBC(sizeof(fbBasicList_t), "basic-list decode"); } memset(&tempElement, 0, sizeof(fbInfoElement_t)); /* decode the length field and move the Buf ptr up to the next field */ FB_READ_LIST_LENGTH(srcLen, src); if (srcLen < 5) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "Not enough bytes for basic list header to decode"); return FALSE; } /* add the semantic field */ FB_READINCREM_U8(basicList->semantic, src, srcLen); /* pull the field ID */ FB_READINCREM_U16(tempElement.num, src, srcLen); /* pull the element length */ FB_READINCREM_U16(elementLen, src, srcLen); /* if enterprise bit is set, pull this field */ if (tempElement.num & 0x8000) { if (srcLen < 4) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "Not enough bytes for basic list header enterprise no."); return FALSE; } FB_READINCREM_U32(tempElement.ent, src, srcLen); tempElement.num &= 0x7fff; } else { tempElement.ent = 0; } /* find the proper info element pointer based on what we built */ basicList->infoElement = fbInfoModelGetElement(model, &tempElement); if (!basicList->infoElement) { /* if infoElement does not exist - notes it's alien and add it */ tempElement.len = elementLen; basicList->infoElement = fbInfoModelAddAlienElement(model, &tempElement); if (!basicList->infoElement) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "BasicList Decode Error: No Information Element with ID %d " "defined", tempElement.num); basicList->semantic = 0; basicList->infoElement = NULL; basicList->numElements = 0; basicList->dataLength = 0; basicList->dataPtr = NULL; goto err; } } if (elementLen == FB_IE_VARLEN) { /* first we need to find out the number of elements */ basicList->numElements = 0; /* if there isn't memory allocated yet, figure out how much */ srcWalker = src; /* while we haven't walked the entire list... */ while (srcLen > (srcWalker - src)) { /* parse the length of each, and jump to the next */ FB_READ_LIST_LENGTH(len, srcWalker); srcWalker += len; basicList->numElements++; } /* now that we know the number of elements, we need to parse the specific varlen field */ ie_num = basicList->infoElement->num; switch (ie_num) { case FB_IE_BASIC_LIST: if (!basicList->dataPtr) { basicList->dataLength = basicList->numElements * sizeof(fbBasicList_t); basicList->dataPtr = g_slice_alloc0(basicList->dataLength); } thisItem = basicList->dataPtr; /* thisItem will be incremented by DecodeBasicList's dst double pointer */ for (i = 0; i < basicList->numElements; i++) { if (!fbDecodeBasicList( model, src, &thisItem, NULL, fbuf, err)) { return FALSE; } /* now figure out how much to increment src by and repeat */ FB_READ_LIST_LENGTH(len, src); src += len; } break; case FB_IE_SUBTEMPLATE_LIST: if (!basicList->dataPtr) { basicList->dataLength = basicList->numElements * sizeof(fbSubTemplateList_t); basicList->dataPtr = g_slice_alloc0(basicList->dataLength); } thisItem = basicList->dataPtr; /* thisItem will be incremented by DecodeSubTemplateList's dst double pointer */ for (i = 0; i < basicList->numElements; i++) { if (!fbDecodeSubTemplateList(src, &thisItem, NULL, fbuf, err)) { return FALSE; } /* now figure out how much to increment src by and repeat */ FB_READ_LIST_LENGTH(len, src); src += len; } break; case FB_IE_SUBTEMPLATE_MULTILIST: if (!basicList->dataPtr) { basicList->dataLength = basicList->numElements * sizeof(fbSubTemplateMultiList_t); basicList->dataPtr = g_slice_alloc0(basicList->dataLength); } thisItem = basicList->dataPtr; /* thisItem will be incremented by DecodeSubTemplateMultiList's dst double pointer */ for (i = 0; i < basicList->numElements; i++) { if (!fbDecodeSubTemplateMultiList(src, &thisItem, NULL, fbuf, err)) { return FALSE; } /* now figure out how much to increment src by and repeat */ FB_READ_LIST_LENGTH(len, src); src += len; } break; default: if (!basicList->dataPtr) { basicList->dataLength = basicList->numElements * sizeof(fbVarfield_t); basicList->dataPtr = g_slice_alloc0(basicList->dataLength); } /* now pull the data numElements times */ thisVarfield = (fbVarfield_t*)basicList->dataPtr; for (i = 0; i < basicList->numElements; i++) { /* decode the length */ FB_READ_LIST_LENGTH(thisVarfield->len, src); thisVarfield->buf = src; src += thisVarfield->len; ++thisVarfield; } } } else { if (srcLen) { /* fixed length field, allocate if needed, then copy */ basicList->numElements = srcLen / elementLen; if (!basicList->dataPtr) { basicList->dataLength = srcLen; basicList->dataPtr = g_slice_alloc0(basicList->dataLength); } memcpy(basicList->dataPtr, src, srcLen); } } err: #if HAVE_ALIGNED_ACCESS_REQUIRED memcpy(*dst, basicList, sizeof(fbBasicList_t)); #endif (*dst) += sizeof(fbBasicList_t); if (d_rem) { *d_rem -= sizeof(fbBasicList_t); } return TRUE; } static gboolean fbEncodeSubTemplateList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { fbSubTemplateList_t *subTemplateList; uint16_t len; uint16_t i; size_t srcLen = 0; size_t dstLen = 0; uint8_t *lenPtr = NULL; gboolean rv = TRUE; uint16_t tempIntID; uint16_t tempExtID; uint16_t dataPtrOffset = 0; size_t srcRem = 0; gboolean retval = FALSE; #if HAVE_ALIGNED_ACCESS_REQUIRED fbSubTemplateList_t subTemplateList_local; subTemplateList = &subTemplateList_local; memcpy(subTemplateList, src, sizeof(fbSubTemplateList_t)); #else subTemplateList = (fbSubTemplateList_t *)src; #endif if (!validSubTemplateList(subTemplateList, err)) { return FALSE; } /* check that there are 7 bytes available in the buffer for the header */ FB_TC_DBC(6, "sub template list header"); (*d_rem) -= 6; /* build the subtemplatelist metadata */ /* encode as variable length */ FB_WRITEINC_U8(*dst, 255); /* Save a pointer to the length location in this subTemplateList */ lenPtr = *dst; (*dst) += 2; /* write the semantic value */ FB_WRITEINC_U8(*dst, subTemplateList->semantic); /* encode the template ID */ FB_WRITEINC_U16(*dst, subTemplateList->tmplID); /* store off the current template ids so we can put them back */ tempIntID = fbuf->int_tid; tempExtID = fbuf->ext_tid; /* set the templates to that used for this subTemplateList */ if (!fBufSetEncodeSubTemplates(fbuf, subTemplateList->tmplID, subTemplateList->tmplID, err)) { goto err; } dataPtrOffset = 0; /* max source length is length of dataPtr */ srcRem = subTemplateList->dataLength.length; for (i = 0; i < subTemplateList->numElements && rv; i++) { srcLen = srcRem; dstLen = *d_rem; /* transcode the sub template multi list*/ rv = fbTranscode(fbuf, FALSE, subTemplateList->dataPtr + dataPtrOffset, *dst, &srcLen, &dstLen, err); if (rv) { /* move up the dst pointer by how much we used in transcode */ (*dst) += dstLen; /* subtract from d_rem the number of dst bytes used in transcode */ *d_rem -= dstLen; /* more the src offset for the next transcode by src bytes used */ dataPtrOffset += srcLen; /* subtract from the original data len for new max value */ srcRem -= srcLen; } else { goto err; } } retval = TRUE; err: /* once transcoding is done, store the list length */ len = ((*dst) - lenPtr) - 2; FB_WRITE_U16(lenPtr, len); /* reset the templates */ if (tempIntID == tempExtID) { /* if equal tempIntID is an external template */ /* so calling setInternalTemplate with tempIntID won't find tmpl */ fBufSetEncodeSubTemplates(fbuf, tempExtID, tempIntID, err); } else { if (!fBufSetInternalTemplate(fbuf, tempIntID, err)) { return FALSE; } if (!fBufResetExportTemplate(fbuf, tempExtID, err)) { return FALSE; } } return retval; } static gboolean fbDecodeSubTemplateList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { fbSubTemplateList_t *subTemplateList; fbTemplate_t *extTemplate = NULL; fbTemplate_t *intTemplate = NULL; size_t srcLen; size_t dstLen; uint16_t srcRem; uint16_t dstRem; uint16_t tempIntID; uint16_t tempExtID; fbTemplate_t *tempIntPtr; fbTemplate_t *tempExtPtr; uint32_t i; gboolean rc = TRUE; uint8_t *subTemplateDst = NULL; uint16_t offset = 0; uint16_t bytesInSrc; uint16_t int_tid = 0; uint16_t ext_tid; #if HAVE_ALIGNED_ACCESS_REQUIRED fbSubTemplateList_t subTemplateList_local; subTemplateList = &subTemplateList_local; memcpy(subTemplateList, *dst, sizeof(fbSubTemplateList_t)); #else subTemplateList = (fbSubTemplateList_t *)*dst; #endif /* decode the length of the list */ FB_READ_LIST_LENGTH(srcLen, src); if (srcLen < 3) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "Not enough bytes for the sub template list header"); return FALSE; } if (d_rem) { FB_TC_DBC(sizeof(fbSubTemplateList_t), "sub-template-list decode"); } FB_READINCREM_U8(subTemplateList->semantic, src, srcLen); FB_READINCREM_U16(ext_tid, src, srcLen); /* get the template */ extTemplate = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); if (extTemplate) { int_tid = fbSessionLookupTemplatePair(fbuf->session, ext_tid); if (int_tid == ext_tid) { /* is there an internal tid with the same tid as the external tid? If so, get it. If not, set the internal template to the external template */ intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!intTemplate) { g_clear_error(err); intTemplate = extTemplate; } } else if (int_tid != 0) { intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!intTemplate) { return FALSE; } } } if (!extTemplate || !intTemplate) { /* we need both to continue on this item*/ if (!extTemplate) { g_clear_error(err); g_warning("Skipping SubTemplateList. No Template 0x%02x Present.", ext_tid); } /* if (!(extTemplate)) { g_clear_error(err); g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Template does not exist for template ID: %02x", ext_tid); return FALSE; } int_tid = fbSessionLookupTemplatePair(fbuf->session, ext_tid); if (int_tid == ext_tid) { intTemplate = extTemplate; } else if (int_tid != 0){ intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); } else {*/ /* the collector doesn't want this template...ever don't move the dst pointer at all! the source pointer will get moved up in fbTranscode(), which won't know we didn't do anything */ subTemplateList->semantic = 0; subTemplateList->tmplID = 0; subTemplateList->tmpl = NULL; subTemplateList->dataLength.length = 0; subTemplateList->dataPtr = NULL; subTemplateList->numElements = 0; goto end; } subTemplateList->tmplID = int_tid; subTemplateList->tmpl = intTemplate; /* now we wanna transcode length / templateSize elements */ if (extTemplate->is_varlen) { uint8_t *srcWalker = src; subTemplateList->numElements = 0; while (srcLen > (size_t)(srcWalker - src)) { bytesUsedBySrcTemplate(srcWalker, extTemplate, &bytesInSrc); srcWalker += bytesInSrc; subTemplateList->numElements++; } if (!subTemplateList->dataPtr) { subTemplateList->dataLength.length = intTemplate->ie_internal_len * subTemplateList->numElements; if (subTemplateList->dataLength.length) { subTemplateList->dataPtr = g_slice_alloc0(subTemplateList->dataLength.length); } dstRem = subTemplateList->dataLength.length; } else { if (subTemplateList->dataLength.length < (size_t)(intTemplate->ie_internal_len * subTemplateList->numElements)) { subTemplateList->semantic = 0; subTemplateList->tmplID = 0; subTemplateList->tmpl = NULL; subTemplateList->dataLength.length = 0; subTemplateList->dataPtr = NULL; subTemplateList->numElements = 0; g_warning("SubTemplateList and Template Length mismatch. " "Was fbSubTemplateListCollectorInit() called " "during setup?"); goto end; } dstRem = intTemplate->ie_internal_len * subTemplateList->numElements; } } else { subTemplateList->numElements = srcLen / extTemplate->ie_len; subTemplateList->dataLength.length = subTemplateList->numElements * intTemplate->ie_internal_len; if (!subTemplateList->dataPtr) { if (subTemplateList->dataLength.length) { subTemplateList->dataPtr = g_slice_alloc0(subTemplateList->dataLength.length); } } dstRem = subTemplateList->dataLength.length; } tempExtID = fbuf->ext_tid; tempIntID = fbuf->int_tid; tempExtPtr = fbuf->ext_tmpl; tempIntPtr = fbuf->int_tmpl; fBufSetDecodeSubTemplates(fbuf, ext_tid, int_tid, err); subTemplateDst = subTemplateList->dataPtr; srcRem = srcLen; offset = 0; for (i = 0; i < subTemplateList->numElements && rc; i++) { srcLen = srcRem; dstLen = dstRem; rc = fbTranscode(fbuf, TRUE, src + offset, subTemplateDst, &srcLen, &dstLen, err); if (rc) { subTemplateDst += dstLen; dstRem -= dstLen; srcRem -= srcLen; offset += srcLen; } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Error Decoding SubTemplateList: %s\n", (*err)->message); return FALSE; } /* transcode numElements number of records */ } if (tempIntPtr == tempExtPtr) { fBufSetDecodeSubTemplates(fbuf, tempExtID, tempIntID, err); } else { if (!fBufSetInternalTemplate(fbuf, tempIntID, err)) { return FALSE; } if (!fBufResetExportTemplate(fbuf, tempExtID, err)) { return FALSE; } } end: #if HAVE_ALIGNED_ACCESS_REQUIRED memcpy(*dst, subTemplateList, sizeof(fbSubTemplateList_t)); #endif *dst += sizeof(fbSubTemplateList_t); if (d_rem) { *d_rem -= sizeof(fbSubTemplateList_t); } return TRUE; } static gboolean fbEncodeSubTemplateMultiList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { fbSubTemplateMultiList_t *multiList; fbSubTemplateMultiListEntry_t *entry = NULL; uint16_t length; uint16_t i, j; size_t srcLen = 0; size_t dstLen = 0; uint8_t *lenPtr = NULL; uint8_t *entryLenPtr = NULL; gboolean rv = TRUE; uint16_t tempIntID; uint16_t tempExtID; uint16_t srcPtrOffset = 0; size_t srcRem = 0; gboolean retval = FALSE; #if HAVE_ALIGNED_ACCESS_REQUIRED fbSubTemplateMultiList_t multiList_local; multiList = &multiList_local; memcpy(multiList, src, sizeof(fbSubTemplateMultiList_t)); #else multiList = (fbSubTemplateMultiList_t *)src; #endif /* calculate total destination length */ if (!validSubTemplateMultiList(multiList, err)) { return FALSE; } /* Check buffer bounds */ FB_TC_DBC(4, "multi list header"); (*d_rem) -= 4; FB_WRITEINC_U8(*dst, 255); /* set the pointer to the length of this subTemplateList */ lenPtr = *dst; (*dst) += 2; FB_WRITEINC_U8(*dst, multiList->semantic); tempIntID = fbuf->int_tid; tempExtID = fbuf->ext_tid; entry = multiList->firstEntry; for (i = 0; i < multiList->numElements; i++) { if (!validSubTemplateMultiListEntry(entry, err)) { continue; } /* check to see if there's enough length for the entry header */ FB_TC_DBC_ERR(4, "multi list entry header"); (*d_rem) -= 4; /* at this point, it's very similar to a subtemplatelist */ /* template ID */ FB_WRITEINC_U16(*dst, entry->tmplID); /* save template data length location */ entryLenPtr = *dst; (*dst) += 2; if (!fBufSetEncodeSubTemplates(fbuf, entry->tmplID,entry->tmplID,err)) { goto err; } srcRem = entry->dataLength; srcPtrOffset = 0; for (j = 0; j < entry->numElements; j++) { srcLen = srcRem; dstLen = *d_rem; rv = fbTranscode(fbuf, FALSE, entry->dataPtr + srcPtrOffset, *dst, &srcLen, &dstLen, err); if (rv) { (*dst) += dstLen; (*d_rem) -= dstLen; srcPtrOffset += srcLen; *entryLenPtr += dstLen; srcRem -= srcLen; } else { goto err; } } length = *dst - entryLenPtr + 2; /* +2 for template ID */ FB_WRITE_U16(entryLenPtr, length); entry++; } retval = TRUE; err: /* Write length */ length = ((*dst) - lenPtr) - 2; FB_WRITE_U16(lenPtr, length); /* Put templates back */ if (tempIntID == tempExtID) { fBufSetEncodeSubTemplates(fbuf, tempExtID, tempIntID, err); } else { if (!fBufSetInternalTemplate(fbuf, tempIntID, err)) { return FALSE; } if (!fBufResetExportTemplate(fbuf, tempExtID, err)) { return FALSE; } } return retval; } static gboolean fbDecodeSubTemplateMultiList( uint8_t *src, uint8_t **dst, uint32_t *d_rem, fBuf_t *fbuf, GError **err) { fbSubTemplateMultiList_t *multiList; fbTemplate_t *extTemplate = NULL, *intTemplate = NULL; size_t srcLen; uint16_t bytesInSrc; size_t dstLen; size_t srcRem; size_t dstRem; uint16_t tempIntID; fbTemplate_t *tempIntPtr; uint16_t tempExtID; fbTemplate_t *tempExtPtr; gboolean rc = TRUE; uint8_t *srcWalker = NULL; fbSubTemplateMultiListEntry_t *entry = NULL; uint16_t thisTemplateLength; uint16_t i; uint16_t j; uint16_t int_tid = 0; uint16_t ext_tid; uint8_t *thisTemplateDst; #if HAVE_ALIGNED_ACCESS_REQUIRED fbSubTemplateMultiList_t multiList_local; multiList = &multiList_local; memcpy(multiList, *dst, sizeof(fbSubTemplateMultiList_t)); #else multiList = (fbSubTemplateMultiList_t *)*dst; #endif FB_READ_LIST_LENGTH(srcLen, src); if (d_rem) { FB_TC_DBC(sizeof(fbSubTemplateMultiList_t), "sub-template-multi-list decode"); } if (srcLen == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "Insufficient bytes for subTemplateMultiList header to " "decode"); return FALSE; } FB_READINCREM_U8(multiList->semantic, src, srcLen); tempExtID = fbuf->ext_tid; tempIntID = fbuf->int_tid; tempExtPtr = fbuf->ext_tmpl; tempIntPtr = fbuf->int_tmpl; multiList->numElements = 0; /* figure out how many elements are here */ srcWalker = src; while (srcLen > (size_t)(srcWalker - src)) { /* jump over the template ID */ srcWalker += 2; FB_READINC_U16(bytesInSrc, srcWalker); if (bytesInSrc < 4) { g_warning("Invalid Length (%d) in STML Record", bytesInSrc); break; } srcWalker += bytesInSrc - 4; multiList->numElements++; } multiList->firstEntry = g_slice_alloc0(multiList->numElements * sizeof(fbSubTemplateMultiListEntry_t)); entry = multiList->firstEntry; for (i = 0; i < multiList->numElements; i++) { intTemplate = NULL; FB_READINC_U16(ext_tid, src); extTemplate = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); /* OLD WAY... if (!extTemplate) { return FALSE; } int_tid = fbSessionLookupTemplatePair(fbuf->session, ext_tid); if (int_tid == ext_tid) { intTemplate = extTemplate; } else if (int_tid != 0) { intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!intTemplate) { return FALSE; } } else { entry->tmpl = NULL; entry->tmplID = 0; entry->dataLength = 0; entry->dataPtr = NULL; FB_READ_U16(thisTemplateLength, src); thisTemplateLength -= 2; src += thisTemplateLength; entry++; continue; }*/ if (extTemplate) { int_tid = fbSessionLookupTemplatePair(fbuf->session, ext_tid); if (int_tid == ext_tid) { /* is it possible that there could be an internal template with the same template id as the external template? - check now */ intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!intTemplate) { g_clear_error(err); intTemplate = extTemplate; } } else if (int_tid != 0) { intTemplate = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!intTemplate) { return FALSE; } } } if (!extTemplate || !intTemplate) { /* we need both to continue on this item*/ if (!extTemplate) { g_clear_error(err); g_warning("Skipping STML Item. No Template %02x Present.", ext_tid); } entry->tmpl = NULL; entry->tmplID = 0; entry->dataLength = 0; entry->dataPtr = NULL; FB_READ_U16(thisTemplateLength, src); thisTemplateLength -= 2; src += thisTemplateLength; entry++; continue; } entry->tmpl = intTemplate; entry->tmplID = int_tid; FB_READINC_U16(thisTemplateLength, src); thisTemplateLength -= 4; /* "removing" template id and length */ /* put src at the start of the content */ if (!thisTemplateLength) { continue; } if (extTemplate->is_varlen) { srcWalker = src; entry->numElements = 0; while (thisTemplateLength > (size_t)(srcWalker - src)) { bytesUsedBySrcTemplate(srcWalker, extTemplate, &bytesInSrc); srcWalker += bytesInSrc; entry->numElements++; } entry->dataLength = intTemplate->ie_internal_len * entry->numElements; entry->dataPtr = g_slice_alloc0(entry->dataLength); } else { entry->numElements = thisTemplateLength / extTemplate->ie_len; entry->dataLength = entry->numElements * intTemplate->ie_internal_len; entry->dataPtr = g_slice_alloc0(entry->dataLength); } dstRem = entry->dataLength; dstLen = dstRem; srcRem = thisTemplateLength; fBufSetDecodeSubTemplates(fbuf, ext_tid, int_tid, err); thisTemplateDst = entry->dataPtr; for (j = 0; j < entry->numElements; j++) { srcLen = srcRem; dstLen = dstRem; rc = fbTranscode(fbuf, TRUE, src, thisTemplateDst, &srcLen, &dstLen, err); if (rc) { src += srcLen; thisTemplateDst += dstLen; srcRem -= srcLen; dstRem -= dstLen; } else { if (tempIntPtr == tempExtPtr) { fBufSetDecodeSubTemplates(fbuf, tempExtID, tempIntID, err); } else { fBufSetInternalTemplate(fbuf, tempIntID, err); fBufResetExportTemplate(fbuf, tempExtID, err); } return FALSE; } } entry++; } if (tempIntPtr == tempExtPtr) { fBufSetDecodeSubTemplates(fbuf, tempExtID, tempIntID, err); } else { if (!fBufSetInternalTemplate(fbuf, tempIntID, err)) { return FALSE; } if (!fBufResetExportTemplate(fbuf, tempExtID, err)) { return FALSE; } } #if HAVE_ALIGNED_ACCESS_REQUIRED memcpy(*dst, multiList, sizeof(fbSubTemplateMultiList_t)); #endif *dst += sizeof(fbSubTemplateMultiList_t); if (d_rem) { *d_rem -= sizeof(fbSubTemplateMultiList_t); } return TRUE; } /** * fbTranscode * * * * * */ static gboolean fbTranscode( fBuf_t *fbuf, gboolean decode, uint8_t *s_base, uint8_t *d_base, size_t *s_len, size_t *d_len, GError **err) { fbTranscodePlan_t *tcplan; fbTemplate_t *s_tmpl, *d_tmpl; ssize_t s_len_offset; uint16_t *offsets; uint8_t *dp; uint32_t s_off, d_rem, i; fbInfoElement_t *s_ie, *d_ie; gboolean ok = TRUE; uint16_t ie_num; /* initialize walk of dest buffer */ dp = d_base; d_rem = *d_len; /* select templates for transcode */ if (decode) { s_tmpl = fbuf->ext_tmpl; d_tmpl = fbuf->int_tmpl; } else { s_tmpl = fbuf->int_tmpl; d_tmpl = fbuf->ext_tmpl; } /* get a transcode plan */ tcplan = fbTranscodePlan(fbuf, s_tmpl, d_tmpl); /* get source record length and offsets */ if ((s_len_offset = fbTranscodeOffsets(s_tmpl, s_base, *s_len, decode, &offsets, err)) < 0) { return FALSE; } *s_len = s_len_offset; #if FB_DEBUG_TC && FB_DEBUG_RD && FB_DEBUG_WR fBufDebugTranscodePlan(tcplan); if (offsets) fBufDebugTranscodeOffsets(s_tmpl, offsets); fBufDebugHex("tsrc", s_base, *s_len); #elif FB_DEBUG_TC && FB_DEBUG_RD if (decode) { fBufDebugTranscodePlan(tcplan); /* if (offsets) fBufDebugTranscodeOffsets(s_tmpl, offsets); fBufDebugHex("tsrc", s_base, *s_len);*/ } if (!decode) { fBufDebugTranscodePlan(tcplan); if (offsets) fBufDebugTranscodeOffsets(s_tmpl, offsets); fBufDebugHex("tsrc", s_base, *s_len); } #endif /* iterate over destination IEs, copying from source */ for (i = 0; i < d_tmpl->ie_count; i++) { /* Get pointers to information elements and source offset */ d_ie = d_tmpl->ie_ary[i]; s_ie = (tcplan->si[i] == FB_TCPLAN_NULL) ? NULL : s_tmpl->ie_ary[tcplan->si[i]]; s_off = s_ie ? offsets[tcplan->si[i]] : 0; if (s_ie == NULL) { /* Null source */ uint32_t null_len; if (d_ie->len == FB_IE_VARLEN) { if (decode) { ie_num = d_ie->num; if (ie_num == FB_IE_BASIC_LIST) { null_len = sizeof(fbBasicList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_LIST) { null_len = sizeof(fbSubTemplateList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_MULTILIST) { null_len = sizeof(fbSubTemplateMultiList_t); } else { null_len = sizeof(fbVarfield_t); } } else { null_len = 1; } } else { null_len = d_ie->len; } if (!(ok = fbTranscodeZero(&dp, &d_rem, null_len, err))) { goto end; } } else if (s_ie->len != FB_IE_VARLEN && d_ie->len != FB_IE_VARLEN) { if (decode) { ok = fbDecodeFixed(s_base + s_off, &dp, &d_rem, s_ie->len, d_ie->len, d_ie->flags, err); } else { ok = fbEncodeFixed(s_base + s_off, &dp, &d_rem, s_ie->len, d_ie->len, d_ie->flags, err); } if (!ok) { goto end; } } else if (s_ie->len == FB_IE_VARLEN && d_ie->len == FB_IE_VARLEN) { /* Varlen transcode */ if (s_ie->num == FB_IE_BASIC_LIST && d_ie->num == FB_IE_BASIC_LIST) { if (decode) { ok = fbDecodeBasicList(fbuf->ext_tmpl->model, s_base + s_off, &dp, &d_rem, fbuf, err); } else { ok = fbEncodeBasicList(s_base + s_off, &dp, &d_rem, fbuf, err); } if (!ok) { goto end; } } else if (s_ie->num == FB_IE_SUBTEMPLATE_LIST && d_ie->num == FB_IE_SUBTEMPLATE_LIST) { if (decode) { ok = fbDecodeSubTemplateList(s_base + s_off, &dp, &d_rem, fbuf, err); } else { ok = fbEncodeSubTemplateList(s_base + s_off, &dp, &d_rem, fbuf, err); } if (!ok) { goto end; } } else if (s_ie->num == FB_IE_SUBTEMPLATE_MULTILIST && d_ie->num == FB_IE_SUBTEMPLATE_MULTILIST) { if (decode) { ok = fbDecodeSubTemplateMultiList(s_base + s_off, &dp, &d_rem, fbuf, err); } else { ok = fbEncodeSubTemplateMultiList(s_base + s_off, &dp, &d_rem, fbuf, err); } if (!ok) { goto end; } } else { if (decode) { ok = fbDecodeVarfield(s_base + s_off, &dp, &d_rem, d_ie->flags, err); } else { ok = fbEncodeVarfield(s_base + s_off, &dp, &d_rem, d_ie->flags, err); } } if (!ok) { goto end; } } else { /* Fixed to varlen or vice versa */ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IMPL, "Transcoding between fixed and varlen IE " "not supported by this version of libfixbuf."); ok = FALSE; goto end; /* if (s_ie->len == FB_IE_VARLEN && d_ie->len != FB_IE_VARLEN) { if (decode) { printf("decode varlen to fixed\n"); ok = fbDecodeVarlenToFixed(s_base + s_off, &dp, &d_rem, d_ie->flags, err); } else { ok = fbEncodeVarlenToFixed(s_base + s_off, d_ie->len, &dp, &d_rem, d_ie->flags, err); } } else { if (decode) { printf("decode fixed to varlen\n"); ok = fbDecodeFixedToVarlen(s_base + s_off, &dp, &d_rem, d_ie->flags, err); } else { ok = fbEncodeFixedToVarlen(s_base + s_off, s_ie->len, &dp, &d_rem, d_ie->flags, err); } } if (!ok) { goto end; }*/ } } /* Return destination length */ *d_len = dp - d_base; #if FB_DEBUG_TC && FB_DEBUG_RD && FB_DEBUG_WR fBufDebugHex("tdst", d_base, *d_len); #elif FB_DEBUG_TC && FB_DEBUG_RD if (decode) fBufDebugHex("tdst", d_base, *d_len); #elif FB_DEBUG_TC && FB_DEBUG_WR if (!decode) fBufDebugHex("tdst", d_base, *d_len); #endif /* All done */ end: fbTranscodeFreeVarlenOffsets(s_tmpl, offsets); return ok; } /*================================================================== * * Common Buffer Management Functions * *==================================================================*/ /** * fBufRewind * * * * * */ void fBufRewind( fBuf_t *fbuf) { if (fbuf->collector || fbuf->exporter) { /* Reset the buffer */ fbuf->cp = fbuf->buf; } else { /* set the buffer to the end of the message */ fbuf->cp = fbuf->mep; } fbuf->mep = fbuf->cp; /* No message or set headers in buffer */ fbuf->msgbase = NULL; fbuf->setbase = NULL; fbuf->sep = NULL; /* No records in buffer either */ fbuf->rc = 0; } /** * fBufSetInternalTemplate * * * * * */ gboolean fBufSetInternalTemplate( fBuf_t *fbuf, uint16_t int_tid, GError **err) { /* Look up new internal template if necessary */ if (!fbuf->int_tmpl || fbuf->int_tid != int_tid || fbSessionIntTmplTableFlagIsSet(fbuf->session)) { fbSessionClearIntTmplTableFlag(fbuf->session); fbuf->int_tid = int_tid; fbuf->int_tmpl = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!fbuf->int_tmpl) { return FALSE; } } #if FB_DEBUG_TMPL fbTemplateDebug("int", int_tid, fbuf->int_tmpl); #endif return TRUE; } /** * fBufSetAutomaticMode * * * * * */ void fBufSetAutomaticMode( fBuf_t *fbuf, gboolean automatic) { fbuf->automatic = automatic; } /** * fBufSetAutomaticInsert * * */ gboolean fBufSetAutomaticInsert( fBuf_t *fbuf, GError **err) { /* need the info model */ fbSession_t *session = fBufGetSession(fbuf); fbTemplate_t *tmpl = NULL; tmpl = fbInfoElementAllocTypeTemplate(fbSessionGetInfoModel(session), err); if (!tmpl) { return FALSE; } fbuf->auto_insert_tid = fbSessionAddTemplate(session, TRUE, FB_TID_AUTO, tmpl, err); if (fbuf->auto_insert_tid == 0) { return FALSE; } return TRUE; } /** * fBufGetSession * * * * * */ fbSession_t *fBufGetSession( fBuf_t *fbuf) { return fbuf->session; } /** * fBufFree * * * * * */ void fBufFree( fBuf_t *fbuf) { fbTCPlanEntry_t *entry; /* free the tcplans */ while (fbuf->latestTcplan) { entry = fbuf->latestTcplan; detachHeadOfDLL((fbDLL_t**)(void*)&(fbuf->latestTcplan), NULL, (fbDLL_t**)(void*)&entry); g_free(entry->tcplan->si); g_slice_free1(sizeof(fbTranscodePlan_t), entry->tcplan); g_slice_free1(sizeof(fbTCPlanEntry_t), entry); } if (fbuf->exporter) { fbExporterFree(fbuf->exporter); } if (fbuf->collector) { fbCollectorRemoveListenerLastBuf(fbuf, fbuf->collector); fbCollectorFree(fbuf->collector); } fbSessionFree(fbuf->session); g_slice_free(fBuf_t, fbuf); } /*================================================================== * * Buffer Append (Writer) Functions * *==================================================================*/ #define FB_APPEND_U16(_val_) FB_WRITEINC_U16(fbuf->cp, _val_); #define FB_APPEND_U32(_val_) FB_WRITEINC_U32(fbuf->cp, _val_); /** * fBufAppendMessageHeader * * * * * */ static void fBufAppendMessageHeader( fBuf_t *fbuf) { /* can only append message header at start of buffer */ g_assert(fbuf->cp == fbuf->buf); /* can only append message header if we have an exporter */ g_assert(fbuf->exporter); /* get MTU from exporter */ fbuf->mep += fbExporterGetMTU(fbuf->exporter); g_assert(FB_REM_MSG(fbuf) > FB_MTU_MIN); /* set message base pointer to show we have an active message */ fbuf->msgbase = fbuf->cp; /* add version to buffer */ FB_APPEND_U16(0x000A); /* add message length to buffer */ FB_APPEND_U16(0); /* add export time to buffer */ if (fbuf->extime) { FB_APPEND_U32(fbuf->extime); } else { FB_APPEND_U32(time(NULL)); } /* add sequence number to buffer */ FB_APPEND_U32(fbSessionGetSequence(fbuf->session)); /* add observation domain ID to buffer */ FB_APPEND_U32(fbSessionGetDomain(fbuf->session)); #if FB_DEBUG_WR fBufDebugBuffer("amsg", fbuf, 16, TRUE); #endif } /** * fBufAppendSetHeader * * * * * */ static gboolean fBufAppendSetHeader( fBuf_t *fbuf, GError **err) { uint16_t set_id, set_minlen; /* Select set ID and minimum set size based on special TID */ if (fbuf->spec_tid) { set_id = fbuf->spec_tid; set_minlen = 4; } else { set_id = fbuf->ext_tid; set_minlen = (fbuf->ext_tmpl->ie_len + 4); } /* Need enough space in the message for a set header and a record */ if (FB_REM_MSG(fbuf) < set_minlen) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "End of message. " "Overrun on set header append " "(need %u bytes, %u available)", set_minlen, (uint32_t)FB_REM_MSG(fbuf)); return FALSE; } /* set set base pointer to show we have an active set */ fbuf->setbase = fbuf->cp; /* add set ID to buffer */ FB_APPEND_U16(set_id); /* add set length to buffer */ FB_APPEND_U16(0); #if FB_DEBUG_WR fBufDebugBuffer("aset", fbuf, 4, TRUE); #endif return TRUE; } /** * fBufAppendSetClose * * * * * */ static void fBufAppendSetClose( fBuf_t *fbuf) { uint16_t setlen; /* If there's an active set... */ if (fbuf->setbase) { /* store set length */ setlen = g_htons(fbuf->cp - fbuf->setbase); memcpy(fbuf->setbase + 2, &setlen, sizeof(setlen)); #if FB_DEBUG_WR fBufDebugHex("cset", fbuf->setbase, 4); #endif /* deactivate set */ fbuf->setbase = NULL; } } #if HAVE_SPREAD /** * fBufSetSpreadExportGroup * * */ void fBufSetSpreadExportGroup( fBuf_t *fbuf, char **groups, int num_groups, GError **err) { if (fbExporterCheckGroups(fbuf->exporter, groups, num_groups)) { /* need to set to 0 bc if the same tmpl_id is used between groups * it won't get set to the new group before using */ fBufEmit(fbuf, err); fbuf->ext_tid = 0; } fbSessionSetGroup(fbuf->session, (char *)groups[0]); fBufSetExportGroups(fbuf, groups, num_groups, err); } /** * * fBufSetExportGroups * */ void fBufSetExportGroups( fBuf_t *fbuf, char **groups, int num_groups, GError **err) { (void) err; fbExporterSetGroupsToSend(fbuf->exporter, groups, num_groups); } #endif /** * fBufSetExportTemplate * * * * * */ gboolean fBufSetExportTemplate( fBuf_t *fbuf, uint16_t ext_tid, GError **err) { /* Look up new external template if necessary */ if (!fbuf->ext_tmpl || fbuf->ext_tid != ext_tid || fbSessionExtTmplTableFlagIsSet(fbuf->session)) { fbSessionClearExtTmplTableFlag(fbuf->session); fbuf->ext_tid = ext_tid; fbuf->ext_tmpl = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); if (!fbuf->ext_tmpl) return FALSE; /* Change of template means new set */ fBufAppendSetClose(fbuf); } #if FB_DEBUG_TMPL fbTemplateDebug("ext", ext_tid, fbuf->ext_tmpl); #endif /* If we're here we're done. */ return TRUE; } /** Set both the external and internal templates to the one referenced in tid. * Pull both template pointers from the external list as this template must * be external and thus on both sides of the connection */ static gboolean fBufSetDecodeSubTemplates( fBuf_t *fbuf, uint16_t ext_tid, uint16_t int_tid, GError **err) { fbuf->ext_tmpl = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); if (!fbuf->ext_tmpl) { return FALSE; } fbuf->ext_tid = ext_tid; if (ext_tid == int_tid) { fbuf->int_tid = int_tid; fbuf->int_tmpl = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!fbuf->int_tmpl) { g_clear_error(err); fbuf->int_tmpl = fbuf->ext_tmpl; } } else { fbuf->int_tmpl = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!fbuf->int_tmpl) { return FALSE; } fbuf->int_tid = int_tid; } return TRUE; } static gboolean fBufSetEncodeSubTemplates( fBuf_t *fbuf, uint16_t ext_tid, uint16_t int_tid, GError **err) { fbuf->ext_tmpl = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); if (!fbuf->ext_tmpl) { return FALSE; } fbuf->ext_tid = ext_tid; if (ext_tid == int_tid) { fbuf->int_tid = int_tid; fbuf->int_tmpl = fbuf->ext_tmpl; } else { fbuf->int_tmpl = fbSessionGetTemplate(fbuf->session, TRUE, int_tid, err); if (!fbuf->int_tmpl) { return FALSE; } fbuf->int_tid = int_tid; } return TRUE; } static gboolean fBufResetExportTemplate( fBuf_t *fbuf, uint16_t ext_tid, GError **err) { if (!fbuf->ext_tmpl || fbuf->ext_tid != ext_tid) { fbuf->ext_tid = ext_tid; fbuf->ext_tmpl = fbSessionGetTemplate(fbuf->session, FALSE, ext_tid, err); if (!fbuf->ext_tmpl) { return FALSE; } } return TRUE; } /** * fBufRemoveTemplateTcplan * */ void fBufRemoveTemplateTcplan( fBuf_t *fbuf, fbTemplate_t *tmpl) { fbTCPlanEntry_t *entry; fbTCPlanEntry_t *otherEntry; if (!fbuf || !tmpl) { return; } entry = fbuf->latestTcplan; while (entry) { if (entry->tcplan->s_tmpl == tmpl || entry->tcplan->d_tmpl == tmpl) { if (entry == fbuf->latestTcplan) { otherEntry = NULL; } else { otherEntry = entry->next; } detachThisEntryOfDLL((fbDLL_t**)(void*)(&(fbuf->latestTcplan)), NULL, (fbDLL_t*)entry); g_free(entry->tcplan->si); g_slice_free1(sizeof(fbTranscodePlan_t), entry->tcplan); g_slice_free1(sizeof(fbTCPlanEntry_t), entry); if (otherEntry) { entry = otherEntry; } else { entry = fbuf->latestTcplan; } } else { entry = entry->next; } } } /** * fBufAppendTemplateSingle * * * * * */ static gboolean fBufAppendTemplateSingle( fBuf_t *fbuf, uint16_t tmpl_id, fbTemplate_t *tmpl, gboolean revoked, GError **err) { uint16_t spec_tid, tmpl_len, ie_count, scope_count; int i; /* Force message closed to start a new template message */ if (!fbuf->spec_tid) { fbuf->spec_tid = (tmpl->scope_count) ? FB_TID_OTS : FB_TID_TS; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "End of message. " "Must start new message for template export."); return FALSE; } /* Start a new message if necessary */ if (!fbuf->msgbase) { fBufAppendMessageHeader(fbuf); } /* Check for set ID change */ spec_tid = (tmpl->scope_count) ? FB_TID_OTS : FB_TID_TS; if (fbuf->spec_tid != spec_tid) { fbuf->spec_tid = spec_tid; fBufAppendSetClose(fbuf); } /* Start a new set if necessary */ if (!fbuf->setbase) { if (!fBufAppendSetHeader(fbuf, err)) return FALSE; } /* * Calculate template length and IE count based on whether this * is a revocation. */ if (revoked) { tmpl_len = 4; ie_count = 0; scope_count = 0; } else { tmpl_len = tmpl->tmpl_len; ie_count = tmpl->ie_count; scope_count = tmpl->scope_count; } /* Ensure we have enough space for the template in the message */ if (FB_REM_MSG(fbuf) < tmpl_len) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "End of message. " "Overrun on template append " "(need %u bytes, %u available)", tmpl_len, (uint32_t)FB_REM_MSG(fbuf)); return FALSE; } /* Copy the template header to the message */ FB_APPEND_U16(tmpl_id); FB_APPEND_U16(ie_count); /* Copy scope IE count if present */ if (scope_count) { FB_APPEND_U16(scope_count); } /* Now copy information element specifiers to the buffer */ for (i = 0; i < ie_count; i++) { if (tmpl->ie_ary[i]->ent) { FB_APPEND_U16(IPFIX_ENTERPRISE_BIT | tmpl->ie_ary[i]->num); FB_APPEND_U16(tmpl->ie_ary[i]->len); FB_APPEND_U32(tmpl->ie_ary[i]->ent); } else { FB_APPEND_U16(tmpl->ie_ary[i]->num); FB_APPEND_U16(tmpl->ie_ary[i]->len); } } /* Template records are records too. Increment record count. */ /* Actually, no they're not. Odd. */ /* ++(fbuf->rc); */ #if FB_DEBUG_TMPL fbTemplateDebug("apd", tmpl_id, tmpl); #endif #if FB_DEBUG_WR fBufDebugBuffer("atpl", fbuf, tmpl_len, TRUE); #endif /* Done */ return TRUE; } /** * fBufAppendTemplate * * * * * */ gboolean fBufAppendTemplate( fBuf_t *fbuf, uint16_t tmpl_id, fbTemplate_t *tmpl, gboolean revoked, GError **err) { /* Attempt single append */ if (fBufAppendTemplateSingle(fbuf, tmpl_id, tmpl, revoked, err)) { return TRUE; } /* Fail if not EOM or not automatic */ if (!g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_EOM) || !fbuf->automatic) return FALSE; /* Retryable. Clear error. */ g_clear_error(err); /* Emit message */ if (!fBufEmit(fbuf, err)) return FALSE; /* Retry single append */ return fBufAppendTemplateSingle(fbuf, tmpl_id, tmpl, revoked, err); } /** * fBufAppendSingle * * * * * */ static gboolean fBufAppendSingle( fBuf_t *fbuf, uint8_t *recbase, size_t recsize, GError **err) { size_t bufsize; /* Buffer must have active templates */ g_assert(fbuf->int_tmpl); g_assert(fbuf->ext_tmpl); /* Force message closed to finish any active template message */ if (fbuf->spec_tid) { fbuf->spec_tid = 0; g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, "End of message. " "Must start new message after template export."); return FALSE; } /* Start a new message if necessary */ if (!fbuf->msgbase) { fBufAppendMessageHeader(fbuf); } /* Cancel special set mode if necessary */ if (fbuf->spec_tid) { fbuf->spec_tid = 0; fBufAppendSetClose(fbuf); } /* Start a new set if necessary */ if (!fbuf->setbase) { if (!fBufAppendSetHeader(fbuf, err)) return FALSE; } /* Transcode bytes into buffer */ bufsize = FB_REM_MSG(fbuf); if (!fbTranscode(fbuf, FALSE, recbase, fbuf->cp, &recsize, &bufsize, err)) return FALSE; /* Move current pointer forward by number of bytes written */ fbuf->cp += bufsize; /* Increment record count */ ++(fbuf->rc); #if FB_DEBUG_WR fBufDebugBuffer("arec", fbuf, bufsize, TRUE); #endif /* Done */ return TRUE; } /** * fBufAppend * * * * * */ gboolean fBufAppend( fBuf_t *fbuf, uint8_t *recbase, size_t recsize, GError **err) { /* Attempt single append */ if (fBufAppendSingle(fbuf, recbase, recsize, err)) return TRUE; /* Fail if not EOM or not automatic */ if (!g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_EOM) || !fbuf->automatic) return FALSE; /* Retryable. Clear error. */ g_clear_error(err); /* Emit message */ if (!fBufEmit(fbuf, err)) return FALSE; /* Retry single append */ return fBufAppendSingle(fbuf, recbase, recsize, err); } /** * fBufEmit * * * * * */ gboolean fBufEmit( fBuf_t *fbuf, GError **err) { uint16_t msglen; /* Short-circuit on no message available */ if (!fbuf->msgbase) return TRUE; /* Close current set */ fBufAppendSetClose(fbuf); /* Store message length */ msglen = g_htons(fbuf->cp - fbuf->msgbase); memcpy(fbuf->msgbase + 2, &msglen, sizeof(msglen)); /* for (i = 0; i < g_ntohs(msglen); i++) { printf("%02x", fbuf->buf[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\n\n\n\n");*/ #if FB_DEBUG_WR fBufDebugHex("emit", fbuf->buf, fbuf->cp - fbuf->msgbase); #endif #if FB_DEBUG_LWR fprintf(stderr, "emit %u (%04x)\n", fbuf->cp - fbuf->msgbase, fbuf->cp - fbuf->msgbase); #endif /* Hand the message content to the exporter */ if (!fbExportMessage(fbuf->exporter, fbuf->buf, fbuf->cp - fbuf->msgbase, err)) return FALSE; /* Increment next record sequence number */ fbSessionSetSequence(fbuf->session, fbSessionGetSequence(fbuf->session) + fbuf->rc); /* Rewind message */ fBufRewind(fbuf); /* All done */ return TRUE; } /** * fBufGetExporter * * * * * */ fbExporter_t *fBufGetExporter( fBuf_t *fbuf) { if (fbuf) { return fbuf->exporter; } return NULL; } /** * fBufSetExporter * * * * * */ void fBufSetExporter( fBuf_t *fbuf, fbExporter_t *exporter) { if (fbuf->collector) { fbCollectorFree(fbuf->collector); fbuf->collector = NULL; } if (fbuf->exporter) { fbExporterFree(fbuf->exporter); } fbuf->exporter = exporter; fbSessionSetTemplateBuffer(fbuf->session, fbuf); fBufRewind(fbuf); } /** * fBufAllocForExport * * * * * */ fBuf_t *fBufAllocForExport( fbSession_t *session, fbExporter_t *exporter) { fBuf_t *fbuf = NULL; /* Allocate a new buffer */ fbuf = g_slice_new0(fBuf_t); /* Store reference to session */ fbuf->session = session; /* Set up exporter */ fBufSetExporter(fbuf, exporter); /* Buffers are automatic by default */ fbuf->automatic = TRUE; return fbuf; } /** * fBufSetExportTime * * * * * */ void fBufSetExportTime( fBuf_t *fbuf, uint32_t extime) { fbuf->extime = extime; } /*================================================================== * * Buffer Consume (Reader) Functions * *==================================================================*/ #define FB_CHECK_AVAIL(_op_, _size_) \ if (_size_ > FB_REM_MSG(fbuf)) { \ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_EOM, \ "End of message %s " \ "(need %u bytes, %u available)", \ (_op_), (_size_), (uint32_t)FB_REM_MSG(fbuf)); \ return FALSE; \ } #define FB_NEXT_U16(_val_) FB_READINC_U16(_val_, fbuf->cp) #define FB_NEXT_U32(_val_) FB_READINC_U32(_val_, fbuf->cp) /** * fBufNextMessage * * * * * */ gboolean fBufNextMessage( fBuf_t *fbuf, GError **err) { size_t msglen; uint16_t mh_version, mh_len; uint32_t ex_sequence, mh_sequence, mh_domain; /* Need a collector */ /*g_assert(fbuf->collector);*/ /* Clear external template */ fbuf->ext_tid = 0; fbuf->ext_tmpl = NULL; /* Rewind the buffer before reading a new message */ fBufRewind(fbuf); /* Read next message from the collector */ if (fbuf->collector) { msglen = sizeof(fbuf->buf); if (!fbCollectMessage(fbuf->collector, fbuf->buf, &msglen, err)) { return FALSE; } } else { if (fbuf->buflen) { if (!fbCollectMessageBuffer(fbuf->cp, fbuf->buflen, &msglen, err)) { return FALSE; } } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ, "Buffer length = 0"); return FALSE; } /* subtract the next message from the total buffer length */ fbuf->buflen -= msglen; } /* Set the message end pointer */ fbuf->mep = fbuf->cp + msglen; #if FB_DEBUG_RD fBufDebugHex("read", fbuf->buf, msglen); #endif #if FB_DEBUG_LWR fprintf(stderr, "read %lu (%04lx)\n", msglen, msglen); #endif /* Make sure we have at least a message header */ FB_CHECK_AVAIL("reading message header", 16); #if FB_DEBUG_RD fBufDebugBuffer("rmsg", fbuf, 16, FALSE); #endif /* Read and verify version */ FB_NEXT_U16(mh_version); if (mh_version != 0x000A) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Message version 0x%04x; " "input is probably not an IPFIX Message stream.", mh_version); return FALSE; } /* Read and verify message length */ FB_NEXT_U16(mh_len); if (mh_len != msglen) { if (NULL != fbuf->collector) { if (!fbCollectorHasTranslator(fbuf->collector)){ g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "IPFIX Message length mismatch " "(buffer has %u, read %u)", (uint32_t)msglen, mh_len); return FALSE; } } else { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "IPFIX Message length mismatch " "(buffer has %u, read %u)", (uint32_t)msglen, mh_len); return FALSE; } } /* Read and store export time */ FB_NEXT_U32(fbuf->extime); /* Read sequence number */ FB_NEXT_U32(mh_sequence); /* Read observation domain ID and reset domain if necessary */ FB_NEXT_U32(mh_domain); fbSessionSetDomain(fbuf->session, mh_domain); #if HAVE_SPREAD /* Only worry about sequence numbers for first group in list * of received groups & only if we subscribe to that group*/ if (fbCollectorTestGroupMembership(fbuf->collector, 0)) { #endif /* Verify and update sequence number */ ex_sequence = fbSessionGetSequence(fbuf->session); if (ex_sequence != mh_sequence) { if (ex_sequence) { g_warning("IPFIX Message out of sequence " "(in domain %08x, expected %08x, got %08x)", fbSessionGetDomain(fbuf->session), ex_sequence, mh_sequence); } fbSessionSetSequence(fbuf->session, mh_sequence); } #if HAVE_SPREAD } #endif /* * We successfully read a message header. * Set message base pointer to start of message. */ fbuf->msgbase = fbuf->cp - 16; return TRUE; } /** * fBufSkipCurrentSet * * * * * */ static void fBufSkipCurrentSet( fBuf_t *fbuf) { if (fbuf->setbase) { fbuf->cp += FB_REM_SET(fbuf); fbuf->setbase = NULL; fbuf->sep = NULL; } } /** * fBufNextSetHeader * * * * * */ static gboolean fBufNextSetHeader( fBuf_t *fbuf, GError **err) { uint16_t set_id, setlen; /* May loop over sets if we're missing templates */ while (1) { /* Make sure we have at least a set header */ FB_CHECK_AVAIL("reading set header", 4); #if FB_DEBUG_RD fBufDebugBuffer("rset", fbuf, 4, FALSE); #endif /* Read set ID */ FB_NEXT_U16(set_id); /* Read set length */ FB_NEXT_U16(setlen); /* Verify set length is legal */ if (setlen < 4) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Set length %hu", setlen); return FALSE; } /* Verify set body fits in the message */ FB_CHECK_AVAIL("checking set length", setlen - 4); /* Set up special set ID or external templates */ if (set_id < FB_TID_MIN_DATA) { if ((set_id != FB_TID_TS) && (set_id != FB_TID_OTS)) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Set ID %04hx", set_id); return FALSE; } fbuf->spec_tid = set_id; } else if (!fbuf->ext_tmpl || fbuf->ext_tid != set_id) { fbuf->spec_tid = 0; fbuf->ext_tid = set_id; fbuf->ext_tmpl = fbSessionGetTemplate(fbuf->session, FALSE, set_id, err); if (!fbuf->ext_tmpl) { if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) { /* Merely warn and skip on missing templates */ g_warning("Skipping set: %s", (*err)->message); g_clear_error(err); fbuf->setbase = fbuf->cp - 4; fbuf->sep = fbuf->setbase + setlen; fBufSkipCurrentSet(fbuf); continue; } } } /* * We successfully read a set header. * Set set base and end pointers. */ fbuf->setbase = fbuf->cp - 4; fbuf->sep = fbuf->setbase + setlen; return TRUE; } } /** * fBufConsumeTemplateSet * * * * * */ static gboolean fBufConsumeTemplateSet( fBuf_t *fbuf, GError **err) { uint16_t mtl, tid, ie_count, scope_count; fbTemplate_t *tmpl; fbInfoElement_t ex_ie = FB_IE_NULL; int i; /* Calculate minimum template record length based on type */ /* FIXME handle revocation sets */ mtl = (fbuf->spec_tid == FB_TID_OTS) ? 6 : 4; /* Keep reading until the set contains only padding. */ while (FB_REM_SET(fbuf) >= mtl) { /* Read template ID */ FB_NEXT_U16(tid); /* Read template IE count */ FB_NEXT_U16(ie_count); /* Read scope count if present */ if (fbuf->spec_tid == FB_TID_OTS) { FB_NEXT_U16(scope_count); /* Check for illegal scope count */ if (scope_count == 0) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Options Template Scope Count 0"); return FALSE; } else if (scope_count > ie_count) { g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IPFIX, "Illegal IPFIX Options Template Scope Count " "(scope count %hu, element count %hu)", scope_count, ie_count); return FALSE; } } else { scope_count = 0; } /* Allocate a new template */ tmpl = fbTemplateAlloc(fbSessionGetInfoModel(fbuf->session)); /* Add information elements to the template */ for (i = 0; i < ie_count; i++) { /* Read information element specifier from buffer */ FB_NEXT_U16(ex_ie.num); FB_NEXT_U16(ex_ie.len); if (ex_ie.num & IPFIX_ENTERPRISE_BIT) { ex_ie.num &= ~IPFIX_ENTERPRISE_BIT; FB_NEXT_U32(ex_ie.ent); } else { ex_ie.ent = 0; } /* Add information element to template */ if (!fbTemplateAppend(tmpl, &ex_ie, err)) return FALSE; } /* Set scope count in template */ if (scope_count) { fbTemplateSetOptionsScope(tmpl, scope_count); } /* Add template to session */ if (!fbSessionAddTemplate(fbuf->session, FALSE, tid, tmpl, err)) { return FALSE; } /* callback (fbuf->session, tid, tmpl) */ if (fbSessionTemplateCallback(fbuf->session)) { (fbSessionTemplateCallback(fbuf->session))(fbuf->session, tid, tmpl); } if (fbSessionTemplateCtxCallback(fbuf->session)) { g_assert(tmpl->app_ctx == NULL); (fbSessionTemplateCtxCallback(fbuf->session))( fbuf->session, tid, tmpl, fbSessionTemplateCtxCallbackAppCtx(fbuf->session), &(tmpl->tmpl_ctx), &(tmpl->ctx_free)); if (NULL == tmpl->app_ctx) { /* tmpl->app_ctx will not be NULL only if set by * fbSessionTemplateCallbackWrapper() */ tmpl->app_ctx = fbSessionTemplateCtxCallbackAppCtx(fbuf->session); } } /* if the template set on the fbuf has the same tid, reset tmpl */ /* so we don't reference the old one if a data set follows */ if (fbuf->ext_tid == tid) { fbuf->ext_tmpl = NULL; fbuf->ext_tid = 0; } #if FB_DEBUG_RD fBufDebugBuffer("rtpl", fbuf, tmpl->tmpl_len, TRUE); #endif } /* Skip any padding at the end of the set */ fBufSkipCurrentSet(fbuf); /* Should set spec_tid to 0 so if next set is data */ fbuf->spec_tid = 0; /* All done */ return TRUE; } static gboolean fBufConsumeInfoElementTypeRecord( fBuf_t *fbuf, GError **err) { fbInfoElementOptRec_t rec; size_t len = sizeof(fbInfoElementOptRec_t); uint16_t tid = fbuf->int_tid; size_t bufsize; if (!fBufSetInternalTemplate(fbuf, fbuf->auto_insert_tid, err)) { return FALSE; } /* Keep reading until the set contains only padding. */ while (FB_REM_SET(fbuf) >= fbuf->int_tmpl->tmpl_len) { /* Transcode bytes out of buffer */ bufsize = FB_REM_SET(fbuf); if (!fbTranscode(fbuf, TRUE, fbuf->cp, (uint8_t *)&rec, &bufsize, &len, err)) { return FALSE; } if (!fbInfoElementAddOptRecElement(fbuf->int_tmpl->model, &rec)) { return FALSE; } /* Advance current record pointer by bytes read */ fbuf->cp += bufsize; /* Increment record count */ ++(fbuf->rc); } if (tid ) { if (!fBufSetInternalTemplate(fbuf, tid, err)) { return FALSE; } } else { fbuf->int_tid = tid; fbuf->int_tmpl = NULL; } return TRUE; } /** * fBufNextDataSet * * * * * */ static gboolean fBufNextDataSet( fBuf_t *fbuf, GError **err) { /* May have to consume multiple template sets */ while (1) { /* Read the next set header */ if (!fBufNextSetHeader(fbuf, err)) { return FALSE; } /* Check to see if we need to consume a template set */ if (fbuf->spec_tid) { if (!fBufConsumeTemplateSet(fbuf, err)) { return FALSE; } continue; } if (fbuf->auto_insert_tid) { if (fbTemplateGetOptionsScope(fbuf->ext_tmpl)) { if (fbInfoModelTypeInfoRecord(fbuf->ext_tmpl)) { if (!fBufConsumeInfoElementTypeRecord(fbuf, err)) { return FALSE; } continue; } } } /* All done. */ return TRUE; } } /** * fBufGetCollectionTemplate * * * * * */ fbTemplate_t *fBufGetCollectionTemplate( fBuf_t *fbuf, uint16_t *ext_tid) { if (fbuf->ext_tmpl) { if (ext_tid) *ext_tid = fbuf->ext_tid; } return fbuf->ext_tmpl; } /** * fBufNextCollectionTemplateSingle * * * * * */ static fbTemplate_t *fBufNextCollectionTemplateSingle( fBuf_t *fbuf, uint16_t *ext_tid, GError **err) { /* Read a new message if necessary */ if (!fbuf->msgbase) { if (!fBufNextMessage(fbuf, err)) { return FALSE; } } /* Skip any padding at end of current data set */ if (fbuf->setbase && (FB_REM_SET(fbuf) < fbuf->ext_tmpl->ie_len)) { fBufSkipCurrentSet(fbuf); } /* Advance to the next data set if necessary */ if (!fbuf->setbase) { if (!fBufNextDataSet(fbuf, err)) { return FALSE; } } return fBufGetCollectionTemplate(fbuf, ext_tid); } /** * fBufNextCollectionTemplate * * * * * */ fbTemplate_t *fBufNextCollectionTemplate( fBuf_t *fbuf, uint16_t *ext_tid, GError **err) { fbTemplate_t *tmpl; while (1) { /* Attempt single record read */ if ((tmpl = fBufNextCollectionTemplateSingle(fbuf, ext_tid, err))) return tmpl; /* Finish the message at EOM */ if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_EOM)) { /* Store next expected sequence number */ #if HAVE_SPREAD /* Only worry about sequence numbers for first group in list * of received groups & only if we subscribe to that group*/ if (fbCollectorTestGroupMembership(fbuf->collector, 0)) { #endif fbSessionSetSequence(fbuf->session, fbSessionGetSequence(fbuf->session) + fbuf->rc); #if HAVE_SPREAD } #endif /* Rewind buffer to force next record read to consume a new message. */ fBufRewind(fbuf); /* Clear error and try again in automatic mode */ if (fbuf->automatic) { g_clear_error(err); continue; } } /* Error. Not EOM or not retryable. Fail. */ return NULL; } } /** * fBufNextSingle * * * * * */ static gboolean fBufNextSingle( fBuf_t *fbuf, uint8_t *recbase, size_t *recsize, GError **err) { size_t bufsize; /* Buffer must have active internal template */ g_assert(fbuf->int_tmpl); /* Read a new message if necessary */ if (!fbuf->msgbase) { if (!fBufNextMessage(fbuf, err)) { return FALSE; } } /* Skip any padding at end of current data set */ if (fbuf->setbase && (FB_REM_SET(fbuf) < fbuf->ext_tmpl->ie_len)) { fBufSkipCurrentSet(fbuf); } /* Advance to the next data set if necessary */ if (!fbuf->setbase) { if (!fBufNextDataSet(fbuf, err)) { return FALSE; } } /* Transcode bytes out of buffer */ bufsize = FB_REM_SET(fbuf); if (!fbTranscode(fbuf, TRUE, fbuf->cp, recbase, &bufsize, recsize, err)) { return FALSE; } /* Advance current record pointer by bytes read */ fbuf->cp += bufsize; /* Increment record count */ ++(fbuf->rc); #if FB_DEBUG_RD fBufDebugBuffer("rrec", fbuf, bufsize, TRUE); #endif /* Done */ return TRUE; } /** * fBufNext * * * * * */ gboolean fBufNext( fBuf_t *fbuf, uint8_t *recbase, size_t *recsize, GError **err) { while (1) { /* Attempt single record read */ if (fBufNextSingle(fbuf, recbase, recsize, err)) return TRUE; /* Finish the message at EOM */ if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_EOM)) { #if HAVE_SPREAD /* Only worry about sequence numbers for first group in list * of received groups & only if we subscribe to that group*/ if (fbCollectorTestGroupMembership(fbuf->collector, 0)) { #endif /* Store next expected sequence number */ fbSessionSetSequence(fbuf->session, fbSessionGetSequence(fbuf->session) + fbuf->rc); #if HAVE_SPREAD } #endif /* Rewind buffer to force next record read to consume a new message. */ fBufRewind(fbuf); /* Clear error and try again in automatic mode */ if (fbuf->automatic) { g_clear_error(err); continue; } } /* Error. Not EOM or not retryable. Fail. */ return FALSE; } } /* * * fBufRemaining * */ size_t fBufRemaining( fBuf_t *fbuf) { return fbuf->buflen; } /** * fBufSetBuffer * * */ void fBufSetBuffer( fBuf_t *fbuf, uint8_t *buf, size_t buflen) { /* not sure if this is necessary, but if these are not null, the appropriate code will not execute*/ fbuf->collector = NULL; fbuf->exporter = NULL; fbuf->cp = buf; fbuf->mep = fbuf->cp; fbuf->buflen = buflen; } /** * fBufGetCollector * * * * * */ fbCollector_t *fBufGetCollector( fBuf_t *fbuf) { return fbuf->collector; } /** * fBufSetCollector * * * * * */ void fBufSetCollector( fBuf_t *fbuf, fbCollector_t *collector) { if (fbuf->exporter) { fbSessionSetTemplateBuffer(fbuf->session, NULL); fbExporterFree(fbuf->exporter); fbuf->exporter = NULL; } if (fbuf->collector) { fbCollectorFree(fbuf->collector); } fbuf->collector = collector; fbSessionSetTemplateBuffer(fbuf->session, fbuf); fBufRewind(fbuf); } /** * fBufAllocForCollection * * * * * */ fBuf_t *fBufAllocForCollection( fbSession_t *session, fbCollector_t *collector) { fBuf_t *fbuf = NULL; /* Allocate a new buffer */ fbuf = g_slice_new0(fBuf_t); /* Store reference to session */ fbuf->session = session; fbSessionSetCollector(session, collector); /* Set up collection */ fBufSetCollector(fbuf, collector); /* Buffers are automatic by default */ fbuf->automatic = TRUE; return fbuf; } /** * fBufSetSession * */ void fBufSetSession( fBuf_t *fbuf, fbSession_t *session) { fbuf->session = session; } /** * fBufGetExportTime * */ uint32_t fBufGetExportTime( fBuf_t *fbuf) { return fbuf->extime; } void fBufInterruptSocket( fBuf_t *fbuf) { fbCollectorInterruptSocket(fbuf->collector); } gboolean fbListValidSemantic( uint8_t semantic) { if (semantic <= 0x04 || semantic == 0xFF) { return TRUE; } return FALSE; } fbBasicList_t* fbBasicListAlloc( void) { fbBasicList_t *bl; bl = (fbBasicList_t*)g_slice_alloc0(sizeof(fbBasicList_t)); return bl; } void* fbBasicListInit( fbBasicList_t *basicList, uint8_t semantic, const fbInfoElement_t *infoElement, uint16_t numElements) { uint16_t ie_num; basicList->semantic = semantic; basicList->infoElement = infoElement; if (!infoElement) { return NULL; } basicList->numElements = numElements; basicList->dataLength = numElements * infoElement->len; if (infoElement->len == FB_IE_VARLEN) { ie_num = infoElement->num; if (ie_num == FB_IE_BASIC_LIST) { basicList->dataLength = numElements * sizeof(fbBasicList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_LIST) { basicList->dataLength = numElements * sizeof(fbSubTemplateList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_MULTILIST) { basicList->dataLength = numElements * sizeof(fbSubTemplateMultiList_t); } else { basicList->dataLength = numElements * sizeof(fbVarfield_t); } } basicList->dataPtr = g_slice_alloc0(basicList->dataLength); return (void*)basicList->dataPtr; } void *fbBasicListInitWithOwnBuffer( fbBasicList_t *basicListPtr, uint8_t semantic, const fbInfoElement_t *infoElement, uint16_t numElements, uint16_t dataLength, uint8_t *dataPtr) { basicListPtr->semantic = semantic; basicListPtr->infoElement = infoElement; basicListPtr->numElements = numElements; basicListPtr->dataLength = dataLength; basicListPtr->dataPtr = dataPtr; return basicListPtr->dataPtr; } void fbBasicListCollectorInit( fbBasicList_t *BL) { BL->semantic = 0; BL->infoElement = NULL; BL->dataPtr = NULL; BL->numElements = 0; BL->dataLength = 0; } uint8_t fbBasicListGetSemantic( fbBasicList_t *basicListPtr) { return basicListPtr->semantic; } const fbInfoElement_t *fbBasicListGetInfoElement( fbBasicList_t *basicListPtr) { return basicListPtr->infoElement; } void *fbBasicListGetDataPtr( fbBasicList_t *basicListPtr) { return (void*)basicListPtr->dataPtr; } void *fbBasicListGetIndexedDataPtr( fbBasicList_t *basicList, uint16_t bl_index) { uint16_t ie_len; uint16_t ie_num; if (bl_index >= basicList->numElements) { return NULL; } ie_len = basicList->infoElement->len; if (ie_len == FB_IE_VARLEN) { ie_num = basicList->infoElement->num; if (ie_num == FB_IE_BASIC_LIST) { return basicList->dataPtr + (bl_index * sizeof(fbBasicList_t)); } else if (ie_num == FB_IE_SUBTEMPLATE_LIST) { return basicList->dataPtr +(bl_index *sizeof(fbSubTemplateList_t)); } else if (ie_num == FB_IE_SUBTEMPLATE_MULTILIST) { return basicList->dataPtr + (bl_index * sizeof(fbSubTemplateMultiList_t)); } else { return basicList->dataPtr + (bl_index * sizeof(fbVarfield_t)); } } return basicList->dataPtr + (bl_index * ie_len); } void *fbBasicListGetNextPtr( fbBasicList_t *basicList, void *curPtr) { uint16_t ie_len; uint16_t ie_num; uint8_t *currentPtr = curPtr; if (!currentPtr) { return basicList->dataPtr; } ie_len = basicList->infoElement->len; if (ie_len == FB_IE_VARLEN) { ie_num = basicList->infoElement->num; if (ie_num == FB_IE_BASIC_LIST) { ie_len = sizeof(fbBasicList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_LIST) { ie_len = sizeof(fbSubTemplateList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_MULTILIST) { ie_len = sizeof(fbSubTemplateMultiList_t); } else { ie_len = sizeof(fbVarfield_t); } } currentPtr += ie_len; if (((currentPtr - basicList->dataPtr) / ie_len) >= basicList->numElements) { return NULL; } return (void*)currentPtr; } void fbBasicListSetSemantic( fbBasicList_t *basicListPtr, uint8_t semantic) { basicListPtr->semantic = semantic; } void *fbBasicListRealloc( fbBasicList_t *basicList, uint16_t newNumElements) { if (newNumElements == basicList->numElements) { return basicList->dataPtr; } g_slice_free1(basicList->dataLength, basicList->dataPtr); return fbBasicListInit(basicList, basicList->semantic, basicList->infoElement, newNumElements); } void* fbBasicListAddNewElements( fbBasicList_t *basicList, uint16_t numNewElements) { uint8_t *newDataPtr; uint16_t dataLength = 0; uint16_t numElements = basicList->numElements + numNewElements; uint16_t ie_num; const fbInfoElement_t *infoElement = basicList->infoElement; uint16_t offset = basicList->dataLength; if (infoElement->len == FB_IE_VARLEN) { ie_num = infoElement->num; if (ie_num == FB_IE_BASIC_LIST) { dataLength = numElements * sizeof(fbBasicList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_LIST) { dataLength = numElements * sizeof(fbSubTemplateList_t); } else if (ie_num == FB_IE_SUBTEMPLATE_MULTILIST) { dataLength = numElements * sizeof(fbSubTemplateMultiList_t); } else { dataLength = numElements * sizeof(fbVarfield_t); } } else { dataLength = numElements * infoElement->len; } newDataPtr = g_slice_alloc0(dataLength); if (basicList->dataPtr) { memcpy(newDataPtr, basicList->dataPtr, basicList->dataLength); g_slice_free1(basicList->dataLength, basicList->dataPtr); } basicList->numElements = numElements; basicList->dataPtr = newDataPtr; basicList->dataLength = dataLength; return basicList->dataPtr + offset; } void fbBasicListClear( fbBasicList_t *basicList) { basicList->semantic = 0; basicList->infoElement = NULL; basicList->numElements = 0; g_slice_free1(basicList->dataLength, basicList->dataPtr); basicList->dataLength = 0; basicList->dataPtr = NULL; } void fbBasicListClearWithoutFree( fbBasicList_t *basicList) { basicList->semantic = 0; basicList->infoElement = NULL; basicList->numElements = 0; } void fbBasicListFree( fbBasicList_t *basicList) { fbBasicListClear(basicList); g_slice_free1(sizeof(fbBasicList_t), basicList); } fbSubTemplateList_t* fbSubTemplateListAlloc( void) { fbSubTemplateList_t *stl; stl = (fbSubTemplateList_t*)g_slice_alloc0(sizeof(fbSubTemplateList_t)); return stl; } void* fbSubTemplateListInit( fbSubTemplateList_t *subTemplateList, uint8_t semantic, uint16_t tmplID, const fbTemplate_t *tmpl, uint16_t numElements) { subTemplateList->semantic = semantic; subTemplateList->tmplID = tmplID; subTemplateList->numElements = numElements; subTemplateList->tmpl = tmpl; if (!tmpl) { return NULL; } subTemplateList->dataLength.length = numElements * tmpl->ie_internal_len; subTemplateList->dataPtr = g_slice_alloc0(subTemplateList->dataLength.length); return (void*)subTemplateList->dataPtr; } void* fbSubTemplateListInitWithOwnBuffer( fbSubTemplateList_t *subTemplateList, uint8_t semantic, uint16_t tmplID, const fbTemplate_t *tmpl, uint16_t numElements, uint16_t dataLength, uint8_t *dataPtr) { subTemplateList->semantic = semantic; subTemplateList->tmplID = tmplID; subTemplateList->numElements = numElements; subTemplateList->tmpl = tmpl; subTemplateList->dataLength.length = dataLength; subTemplateList->dataPtr = dataPtr; return (void*)subTemplateList->dataPtr; } void fbSubTemplateListCollectorInit( fbSubTemplateList_t *STL) { STL->semantic = 0; STL->numElements = 0; STL->dataLength.length = 0; STL->tmplID = 0; STL->tmpl = NULL; STL->dataPtr = NULL; } void fbSubTemplateListClear( fbSubTemplateList_t *subTemplateList) { subTemplateList->semantic = 0; subTemplateList->numElements = 0; subTemplateList->tmplID = 0; subTemplateList->tmpl = NULL; if (subTemplateList->dataLength.length) { g_slice_free1(subTemplateList->dataLength.length, subTemplateList->dataPtr); } subTemplateList->dataPtr = NULL; subTemplateList->dataLength.length = 0; } void fbSubTemplateListFree( fbSubTemplateList_t *subTemplateList) { fbSubTemplateListClear(subTemplateList); g_slice_free1(sizeof(fbSubTemplateList_t), subTemplateList); } void fbSubTemplateListClearWithoutFree( fbSubTemplateList_t *subTemplateList) { subTemplateList->semantic = 0; subTemplateList->tmplID = 0; subTemplateList->tmpl = NULL; subTemplateList->numElements = 0; } void* fbSubTemplateListGetDataPtr( const fbSubTemplateList_t *sTL) { return sTL->dataPtr; } /* index is 0-based. Goes from 0 - (numElements-1) */ void* fbSubTemplateListGetIndexedDataPtr( const fbSubTemplateList_t *sTL, uint16_t stlIndex) { if (stlIndex >= sTL->numElements) { return NULL; } return ((uint8_t*)(sTL->dataPtr) + stlIndex * sTL->tmpl->ie_internal_len); } void* fbSubTemplateListGetNextPtr( const fbSubTemplateList_t *sTL, void *curPtr) { uint16_t tmplLen; uint8_t *currentPtr = curPtr; if (!currentPtr) { return sTL->dataPtr; } tmplLen = sTL->tmpl->ie_internal_len; currentPtr += tmplLen; if (((currentPtr - sTL->dataPtr) / tmplLen) >= sTL->numElements) { return NULL; } return (void*)currentPtr; } void fbSubTemplateListSetSemantic( fbSubTemplateList_t *sTL, uint8_t semantic) { sTL->semantic = semantic; } uint8_t fbSubTemplateListGetSemantic( fbSubTemplateList_t *STL) { return STL->semantic; } const fbTemplate_t* fbSubTemplateListGetTemplate( fbSubTemplateList_t *STL) { return STL->tmpl; } uint16_t fbSubTemplateListGetTemplateID( fbSubTemplateList_t *STL) { return STL->tmplID; } void* fbSubTemplateListRealloc( fbSubTemplateList_t *subTemplateList, uint16_t newNumElements) { if (newNumElements == subTemplateList->numElements) { return subTemplateList->dataPtr; } g_slice_free1(subTemplateList->dataLength.length, subTemplateList->dataPtr); subTemplateList->numElements = newNumElements; subTemplateList->dataLength.length = subTemplateList->numElements * subTemplateList->tmpl->ie_internal_len; subTemplateList->dataPtr = g_slice_alloc0(subTemplateList->dataLength.length); return subTemplateList->dataPtr; } void* fbSubTemplateListAddNewElements( fbSubTemplateList_t *sTL, uint16_t numNewElements) { uint16_t offset = sTL->dataLength.length; uint16_t numElements = sTL->numElements + numNewElements; uint8_t *newDataPtr = NULL; uint16_t dataLength = 0; dataLength = numElements * sTL->tmpl->ie_internal_len; newDataPtr = g_slice_alloc0(dataLength); if (sTL->dataPtr) { memcpy(newDataPtr, sTL->dataPtr, sTL->dataLength.length); g_slice_free1(sTL->dataLength.length, sTL->dataPtr); } sTL->numElements = numElements; sTL->dataPtr = newDataPtr; sTL->dataLength.length = dataLength; return sTL->dataPtr + offset; } fbSubTemplateMultiList_t* fbSubTemplateMultiListAlloc( void) { fbSubTemplateMultiList_t *stml; stml = (fbSubTemplateMultiList_t*)g_slice_alloc0(sizeof(fbSubTemplateMultiList_t)); return stml; } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListInit( fbSubTemplateMultiList_t *sTML, uint8_t semantic, uint16_t numElements) { sTML->semantic = semantic; sTML->numElements = numElements; sTML->firstEntry = g_slice_alloc0(sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t)); return sTML->firstEntry; } void fbSubTemplateMultiListSetSemantic( fbSubTemplateMultiList_t *STML, uint8_t semantic) { STML->semantic = semantic; } uint8_t fbSubTemplateMultiListGetSemantic( fbSubTemplateMultiList_t *STML) { return STML->semantic; } void fbSubTemplateMultiListClear( fbSubTemplateMultiList_t *sTML) { fbSubTemplateMultiListClearEntries(sTML); g_slice_free1(sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t), sTML->firstEntry); sTML->numElements = 0; sTML->firstEntry = NULL; } void fbSubTemplateMultiListClearEntries( fbSubTemplateMultiList_t *sTML) { fbSubTemplateMultiListEntry_t *entry = NULL; while ((entry = fbSubTemplateMultiListGetNextEntry(sTML, entry))) { fbSubTemplateMultiListEntryClear(entry); } } void fbSubTemplateMultiListFree( fbSubTemplateMultiList_t *sTML) { fbSubTemplateMultiListClear(sTML); g_slice_free1(sizeof(fbSubTemplateMultiList_t), sTML); } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListRealloc( fbSubTemplateMultiList_t *sTML, uint16_t newNumElements) { fbSubTemplateMultiListClearEntries(sTML); if (newNumElements != sTML->numElements) { g_slice_free1(sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t), sTML->firstEntry); sTML->numElements = newNumElements; sTML->firstEntry = g_slice_alloc0(sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t)); } return sTML->firstEntry; } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListAddNewEntries( fbSubTemplateMultiList_t *sTML, uint16_t numNewEntries) { fbSubTemplateMultiListEntry_t *newFirstEntry; uint16_t newNumElements = sTML->numElements + numNewEntries; uint16_t oldNumElements = sTML->numElements; newFirstEntry = g_slice_alloc0(newNumElements * sizeof(fbSubTemplateMultiListEntry_t)); if (sTML->firstEntry) { memcpy(newFirstEntry, sTML->firstEntry, (sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t))); g_slice_free1(sTML->numElements * sizeof(fbSubTemplateMultiListEntry_t), sTML->firstEntry); } sTML->numElements = newNumElements; sTML->firstEntry = newFirstEntry; return sTML->firstEntry + oldNumElements; } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetFirstEntry( fbSubTemplateMultiList_t *sTML) { return sTML->firstEntry; } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetIndexedEntry( fbSubTemplateMultiList_t *sTML, uint16_t stmlIndex) { if (stmlIndex >= sTML->numElements) { return NULL; } return sTML->firstEntry + stmlIndex; } fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetNextEntry( fbSubTemplateMultiList_t *sTML, fbSubTemplateMultiListEntry_t *currentEntry) { if (!currentEntry) { return sTML->firstEntry; } currentEntry++; if ((uint16_t)(currentEntry - sTML->firstEntry) >= sTML->numElements) { return NULL; } return currentEntry; } void fbSubTemplateMultiListEntryClear( fbSubTemplateMultiListEntry_t *entry) { g_slice_free1(entry->dataLength, entry->dataPtr); entry->dataLength = 0; entry->dataPtr = NULL; } void* fbSubTemplateMultiListEntryGetDataPtr( fbSubTemplateMultiListEntry_t *entry) { return entry->dataPtr; } void* fbSubTemplateMultiListEntryInit( fbSubTemplateMultiListEntry_t *entry, uint16_t tmplID, fbTemplate_t *tmpl, uint16_t numElements) { entry->tmplID = tmplID; entry->tmpl = tmpl; if (!tmpl) { return NULL; } entry->numElements = numElements; entry->dataLength = tmpl->ie_internal_len * numElements; entry->dataPtr = g_slice_alloc0(entry->dataLength); return entry->dataPtr; } const fbTemplate_t* fbSubTemplateMultiListEntryGetTemplate( fbSubTemplateMultiListEntry_t *entry) { return entry->tmpl; } uint16_t fbSubTemplateMultiListEntryGetTemplateID( fbSubTemplateMultiListEntry_t *entry) { return entry->tmplID; } void *fbSubTemplateMultiListEntryRealloc( fbSubTemplateMultiListEntry_t *entry, uint16_t newNumElements) { if (newNumElements == entry->numElements) { return entry->dataPtr; } g_slice_free1(entry->dataLength, entry->dataPtr); entry->numElements = newNumElements; entry->dataLength = newNumElements * entry->tmpl->ie_internal_len; entry->dataPtr = g_slice_alloc0(entry->dataLength); return entry->dataPtr; } void* fbSubTemplateMultiListEntryAddNewElements( fbSubTemplateMultiListEntry_t *entry, uint16_t numNewElements) { uint16_t offset = entry->dataLength; uint16_t numElements = entry->numElements + numNewElements; uint8_t *newDataPtr; uint16_t dataLength; dataLength = numElements * entry->tmpl->ie_internal_len; newDataPtr = g_slice_alloc0(dataLength); if (entry->dataPtr) { memcpy(newDataPtr, entry->dataPtr, entry->dataLength); g_slice_free1(entry->dataLength, entry->dataPtr); } entry->numElements = numElements; entry->dataPtr = newDataPtr; entry->dataLength = dataLength; return entry->dataPtr + offset; } void* fbSubTemplateMultiListEntryNextDataPtr( fbSubTemplateMultiListEntry_t *entry, void *curPtr) { uint16_t tmplLen; uint8_t *currentPtr = curPtr; if (!currentPtr) { return entry->dataPtr; } tmplLen = entry->tmpl->ie_internal_len; currentPtr += tmplLen; if ((uint16_t)(currentPtr - entry->dataPtr) >= entry->dataLength) { return NULL; } return (void*)currentPtr; } void* fbSubTemplateMultiListEntryGetIndexedPtr( fbSubTemplateMultiListEntry_t *entry, uint16_t stmleIndex) { if (stmleIndex >= entry->numElements) { return NULL; } return ((uint8_t*)(entry->dataPtr) + (stmleIndex * entry->tmpl->ie_internal_len)); } /** * fBufSTMLEntryRecordFree * * Free all records within the STMLEntry * */ static void fBufSTMLEntryRecordFree( fbSubTemplateMultiListEntry_t *entry) { uint8_t *data = NULL; while ((data = fbSubTemplateMultiListEntryNextDataPtr(entry, data))) { fBufListFree(entry->tmpl, data); } } /** * fBufSTMLRecordFree * * Access each entry in the STML and free the records in each * entry. * */ static void fBufSTMLRecordFree( uint8_t *record) { fbSubTemplateMultiList_t *stml = (fbSubTemplateMultiList_t *)record; fbSubTemplateMultiListEntry_t *entry = NULL; int i = 0; while ((entry = fbSubTemplateMultiListGetNextEntry(stml, entry))) { /*something */ fBufSTMLEntryRecordFree(entry); i++; } } /** * fBufSTLRecordFree * * Free all records within the subTemplateList * */ static void fBufSTLRecordFree( uint8_t *record) { fbSubTemplateList_t *stl = (fbSubTemplateList_t *)record; uint8_t *data = NULL; while ((data = fbSubTemplateListGetNextPtr(stl, data))) { fBufListFree((fbTemplate_t *)(stl->tmpl), data); } } /** * fBufBLRecordFree * * Free any list elements nested within a basicList * */ static void fBufBLRecordFree( fbBasicList_t *bl) { uint8_t *data = NULL; while ((data = fbBasicListGetNextPtr(bl, data))) { if (bl->infoElement->num == FB_IE_SUBTEMPLATE_MULTILIST) { fBufSTMLRecordFree(data); fbSubTemplateMultiListClear((fbSubTemplateMultiList_t *)(data)); } else if (bl->infoElement->num == FB_IE_SUBTEMPLATE_LIST) { fBufSTLRecordFree(data); fbSubTemplateListClear((fbSubTemplateList_t *)(data)); } else if (bl->infoElement->num == FB_IE_BASIC_LIST) { fBufBLRecordFree((fbBasicList_t *)data); fbBasicListClear((fbBasicList_t *)(data)); } } } /** * fBufListFree * * This frees any list information elements that were allocated * either by fixbuf or the application during encode or decode. * * The template provided is the internal template and MUST match * the record exactly, or bad things will happen. * There is no way to check that the user is doing the right * thing. */ void fBufListFree( fbTemplate_t *template, uint8_t *record) { uint32_t i; fbInfoElement_t *ie = NULL; uint16_t buf_walk = 0; uint32_t count = fbTemplateCountElements(template); if (!template->is_varlen) { /* no variable length fields in this template */ return; } for (i = 0; i < count; i++) { ie = fbTemplateGetIndexedIE(template, i); if (ie->len != 65535) { buf_walk += ie->len; } else if (ie->num == FB_IE_SUBTEMPLATE_MULTILIST) { fBufSTMLRecordFree(record+buf_walk); fbSubTemplateMultiListClear((fbSubTemplateMultiList_t *)(record+buf_walk)); buf_walk += sizeof(fbSubTemplateMultiList_t); } else if (ie->num == FB_IE_SUBTEMPLATE_LIST) { fBufSTLRecordFree(record+buf_walk); fbSubTemplateListClear((fbSubTemplateList_t *)(record + buf_walk)); buf_walk += sizeof(fbSubTemplateList_t); } else if (ie->num == FB_IE_BASIC_LIST) { fBufBLRecordFree((fbBasicList_t *)(record+buf_walk)); fbBasicListClear((fbBasicList_t *)(record + buf_walk)); buf_walk += sizeof(fbBasicList_t); } else { /* variable length */ buf_walk += sizeof(fbVarfield_t); } } } libfixbuf-1.7.1/src/Makefile.am000644 000770 000024 00000002332 12545036674 020645 0ustar00emilyecoffmessagebus000000 000000 ## Process this file with automake to produce Makefile.in ## ------------------------------------------------------------------------ ## Makefile.am (source) ## autotools build system for libfixbuf ## ------------------------------------------------------------------------ ## Copyright (C) 2005-2015 Carnegie Mellon University. All Rights Reserved. ## ------------------------------------------------------------------------ ## Authors: Brian Trammell ## ------------------------------------------------------------------------ ## GNU Lesser GPL Rights pursuant to Version 2.1, February 1999 ## Government Purpose License Rights (GPLR) pursuant to DFARS 252.227-7013 ## ------------------------------------------------------------------------ lib_LTLIBRARIES = libfixbuf.la WARN_CFLAGS = -g -DDEBUG -Wall libfixbuf_la_SOURCES = fbuf.c fbinfomodel.c fbtemplate.c fbsession.c \ fbconnspec.c fbexporter.c fbcollector.c fblistener.c \ fbnetflow.c fbsflow.c libfixbuf_la_LIBADD = $(GLIB_LDADD) libfixbuf_la_LDFLAGS = $(SPREAD_LDFLAGS) $(SPREAD_LIBS) $(GLIB_LIBS) -version-info $(LIBCOMPAT) libfixbuf_la_CFLAGS = $(WARN_CFLAGS) $(DEBUG_CFLAGS) $(SPREAD_CFLAGS) $(GLIB_CFLAGS) noinst_HEADERS = fbcollector.h libfixbuf-1.7.1/src/Makefile.in000644 000770 000024 00000101733 12605776213 020660 0ustar00emilyecoffmessagebus000000 000000 # Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/autoconf/depcomp $(noinst_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ $(top_srcdir)/m4/ax_check_aligned_access_required.m4 \ $(top_srcdir)/m4/ax_prog_doxygen.m4 $(top_srcdir)/m4/debug.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/spread.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/fixbuf/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libfixbuf_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libfixbuf_la_OBJECTS = libfixbuf_la-fbuf.lo \ libfixbuf_la-fbinfomodel.lo libfixbuf_la-fbtemplate.lo \ libfixbuf_la-fbsession.lo libfixbuf_la-fbconnspec.lo \ libfixbuf_la-fbexporter.lo libfixbuf_la-fbcollector.lo \ libfixbuf_la-fblistener.lo libfixbuf_la-fbnetflow.lo \ libfixbuf_la-fbsflow.lo libfixbuf_la_OBJECTS = $(am_libfixbuf_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libfixbuf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libfixbuf_la_CFLAGS) \ $(CFLAGS) $(libfixbuf_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/fixbuf depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libfixbuf_la_SOURCES) DIST_SOURCES = $(libfixbuf_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUG_CFLAGS = @DEBUG_CFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DX_CONFIG = @DX_CONFIG@ DX_DOCDIR = @DX_DOCDIR@ DX_DOT = @DX_DOT@ DX_DOXYGEN = @DX_DOXYGEN@ DX_DVIPS = @DX_DVIPS@ DX_EGREP = @DX_EGREP@ DX_ENV = @DX_ENV@ DX_FLAG_chi = @DX_FLAG_chi@ DX_FLAG_chm = @DX_FLAG_chm@ DX_FLAG_doc = @DX_FLAG_doc@ DX_FLAG_dot = @DX_FLAG_dot@ DX_FLAG_html = @DX_FLAG_html@ DX_FLAG_man = @DX_FLAG_man@ DX_FLAG_pdf = @DX_FLAG_pdf@ DX_FLAG_ps = @DX_FLAG_ps@ DX_FLAG_rtf = @DX_FLAG_rtf@ DX_FLAG_xml = @DX_FLAG_xml@ DX_HHC = @DX_HHC@ DX_LATEX = @DX_LATEX@ DX_MAKEINDEX = @DX_MAKEINDEX@ DX_PDFLATEX = @DX_PDFLATEX@ DX_PERL = @DX_PERL@ DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIXBUF_REQ_LIBSCTP = @FIXBUF_REQ_LIBSCTP@ FIXBUF_REQ_LIBSPREAD = @FIXBUF_REQ_LIBSPREAD@ FIXBUF_REQ_LIBSSL = @FIXBUF_REQ_LIBSSL@ FIXBUF_REQ_SCTPDEV = @FIXBUF_REQ_SCTPDEV@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LDADD = @GLIB_LDADD@ GLIB_LIBS = @GLIB_LIBS@ GLIB_MKENUMS = @GLIB_MKENUMS@ GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCOMPAT = @LIBCOMPAT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPM_CONFIG_FLAGS = @RPM_CONFIG_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPREAD_CC_DEFINE = @SPREAD_CC_DEFINE@ SPREAD_CFLAGS = @SPREAD_CFLAGS@ SPREAD_LDFLAGS = @SPREAD_LDFLAGS@ SPREAD_LIBS = @SPREAD_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ lib_LTLIBRARIES = libfixbuf.la WARN_CFLAGS = -g -DDEBUG -Wall libfixbuf_la_SOURCES = fbuf.c fbinfomodel.c fbtemplate.c fbsession.c \ fbconnspec.c fbexporter.c fbcollector.c fblistener.c \ fbnetflow.c fbsflow.c libfixbuf_la_LIBADD = $(GLIB_LDADD) libfixbuf_la_LDFLAGS = $(SPREAD_LDFLAGS) $(SPREAD_LIBS) $(GLIB_LIBS) -version-info $(LIBCOMPAT) libfixbuf_la_CFLAGS = $(WARN_CFLAGS) $(DEBUG_CFLAGS) $(SPREAD_CFLAGS) $(GLIB_CFLAGS) noinst_HEADERS = fbcollector.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libfixbuf.la: $(libfixbuf_la_OBJECTS) $(libfixbuf_la_DEPENDENCIES) $(EXTRA_libfixbuf_la_DEPENDENCIES) $(AM_V_CCLD)$(libfixbuf_la_LINK) -rpath $(libdir) $(libfixbuf_la_OBJECTS) $(libfixbuf_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbcollector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbconnspec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbexporter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbinfomodel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fblistener.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbnetflow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbsession.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbsflow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbtemplate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfixbuf_la-fbuf.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libfixbuf_la-fbuf.lo: fbuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbuf.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbuf.Tpo -c -o libfixbuf_la-fbuf.lo `test -f 'fbuf.c' || echo '$(srcdir)/'`fbuf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbuf.Tpo $(DEPDIR)/libfixbuf_la-fbuf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbuf.c' object='libfixbuf_la-fbuf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbuf.lo `test -f 'fbuf.c' || echo '$(srcdir)/'`fbuf.c libfixbuf_la-fbinfomodel.lo: fbinfomodel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbinfomodel.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbinfomodel.Tpo -c -o libfixbuf_la-fbinfomodel.lo `test -f 'fbinfomodel.c' || echo '$(srcdir)/'`fbinfomodel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbinfomodel.Tpo $(DEPDIR)/libfixbuf_la-fbinfomodel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbinfomodel.c' object='libfixbuf_la-fbinfomodel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbinfomodel.lo `test -f 'fbinfomodel.c' || echo '$(srcdir)/'`fbinfomodel.c libfixbuf_la-fbtemplate.lo: fbtemplate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbtemplate.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbtemplate.Tpo -c -o libfixbuf_la-fbtemplate.lo `test -f 'fbtemplate.c' || echo '$(srcdir)/'`fbtemplate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbtemplate.Tpo $(DEPDIR)/libfixbuf_la-fbtemplate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbtemplate.c' object='libfixbuf_la-fbtemplate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbtemplate.lo `test -f 'fbtemplate.c' || echo '$(srcdir)/'`fbtemplate.c libfixbuf_la-fbsession.lo: fbsession.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbsession.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbsession.Tpo -c -o libfixbuf_la-fbsession.lo `test -f 'fbsession.c' || echo '$(srcdir)/'`fbsession.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbsession.Tpo $(DEPDIR)/libfixbuf_la-fbsession.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbsession.c' object='libfixbuf_la-fbsession.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbsession.lo `test -f 'fbsession.c' || echo '$(srcdir)/'`fbsession.c libfixbuf_la-fbconnspec.lo: fbconnspec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbconnspec.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbconnspec.Tpo -c -o libfixbuf_la-fbconnspec.lo `test -f 'fbconnspec.c' || echo '$(srcdir)/'`fbconnspec.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbconnspec.Tpo $(DEPDIR)/libfixbuf_la-fbconnspec.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbconnspec.c' object='libfixbuf_la-fbconnspec.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbconnspec.lo `test -f 'fbconnspec.c' || echo '$(srcdir)/'`fbconnspec.c libfixbuf_la-fbexporter.lo: fbexporter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbexporter.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbexporter.Tpo -c -o libfixbuf_la-fbexporter.lo `test -f 'fbexporter.c' || echo '$(srcdir)/'`fbexporter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbexporter.Tpo $(DEPDIR)/libfixbuf_la-fbexporter.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbexporter.c' object='libfixbuf_la-fbexporter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbexporter.lo `test -f 'fbexporter.c' || echo '$(srcdir)/'`fbexporter.c libfixbuf_la-fbcollector.lo: fbcollector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbcollector.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbcollector.Tpo -c -o libfixbuf_la-fbcollector.lo `test -f 'fbcollector.c' || echo '$(srcdir)/'`fbcollector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbcollector.Tpo $(DEPDIR)/libfixbuf_la-fbcollector.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbcollector.c' object='libfixbuf_la-fbcollector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbcollector.lo `test -f 'fbcollector.c' || echo '$(srcdir)/'`fbcollector.c libfixbuf_la-fblistener.lo: fblistener.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fblistener.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fblistener.Tpo -c -o libfixbuf_la-fblistener.lo `test -f 'fblistener.c' || echo '$(srcdir)/'`fblistener.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fblistener.Tpo $(DEPDIR)/libfixbuf_la-fblistener.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fblistener.c' object='libfixbuf_la-fblistener.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fblistener.lo `test -f 'fblistener.c' || echo '$(srcdir)/'`fblistener.c libfixbuf_la-fbnetflow.lo: fbnetflow.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbnetflow.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbnetflow.Tpo -c -o libfixbuf_la-fbnetflow.lo `test -f 'fbnetflow.c' || echo '$(srcdir)/'`fbnetflow.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbnetflow.Tpo $(DEPDIR)/libfixbuf_la-fbnetflow.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbnetflow.c' object='libfixbuf_la-fbnetflow.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbnetflow.lo `test -f 'fbnetflow.c' || echo '$(srcdir)/'`fbnetflow.c libfixbuf_la-fbsflow.lo: fbsflow.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -MT libfixbuf_la-fbsflow.lo -MD -MP -MF $(DEPDIR)/libfixbuf_la-fbsflow.Tpo -c -o libfixbuf_la-fbsflow.lo `test -f 'fbsflow.c' || echo '$(srcdir)/'`fbsflow.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfixbuf_la-fbsflow.Tpo $(DEPDIR)/libfixbuf_la-fbsflow.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fbsflow.c' object='libfixbuf_la-fbsflow.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfixbuf_la_CFLAGS) $(CFLAGS) -c -o libfixbuf_la-fbsflow.lo `test -f 'fbsflow.c' || echo '$(srcdir)/'`fbsflow.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libfixbuf-1.7.1/m4/ax_check_aligned_access_required.m4000644 000770 000024 00000006136 12412300776 025251 0ustar00emilyecoffmessagebus000000 000000 ##### http://autoconf-archive.cryp.to/ax_check_aligned_access_required.html # # SYNOPSIS # # AC_CHECK_ALIGNED_ACCESS_REQUIRED # # DESCRIPTION # # While the x86 CPUs allow access to memory objects to be unaligned # it happens that most of the modern designs require objects to be # aligned - or they will fail with a buserror. That mode is quite # known by big-endian machines (sparc, etc) however the alpha cpu is # little- endian. # # The following function will test for aligned access to be required # and set a config.h define HAVE_ALIGNED_ACCESS_REQUIRED (name # derived by standard usage). Structures loaded from a file (or # mmapped to memory) should be accessed per-byte in that case to # avoid segfault type errors. # # LAST MODIFICATION # # 2006-08-17 # # COPYLEFT # # Copyright (c) 2006 Guido U. Draheim # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # # As a special exception, the respective Autoconf Macro's copyright # owner gives unlimited permission to copy, distribute and modify the # configure scripts that are the output of Autoconf when processing # the Macro. You need not follow the terms of the GNU General Public # License when using or distributing such scripts, even though # portions of the text of the Macro appear in them. The GNU General # Public License (GPL) does govern all other use of the material that # constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the # Autoconf Macro released by the Autoconf Macro Archive. When you # make and distribute a modified version of the Autoconf Macro, you # may extend this special exception to the GPL to apply to your # modified version as well. AC_DEFUN([AX_CHECK_ALIGNED_ACCESS_REQUIRED], [AC_CACHE_CHECK([if pointers to integers require aligned access], [ax_cv_have_aligned_access_required], [AC_TRY_RUN([ #include #include int main() { char* string = malloc(40); int i; for (i=0; i < 40; i++) string[i] = i; { void* s = string; int* p = s+1; int* q = s+2; if (*p == *q) { return 1; } } return 0; } ], [ax_cv_have_aligned_access_required=no], [ax_cv_have_aligned_access_required=yes], [ax_cv_have_aligned_access_required=no]) ]) if test "$ax_cv_have_aligned_access_required" = yes ; then AC_DEFINE([HAVE_ALIGNED_ACCESS_REQUIRED], [1], [Define if pointers to integers require aligned access]) fi ]) libfixbuf-1.7.1/m4/ax_prog_doxygen.m4000644 000770 000024 00000042431 12412300776 021772 0ustar00emilyecoffmessagebus000000 000000 # =========================================================================== # http://autoconf-archive.cryp.to/ax_prog_doxygen.html # =========================================================================== # # SYNOPSIS # # DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR]) # DX_DOXYGEN_FEATURE(ON|OFF) # DX_DOT_FEATURE(ON|OFF) # DX_HTML_FEATURE(ON|OFF) # DX_CHM_FEATURE(ON|OFF) # DX_CHI_FEATURE(ON|OFF) # DX_MAN_FEATURE(ON|OFF) # DX_RTF_FEATURE(ON|OFF) # DX_XML_FEATURE(ON|OFF) # DX_PDF_FEATURE(ON|OFF) # DX_PS_FEATURE(ON|OFF) # # DESCRIPTION # # The DX_*_FEATURE macros control the default setting for the given # Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for # generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML # help (for MS users), 'CHI' for generating a seperate .chi file by the # .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate # output formats. The environment variable DOXYGEN_PAPER_SIZE may be # specified to override the default 'a4wide' paper size. # # By default, HTML, PDF and PS documentation is generated as this seems to # be the most popular and portable combination. MAN pages created by # Doxygen are usually problematic, though by picking an appropriate subset # and doing some massaging they might be better than nothing. CHM and RTF # are specific for MS (note that you can't generate both HTML and CHM at # the same time). The XML is rather useless unless you apply specialized # post-processing to it. # # The macros mainly control the default state of the feature. The use can # override the default by specifying --enable or --disable. The macros # ensure that contradictory flags are not given (e.g., # --enable-doxygen-html and --enable-doxygen-chm, # --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each # feature will be automatically disabled (with a warning) if the required # programs are missing. # # Once all the feature defaults have been specified, call DX_INIT_DOXYGEN # with the following parameters: a one-word name for the project for use # as a filename base etc., an optional configuration file name (the # default is 'Doxyfile', the same as Doxygen's default), and an optional # output directory name (the default is 'doxygen-doc'). # # Automake Support # # The following is a template aminclude.am file for use with Automake. # Make targets and variables values are controlled by the various # DX_COND_* conditionals set by autoconf. # # The provided targets are: # # doxygen-doc: Generate all doxygen documentation. # # doxygen-run: Run doxygen, which will generate some of the # documentation (HTML, CHM, CHI, MAN, RTF, XML) # but will not do the post processing required # for the rest of it (PS, PDF, and some MAN). # # doxygen-man: Rename some doxygen generated man pages. # # doxygen-ps: Generate doxygen PostScript documentation. # # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake targets. # If doxygen is used to generate man pages, you can achieve this # integration by setting man3_MANS to the list of man pages generated and # then adding the dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # Then add this variable to MOSTLYCLEANFILES. # # ----- begin aminclude.am ------------------------------------- # # ## --------------------------------- ## # ## Format-independent Doxygen rules. ## # ## --------------------------------- ## # # if DX_COND_doc # # ## ------------------------------- ## # ## Rules specific for HTML output. ## # ## ------------------------------- ## # # if DX_COND_html # # DX_CLEAN_HTML = @DX_DOCDIR@/html # # endif DX_COND_html # # ## ------------------------------ ## # ## Rules specific for CHM output. ## # ## ------------------------------ ## # # if DX_COND_chm # # DX_CLEAN_CHM = @DX_DOCDIR@/chm # # if DX_COND_chi # # DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi # # endif DX_COND_chi # # endif DX_COND_chm # # ## ------------------------------ ## # ## Rules specific for MAN output. ## # ## ------------------------------ ## # # if DX_COND_man # # DX_CLEAN_MAN = @DX_DOCDIR@/man # # endif DX_COND_man # # ## ------------------------------ ## # ## Rules specific for RTF output. ## # ## ------------------------------ ## # # if DX_COND_rtf # # DX_CLEAN_RTF = @DX_DOCDIR@/rtf # # endif DX_COND_rtf # # ## ------------------------------ ## # ## Rules specific for XML output. ## # ## ------------------------------ ## # # if DX_COND_xml # # DX_CLEAN_XML = @DX_DOCDIR@/xml # # endif DX_COND_xml # # ## ----------------------------- ## # ## Rules specific for PS output. ## # ## ----------------------------- ## # # if DX_COND_ps # # DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps # # DX_PS_GOAL = doxygen-ps # # doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps # # @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag # cd @DX_DOCDIR@/latex; \ # rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ # $(DX_LATEX) refman.tex; \ # $(MAKEINDEX_PATH) refman.idx; \ # $(DX_LATEX) refman.tex; \ # countdown=5; \ # while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ # refman.log > /dev/null 2>&1 \ # && test $$countdown -gt 0; do \ # $(DX_LATEX) refman.tex; \ # countdown=`expr $$countdown - 1`; \ # done; \ # $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi # # endif DX_COND_ps # # ## ------------------------------ ## # ## Rules specific for PDF output. ## # ## ------------------------------ ## # # if DX_COND_pdf # # DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf # # DX_PDF_GOAL = doxygen-pdf # # doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf # # @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag # cd @DX_DOCDIR@/latex; \ # rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ # $(DX_PDFLATEX) refman.tex; \ # $(DX_MAKEINDEX) refman.idx; \ # $(DX_PDFLATEX) refman.tex; \ # countdown=5; \ # while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ # refman.log > /dev/null 2>&1 \ # && test $$countdown -gt 0; do \ # $(DX_PDFLATEX) refman.tex; \ # countdown=`expr $$countdown - 1`; \ # done; \ # mv refman.pdf ../@PACKAGE@.pdf # # endif DX_COND_pdf # # ## ------------------------------------------------- ## # ## Rules specific for LaTeX (shared for PS and PDF). ## # ## ------------------------------------------------- ## # # if DX_COND_latex # # DX_CLEAN_LATEX = @DX_DOCDIR@/latex # # endif DX_COND_latex # # .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) # # .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) # # doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag # # doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) # # @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) # rm -rf @DX_DOCDIR@ # $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) # # DX_CLEANFILES = \ # @DX_DOCDIR@/@PACKAGE@.tag \ # -r \ # $(DX_CLEAN_HTML) \ # $(DX_CLEAN_CHM) \ # $(DX_CLEAN_CHI) \ # $(DX_CLEAN_MAN) \ # $(DX_CLEAN_RTF) \ # $(DX_CLEAN_XML) \ # $(DX_CLEAN_PS) \ # $(DX_CLEAN_PDF) \ # $(DX_CLEAN_LATEX) # # endif DX_COND_doc # # ----- end aminclude.am --------------------------------------- # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Oren Ben-Kiki # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. ## ----------## ## Defaults. ## ## ----------## DX_ENV="" AC_DEFUN([DX_FEATURE_doc], ON) AC_DEFUN([DX_FEATURE_dot], ON) AC_DEFUN([DX_FEATURE_man], OFF) AC_DEFUN([DX_FEATURE_html], ON) AC_DEFUN([DX_FEATURE_chm], OFF) AC_DEFUN([DX_FEATURE_chi], OFF) AC_DEFUN([DX_FEATURE_rtf], OFF) AC_DEFUN([DX_FEATURE_xml], OFF) AC_DEFUN([DX_FEATURE_pdf], ON) AC_DEFUN([DX_FEATURE_ps], ON) ## --------------- ## ## Private macros. ## ## --------------- ## # DX_ENV_APPEND(VARIABLE, VALUE) # ------------------------------ # Append VARIABLE="VALUE" to DX_ENV for invoking doxygen. AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])]) # DX_DIRNAME_EXPR # --------------- # Expand into a shell expression prints the directory part of a path. AC_DEFUN([DX_DIRNAME_EXPR], [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) # DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) # ------------------------------------- # Expands according to the M4 (static) status of the feature. AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) # DX_REQUIRE_PROG(VARIABLE, PROGRAM) # ---------------------------------- # Require the specified program to be found for the DX_CURRENT_FEATURE to work. AC_DEFUN([DX_REQUIRE_PROG], [ AC_PATH_TOOL([$1], [$2]) if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0) fi ]) # DX_TEST_FEATURE(FEATURE) # ------------------------ # Expand to a shell expression testing whether the feature is active. AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) # DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) # ------------------------------------------------- # Verify that a required features has the right state before trying to turn on # the DX_CURRENT_FEATURE. AC_DEFUN([DX_CHECK_DEPEND], [ test "$DX_FLAG_$1" = "$2" \ || AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, requires, contradicts) doxygen-DX_CURRENT_FEATURE]) ]) # DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) # ---------------------------------------------------------- # Turn off the DX_CURRENT_FEATURE if the required feature is off. AC_DEFUN([DX_CLEAR_DEPEND], [ test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0) ]) # DX_FEATURE_ARG(FEATURE, DESCRIPTION, # CHECK_DEPEND, CLEAR_DEPEND, # REQUIRE, DO-IF-ON, DO-IF-OFF) # -------------------------------------------- # Parse the command-line option controlling a feature. CHECK_DEPEND is called # if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), # otherwise CLEAR_DEPEND is called to turn off the default state if a required # feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional # requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and # DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. AC_DEFUN([DX_ARG_ABLE], [ AC_DEFUN([DX_CURRENT_FEATURE], [$1]) AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) AC_ARG_ENABLE(doxygen-$1, [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], [--enable-doxygen-$1]), DX_IF_FEATURE([$1], [don't $2], [$2]))], [ case "$enableval" in #( y|Y|yes|Yes|YES) AC_SUBST([DX_FLAG_$1], 1) $3 ;; #( n|N|no|No|NO) AC_SUBST([DX_FLAG_$1], 0) ;; #( *) AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) ;; esac ], [ AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) $4 ]) if DX_TEST_FEATURE([$1]); then $5 : fi if DX_TEST_FEATURE([$1]); then AM_CONDITIONAL(DX_COND_$1, :) $6 : else AM_CONDITIONAL(DX_COND_$1, false) $7 : fi ]) ## -------------- ## ## Public macros. ## ## -------------- ## # DX_XXX_FEATURE(DEFAULT_STATE) # ----------------------------- AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) # DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR]) # --------------------------------------------------------- # PROJECT also serves as the base name for the documentation files. # The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc". AC_DEFUN([DX_INIT_DOXYGEN], [ # Files: AC_SUBST([DX_PROJECT], [$1]) AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])]) AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])]) # Environment variables used inside doxygen.cfg: DX_ENV_APPEND(SRCDIR, $srcdir) DX_ENV_APPEND(PROJECT, $DX_PROJECT) DX_ENV_APPEND(DOCDIR, $DX_DOCDIR) DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) # Doxygen itself: DX_ARG_ABLE(doc, [generate any doxygen documentation], [], [], [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) DX_REQUIRE_PROG([DX_PERL], perl)], [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) # Dot for graphics: DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_DOT], dot)], [DX_ENV_APPEND(HAVE_DOT, YES) DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], [DX_ENV_APPEND(HAVE_DOT, NO)]) # Man pages generation: DX_ARG_ABLE(man, [generate doxygen manual pages], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_MAN, YES)], [DX_ENV_APPEND(GENERATE_MAN, NO)]) # RTF file generation: DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_RTF, YES)], [DX_ENV_APPEND(GENERATE_RTF, NO)]) # XML file generation: DX_ARG_ABLE(xml, [generate doxygen XML documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_XML, YES)], [DX_ENV_APPEND(GENERATE_XML, NO)]) # (Compressed) HTML help generation: DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_HHC], hhc)], [DX_ENV_APPEND(HHC_PATH, $DX_HHC) DX_ENV_APPEND(GENERATE_HTML, YES) DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) # Seperate CHI file generation. DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], [DX_CHECK_DEPEND(chm, 1)], [DX_CLEAR_DEPEND(chm, 1)], [], [DX_ENV_APPEND(GENERATE_CHI, YES)], [DX_ENV_APPEND(GENERATE_CHI, NO)]) # Plain HTML pages generation: DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], [], [DX_ENV_APPEND(GENERATE_HTML, YES)], [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) # PostScript file generation: DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_LATEX], latex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_DVIPS], dvips) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # PDF file generation: DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # LaTeX generation for PS and/or PDF: if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then AM_CONDITIONAL(DX_COND_latex, :) DX_ENV_APPEND(GENERATE_LATEX, YES) else AM_CONDITIONAL(DX_COND_latex, false) DX_ENV_APPEND(GENERATE_LATEX, NO) fi # Paper size for PS and/or PDF: AC_ARG_VAR(DOXYGEN_PAPER_SIZE, [a4wide (default), a4, letter, legal or executive]) case "$DOXYGEN_PAPER_SIZE" in #( "") AC_SUBST(DOXYGEN_PAPER_SIZE, "") ;; #( a4wide|a4|letter|legal|executive) DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) ;; #( *) AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) ;; esac #For debugging: #echo DX_FLAG_doc=$DX_FLAG_doc #echo DX_FLAG_dot=$DX_FLAG_dot #echo DX_FLAG_man=$DX_FLAG_man #echo DX_FLAG_html=$DX_FLAG_html #echo DX_FLAG_chm=$DX_FLAG_chm #echo DX_FLAG_chi=$DX_FLAG_chi #echo DX_FLAG_rtf=$DX_FLAG_rtf #echo DX_FLAG_xml=$DX_FLAG_xml #echo DX_FLAG_pdf=$DX_FLAG_pdf #echo DX_FLAG_ps=$DX_FLAG_ps #echo DX_ENV=$DX_ENV ]) libfixbuf-1.7.1/m4/debug.m4000644 000770 000024 00000001111 12412300776 017652 0ustar00emilyecoffmessagebus000000 000000 # AC_DEBUG() # # Check for commandline options requesting DEBUG feature. # Might define DEBUG, NODEBUG, or NDEBUG, depending on flags given. AC_DEFUN([AC_DEBUG],[dnl AC_ARG_ENABLE([debug], AC_HELP_STRING([--enable-debug], [include debugging code (default=no)]), [ case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) AC_MSG_ERROR(bad value ${enableval} for debug option) ;; esac], [debug=false]) if test "$debug" = true; then AC_SUBST([DEBUG_CFLAGS],["-DDEBUG -ggdb -O0"]) else AC_SUBST([DEBUG_CFLAGS],["-DNDEBUG"]) fi ]) libfixbuf-1.7.1/m4/ltoptions.m4000644 000770 000024 00000030073 12605776206 020641 0ustar00emilyecoffmessagebus000000 000000 # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) libfixbuf-1.7.1/m4/ltsugar.m4000644 000770 000024 00000010424 12605776206 020265 0ustar00emilyecoffmessagebus000000 000000 # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) libfixbuf-1.7.1/m4/ltversion.m4000644 000770 000024 00000001262 12605776206 020631 0ustar00emilyecoffmessagebus000000 000000 # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libfixbuf-1.7.1/m4/lt~obsolete.m4000644 000770 000024 00000013756 12605776206 021171 0ustar00emilyecoffmessagebus000000 000000 # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) libfixbuf-1.7.1/m4/pkg.m4000644 000770 000024 00000012160 12412300776 017353 0ustar00emilyecoffmessagebus000000 000000 # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [AC_MSG_RESULT([no]) $4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES libfixbuf-1.7.1/m4/spread.m4000644 000770 000024 00000014627 12412300776 020062 0ustar00emilyecoffmessagebus000000 000000 # tests for Spread EMS headers and libraries # # AC_DEFUN([PT_SPREAD_REQUIRED],[ te_req_err="true" echo "WARNING: Specifying --with-$1=no or --without-$1 will prevent Spread" echo " support from being built." ]) AC_DEFUN([PT_SPREAD_NOT_FOUND],[ echo "WARNING: Spread 4.1 $1 not found - libfixbuf will be built without Spread support" ]) # # PT_TRY_HEADER( incpath ) # # look for the headers in incpath AC_DEFUN([PT_TRY_HEADER],[ if test "x$1" != "x"; then _te_save_cppflags=$CPPFLAGS CPPFLAGS="-I$1 $CPPFLAGS" fi AC_CHECK_HEADERS([sp.h],[te_header_found="true"]) if test "x$1" != "x"; then CPPFLAGS=$_te_save_cppflags unset _te_save_cppflags fi ]) # # PT_TRY_LINK( incpath, libpath ) # # Try linking the spread library to validate inc and lib paths AC_DEFUN([PT_TRY_LINK],[ if test "x$1" != "x"; then _te_save_cppflags=$CPPFLAGS CPPFLAGS="-I$1 $CPPFLAGS" fi _te_save_libs=$LIBS if test "x$2" != "x"; then LIBS="-L$2 -l$te_lib_name $LIBS" else LIBS="-l$te_lib_name $LIBS" fi AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ mailbox mbox; char *pg = NULL; int res = SP_connect( "foo", "bar", 0, 1, &mbox, pg ); ]])], [te_library_found=true] []) AC_TRY_RUN([ #include #include #include int main() { membership_info memb_info; return 0; } ],[AC_MSG_NOTICE([acceptable version of Spread found])],[ te_library_found="false" AC_MSG_WARN([Old Version of Spread? Fixbuf Requires Version 4.1]) ]) if test "x$1" != "x"; then CPPFLAGS=$_te_save_cppflags unset _te_save_cppflags fi LIBS=$_te_save_libs unset _te_save_libs ]) # # The only public macro # # AC_PATH_SPREAD( version ) # AC_DEFUN([AC_PATH_SPREAD],[ te_path="" te_install_path="no" te_inc_path="" te_header_found="false" te_lib_path="" te_library_found="false" te_req_err="false" te_lib_name="spread" te_pthreadlib="" te_pthread="yes" AC_ARG_WITH([spread], AC_HELP_STRING([--with-spread=DIR],[location of Spread toolkit]), [ case $withval in yes) te_install_path="yes" ;; no) PT_SPREAD_REQUIRED([spread]) ;; *) te_install_path="yes" te_path="$withval" ;; esac ], [te_req_err="true"]) if test "$te_install_path" = "no"; then AC_ARG_WITH([spread-include], AC_HELP_STRING([--with-spread-include=DIR],[location of Spread headers]), [ case $withval in yes) ;; no) PT_SPREAD_REQUIRED([spread-include]) ;; *) te_inc_path="$withval" ;; esac ], [te_req_err="true"]) AC_ARG_WITH([spread-lib], AC_HELP_STRING([--with-spread-lib=DIR],[location of Spread libraries]), [ case $withval in yes) ;; no) PT_SPREAD_REQUIRED([spread-lib]) ;; *) te_lib_path="$withval" ;; esac ], [te_req_err="true"]) fi # ---- test for headers if test "x$te_req_err" = "xfalse"; then if test "x$te_inc_path" = "x"; then if test "x$te_path" = "x"; then AC_MSG_NOTICE(checking for sp.h in default locations) else AC_MSG_NOTICE(checking for sp.h in install directory $te_path) te_inc_path=${te_path}/include fi else AC_MSG_NOTICE(checking for sp.h in Spread include directory $te_inc_path) fi PT_TRY_HEADER([$te_inc_path]) if test "$te_header_found" = "false"; then PT_SPREAD_NOT_FOUND([header],[include]) fi # ---- test for libraries if test "x$te_lib_path" = "x"; then if test "x$te_path" = "x"; then AC_MSG_NOTICE(checking for $te_lib_name library in default locations) else te_lib_path=${te_path}/lib AC_MSG_NOTICE(checking for $te_lib_name library in install directory $te_path) fi else AC_MSG_NOTICE(checking for $te_lib_name library in Spread lib directory $te_lib_path) fi PT_TRY_LINK([$te_inc_path],[$te_lib_path]) if test "$te_library_found" = "false"; then PT_SPREAD_NOT_FOUND([library],[lib]) fi #--- everthing is good so far, check for pthread AC_CHECK_HEADERS([pthread.h],,[ te_pthread="no" AC_MSG_WARN([pthread.h not found, Spread support will not be built]) ]) AC_CHECK_LIB([pthread],[pthread_mutex_lock],[te_pthreadlib=pthread],[ te_pthread="no" AC_MSG_WARN([pthread library not found, Spread support will not be built]) ]) if test "$te_pthread" == "yes"; then if test "$te_library_found" == "true"; then if test "$te_header_found" == "true"; then AC_SUBST(FIXBUF_REQ_LIBSPREAD, [1]) if test "x$te_inc_path" != "x"; then AC_MSG_NOTICE(using sp.h found in $te_inc_path) AC_SUBST([SPREAD_CFLAGS],["-I$te_inc_path -DHAVE_SPREAD"]) else AC_MSG_NOTICE(using sp.h found in default include path) AC_SUBST([SPREAD_CFLAGS],["-DHAVE_SPREAD"]) fi AC_SUBST([SPREAD_CC_DEFINE],["-DHAVE_SPREAD"]) if test "x$te_lib_path" != "x"; then AC_MSG_NOTICE(using libspread found in $te_lib_path) AC_SUBST([SPREAD_LDFLAGS],[-L$te_lib_path]) RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-spread=${te_path}" else AC_MSG_NOTICE(using libspread found in default library path) RPM_CONFIG_FLAGS="${RPM_CONFIG_FLAGS} --with-spread" fi if test "x$te_pthreadlib" != "x"; then AC_SUBST([SPREAD_LIBS],["-l$te_lib_name -l$te_pthreadlib"]) else AC_SUBST([SPREAD_LIBS],["-l$te_lib_name"]) fi fi fi fi fi unset te_path unset te_install_path unset te_inc_path unset te_header_found unset te_lib_path unset te_library_found unset te_req_err unset te_pthreadlib unset te_do_spread ]) libfixbuf-1.7.1/include/fixbuf/000755 000770 000024 00000000000 12606001063 020706 5ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/include/Makefile.am000644 000770 000024 00000001561 12545036674 021504 0ustar00emilyecoffmessagebus000000 000000 ## Process this file with automake to produce Makefile.in ## ------------------------------------------------------------------------ ## Makefile.am (toplevel) ## autotools build system for libfixbuf ## ------------------------------------------------------------------------ ## Copyright (C) 2005-2014 Carnegie Mellon University. All Rights Reserved. ## ------------------------------------------------------------------------ ## Authors: Brian Trammell ## ------------------------------------------------------------------------ ## GNU Lesser GPL Rights pursuant to Version 2.1, February 1999 ## Government Purpose License Rights (GPLR) pursuant to DFARS 252.227-7013 ## ------------------------------------------------------------------------ nobase_include_HEADERS = fixbuf/autoinc.h \ fixbuf/public.h \ fixbuf/private.h libfixbuf-1.7.1/include/Makefile.in000644 000770 000024 00000043151 12605776213 021513 0ustar00emilyecoffmessagebus000000 000000 # Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(nobase_include_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ $(top_srcdir)/m4/ax_check_aligned_access_required.m4 \ $(top_srcdir)/m4/ax_prog_doxygen.m4 $(top_srcdir)/m4/debug.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/spread.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/fixbuf/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(includedir)" HEADERS = $(nobase_include_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUG_CFLAGS = @DEBUG_CFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DX_CONFIG = @DX_CONFIG@ DX_DOCDIR = @DX_DOCDIR@ DX_DOT = @DX_DOT@ DX_DOXYGEN = @DX_DOXYGEN@ DX_DVIPS = @DX_DVIPS@ DX_EGREP = @DX_EGREP@ DX_ENV = @DX_ENV@ DX_FLAG_chi = @DX_FLAG_chi@ DX_FLAG_chm = @DX_FLAG_chm@ DX_FLAG_doc = @DX_FLAG_doc@ DX_FLAG_dot = @DX_FLAG_dot@ DX_FLAG_html = @DX_FLAG_html@ DX_FLAG_man = @DX_FLAG_man@ DX_FLAG_pdf = @DX_FLAG_pdf@ DX_FLAG_ps = @DX_FLAG_ps@ DX_FLAG_rtf = @DX_FLAG_rtf@ DX_FLAG_xml = @DX_FLAG_xml@ DX_HHC = @DX_HHC@ DX_LATEX = @DX_LATEX@ DX_MAKEINDEX = @DX_MAKEINDEX@ DX_PDFLATEX = @DX_PDFLATEX@ DX_PERL = @DX_PERL@ DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIXBUF_REQ_LIBSCTP = @FIXBUF_REQ_LIBSCTP@ FIXBUF_REQ_LIBSPREAD = @FIXBUF_REQ_LIBSPREAD@ FIXBUF_REQ_LIBSSL = @FIXBUF_REQ_LIBSSL@ FIXBUF_REQ_SCTPDEV = @FIXBUF_REQ_SCTPDEV@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LDADD = @GLIB_LDADD@ GLIB_LIBS = @GLIB_LIBS@ GLIB_MKENUMS = @GLIB_MKENUMS@ GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCOMPAT = @LIBCOMPAT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPM_CONFIG_FLAGS = @RPM_CONFIG_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPREAD_CC_DEFINE = @SPREAD_CC_DEFINE@ SPREAD_CFLAGS = @SPREAD_CFLAGS@ SPREAD_LDFLAGS = @SPREAD_LDFLAGS@ SPREAD_LIBS = @SPREAD_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ nobase_include_HEADERS = fixbuf/autoinc.h \ fixbuf/public.h \ fixbuf/private.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_includeHEADERS: $(nobase_include_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nobase_includeHEADERS install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-nobase_includeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libfixbuf-1.7.1/include/fixbuf/autoinc.h000644 000770 000024 00000010543 12545036674 022546 0ustar00emilyecoffmessagebus000000 000000 /* ** autoinc.h ** Autotools-happy standard library include file ** ** ------------------------------------------------------------------------ ** Copyright (C) 2005-2014 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the fixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ /** @file * Convenience include file for libfixbuf. */ #ifndef _FIX_AUTOINC_H_ #define _FIX_AUTOINC_H_ #ifdef _FIXBUF_SOURCE_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if GLIB_CHECK_VERSION(2,6,0) # include #else #define g_debug(...) g_log (G_LOG_DOMAIN, \ G_LOG_LEVEL_DEBUG, \ __VA_ARGS__) #endif #ifdef _FIXBUF_SOURCE_ #if !GLIB_CHECK_VERSION(2,10,0) #define g_slice_new0(_t_) g_new0(_t_, 1) #define g_slice_alloc0(_s_) g_malloc0(_s_) #define g_slice_alloc(_s_) g_malloc(_s_) #define g_slice_new(_t_) g_new(_t_, 1) #define g_slice_free(_t_, _p_) g_free(_p_) #define g_slice_free1(_s_, _p_) g_free(_p_) #endif #endif #if HAVE_OPENSSL #include #include #include #include #include #endif #if FB_ENABLE_SCTP #if FB_INCLUDE_SCTP_H #include #endif #if FB_INCLUDE_SCTP_UIO_H #include #endif #endif #endif libfixbuf-1.7.1/include/fixbuf/config.h.in000644 000770 000024 00000005371 12605776213 022756 0ustar00emilyecoffmessagebus000000 000000 /* include/fixbuf/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 to enable SCTP support */ #undef FB_ENABLE_SCTP /* Define to 1 to use sctp.h header */ #undef FB_INCLUDE_SCTP_H /* Define to 1 to use sctp_uio.h header */ #undef FB_INCLUDE_SCTP_UIO_H /* Define if pointers to integers require aligned access */ #undef HAVE_ALIGNED_ACCESS_REQUIRED /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 to enable OpenSSL support */ #undef HAVE_OPENSSL /* Define to 1 to enable DTLS support */ #undef HAVE_OPENSSL_DTLS /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the header file. */ #undef HAVE_SP_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define if using the dmalloc debugging malloc package */ #undef WITH_DMALLOC libfixbuf-1.7.1/include/fixbuf/private.h000644 000770 000024 00000050133 12545036674 022555 0ustar00emilyecoffmessagebus000000 000000 /** *@internal * ** private.h ** fixbuf IPFIX Implementation Private Interface ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2014 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell ** ------------------------------------------------------------------------ ** @OPENSOURCE_HEADER_START@ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ ** ------------------------------------------------------------------------ */ #ifndef _FB_PRIVATE_H_ #define _FB_PRIVATE_H_ #include #if HAVE_SPREAD #include #include #endif #ident "$Id$" /** * @file * * fixbuf IPFIX protocol library private interface. These calls and structures * are intended for the use of libfixbuf modules, and as such are not * documented or guaranteed to remain stable in any way. Applications using * these calls and structures may have to be modified to track changes to this * interface across minor version releases of fixbuf. */ /** define the bit in ID's that marks the Enterprise ID's */ #define IPFIX_ENTERPRISE_BIT 0x8000 /** This is the Private Enterprise Number defined in the IPFIX standard, see RFC 5102, for reverse flow datum */ #define IPFIX_REVERSE_PEN 29305 /** definition of the max-size of an fbuf_t buffer, or the default/only size */ #define FB_MSGLEN_MAX 65535 #if HAVE_SPREAD typedef struct sp_groupname_st { char name[MAX_GROUP_NAME]; } sp_groupname_t; #define FB_SPREAD_NUM_GROUPS 16 #define FB_SPREAD_MTU 8192 typedef struct fbSpreadSpec_st { /** pointer to the session, this MUST be set to a valid session before * the spec is passed to fbExporterAllocSpread. */ fbSession_t *session; /** pointer to the daemon host address, in Spread format. Must be set * before the spec is passed to fbExporterAllocSpread */ char * daemon; /** pointer to array of group names, must have at least one, and must be null term array */ sp_groupname_t *groups; /** number of groups in groups */ int num_groups; /** groups to send to */ sp_groupname_t *groups_to_send; int num_groups_to_send; /** the mailbox for the connection */ mailbox mbox; /** the connection private name */ char privgroup[MAX_GROUP_NAME + 2]; /** Spread write lock */ pthread_mutex_t write_lock; /** the receiver thread */ pthread_t recv_thread; /** the receiver's mailbox */ mailbox recv_mbox; /** the connection private name for the receiver */ char recv_privgroup[MAX_GROUP_NAME + 2]; /** GError for thread errors, set by receiver, read by main */ GError *recv_err; /** flag to tell the thread to exit */ int recv_exit; /** max size of group name array */ int recv_max_groups; /** actual size of group name array */ int recv_num_groups; /** groups array for SP_receive */ sp_groupname_t *recv_groups; /** length of message buffer */ int recv_max; /** message buffer for receive */ char *recv_mess; } fbSpreadSpec_t; #endif /* HAVE_SPREAD */ /** * An UDP Connection specifier. These are managed by the * collector. The collector creates one fbUDPConnSpec_t * per "UDP session." A UDP session is defined by a unique * IP and observation domain." */ typedef struct fbUDPConnSpec_st { /** pointer to the session for this peer address */ fbSession_t *session; /** application context. Created and owned by the app */ void *ctx; /** key to this conn spec */ union { struct sockaddr so; struct sockaddr_in ip4; struct sockaddr_in6 ip6; } peer; /** size of peer */ size_t peerlen; /** link to next one in list */ struct fbUDPConnSpec_st *next; /** doubly linked to timeout faster */ struct fbUDPConnSpec_st *prev; /** last seen time */ time_t last_seen; /** with peer address this is the key */ uint32_t obdomain; /** reject flag */ gboolean reject; } fbUDPConnSpec_t; /** * An IPFIX template or options template structure. Part of the private * interface. Applications should use the fbTemplate calls defined in public.h * to manipulate templates instead of accessing this structure directly. */ struct fbTemplate_st { /** Information model (for looking up information elements by spec) */ fbInfoModel_t *model; /** Reference count */ int ref_count; /** Count of information elements in template. */ uint16_t ie_count; /** * Count of scope information elements in template. If sie_count * is greater than 0, this template is an options template. */ uint16_t scope_count; /** * Total length of information elements in records described by * this template. If the is_varlen flag is set, this represents the * minimum length of the information elements in the record * (i.e. with each variable length IE's length set to 0). */ uint16_t ie_len; /** * Total length required to store this template in a data structure. * Uses sizeof(fbVarfield_t), sizeof(fbBasicList_t), etc instead of 0 * as done with ie_len */ uint16_t ie_internal_len; /** * Total length of the template record or options template record * defining this template. Used during template input and output. */ uint16_t tmpl_len; /** Set to TRUE if this template contains any variable length IEs. */ gboolean is_varlen; /** Ordered array of pointers to information elements in this template. */ fbInfoElement_t **ie_ary; /** Map of information element to index in ie_ary. */ GHashTable *indices; /** Field offset cache. For internal use by the transcoder. */ uint16_t *off_cache; /** TRUE if this template has been activated (is no longer mutable) */ gboolean active; /** * Template context. Created and owned by the application * when the listener calls the fbTemplateCtxCallback_fn. */ void *tmpl_ctx; /** * Callback to free the ctx pointer when template is freed */ fbTemplateCtxFree2_fn ctx_free; /** * The application's Context pointer for the ctx_free function. */ void *app_ctx; }; /** * fBufRewind * * @param fbuf * */ void fBufRewind( fBuf_t *fbuf); /** * fBufAppendTemplate * * @param fbuf * @param tmpl_id * @param tmpl * @param revoked * @param err * * @return TRUE on success, FALSE on error */ gboolean fBufAppendTemplate( fBuf_t *fbuf, uint16_t tmpl_id, fbTemplate_t *tmpl, gboolean revoked, GError **err); #if HAVE_SPREAD /** * fBufSetExportGroups * * * */ void fBufSetExportGroups( fBuf_t *fbuf, char **groups, int num_groups, GError **err); #endif /** * fBufRemoveTemplateTcplan * * */ void fBufRemoveTemplateTcplan( fBuf_t *fbuf, fbTemplate_t *tmpl); /** * fBufSetSession * */ void fBufSetSession( fBuf_t *fbuf, fbSession_t *session); /** * fbInfoElementHash * * @param ie * * */ uint32_t fbInfoElementHash( fbInfoElement_t *ie); /** * fbInfoElementEqual * * @param a * @param b * * */ gboolean fbInfoElementEqual( const fbInfoElement_t *a, const fbInfoElement_t *b); /** *fbInfoElementDebug * * @param tmpl * @param ie * */ void fbInfoElementDebug( gboolean tmpl, fbInfoElement_t *ie); /** * fbInfoModelGetElement * * @param model * @param ex_ie * */ const fbInfoElement_t *fbInfoModelGetElement( fbInfoModel_t *model, fbInfoElement_t *ex_ie); /** * fbInfoElementCopyToTemplate * * @param model * @param ex_ie * @param tmpl_ie * */ gboolean fbInfoElementCopyToTemplate( fbInfoModel_t *model, fbInfoElement_t *ex_ie, fbInfoElement_t *tmpl_ie); /** * fbInfoElementCopyToTemplateByName * * @param model * @param name * @param len_override * @param tmpl_ie * * */ gboolean fbInfoElementCopyToTemplateByName( fbInfoModel_t *model, const char *name, uint16_t len_override, fbInfoElement_t *tmpl_ie); /** * fbInfoModelAddAlienElement * * @param model * @param ex_ie * @return info_elemnt * */ const fbInfoElement_t *fbInfoModelAddAlienElement( fbInfoModel_t *model, fbInfoElement_t *ex_ie); /** * fbTemplateRetain * * @param tmpl * * */ void fbTemplateRetain( fbTemplate_t *tmpl); /** * fbTemplateRelease * * * @param tmpl * */ void fbTemplateRelease( fbTemplate_t *tmpl); /** * fbTemplateFree * * @param tmpl * * */ void fbTemplateFree( fbTemplate_t *tmpl); /** * fbTemplateDebug * * @param label * @param tid * @param tmpl * */ void fbTemplateDebug( const char *label, uint16_t tid, fbTemplate_t *tmpl); /** * Returns the callback function for a given session * * @param session * @return the callback function variable in the session */ fbNewTemplateCallback_fn fbSessionTemplateCallback( fbSession_t *session); /** * Return the ctx callback function for a given session * * @param session * @return the Context callback function added to the session */ fbTemplateCtxCallback2_fn fbSessionTemplateCtxCallback( fbSession_t *session); /** * Return the ctx callback function's application context for a given * session * * @param session * @return the Application context pointer added to the session */ void *fbSessionTemplateCtxCallbackAppCtx( fbSession_t *session); /** * fbSessionClone * * @param base * */ fbSession_t *fbSessionClone( fbSession_t *base); /** * fbSessionGetSequence * * @param session * * */ uint32_t fbSessionGetSequence( fbSession_t *session); /** * fbSessionSetSequence * * @param session * @param sequence * */ void fbSessionSetSequence( fbSession_t *session, uint32_t sequence); /** * fbSessionSetTemplateBuffer * * @param session * @param fbuf * */ void fbSessionSetTemplateBuffer( fbSession_t *session, fBuf_t *fbuf); /** * fbSessionSetCollector * * @param session * @param collector * */ void fbSessionSetCollector( fbSession_t *session, fbCollector_t *collector); #if HAVE_SPREAD /** * fbSessionSetGroupParams * */ void fbSessionSetGroupParams( fbSession_t *session, sp_groupname_t *groups, int num_groups); /** * fbSessionSetPrivateGroup * * */ void fbSessionSetPrivateGroup( fbSession_t *session, char *group, char *privgroup); /** * fbSessionSetGroup * */ void fbSessionSetGroup( fbSession_t *session, char *group); /** * fbSessionGetGroupOffset * */ unsigned int fbSessionGetGroupOffset( fbSession_t *session, char *group); /** * fbSessionGetGroup * */ unsigned int fbSessionGetGroup( fbSession_t *session); #endif void fbSessionClearIntTmplTableFlag( fbSession_t *session); void fbSessionClearExtTmplTableFlag( fbSession_t *session); int fbSessionIntTmplTableFlagIsSet( fbSession_t *session); int fbSessionExtTmplTableFlagIsSet( fbSession_t *session); /** * fbConnSpecLookupAI * * @param spec * @param passive * @param err * */ gboolean fbConnSpecLookupAI( fbConnSpec_t *spec, gboolean passive, GError **err); /** * fbConnSpecInitTLS * * @param spec * @param passive * @param err * */ gboolean fbConnSpecInitTLS( fbConnSpec_t *spec, gboolean passive, GError **err); /** * fbConnSpecCopy * * @param spec * * */ fbConnSpec_t *fbConnSpecCopy( fbConnSpec_t *spec); /** * fbConnSpecFree * * @param spec * * */ void fbConnSpecFree( fbConnSpec_t *spec); #if HAVE_SPREAD /** * fbConnSpreadCopy * * @param spec * * */ fbSpreadSpec_t *fbConnSpreadCopy( fbSpreadParams_t *spec); /** * fbConnSpreadFree * * @param spec * * */ void fbConnSpreadFree( fbSpreadSpec_t *spec); /** * fbConnSpreadError * * Return a string message for the given Spread error code * * @param err the spread error code * @return the text message */ const char * fbConnSpreadError( int err ); /** * fbExporterSetGroupToSend * * @param exporter * @param groups * @param number of groups in above group list * */ void fbExporterSetGroupsToSend( fbExporter_t *exporter, char **groups, int num_groups); /** * fbExporterCheckGroups * * @param exporter * @param groups * @param number of groups in above group list * @return TRUE if group is in subscribed group list * */ gboolean fbExporterCheckGroups( fbExporter_t *exporter, char **groups, int num_groups); #endif /* HAVE_SPREAD */ /** * fbExporterGetMTU * * @param exporter * * */ uint16_t fbExporterGetMTU( fbExporter_t *exporter); /** * fbExportMessage * * @param exporter * @param msgbase * @param msglen * @param err * */ gboolean fbExportMessage( fbExporter_t *exporter, uint8_t *msgbase, size_t msglen, GError **err); /** * fbExporterFree * * @param exporter * * */ void fbExporterFree( fbExporter_t *exporter); /** * fbCollectorRemoveListenerLastBuf * * @param fbuf * @param collector * */ void fbCollectorRemoveListenerLastBuf( fBuf_t *fbuf, fbCollector_t *collector); /** * fbCollectorAllocSocket * * @param listener * @param ctx * @param fd * @param peer * @param peerlen * */ fbCollector_t *fbCollectorAllocSocket( fbListener_t *listener, void *ctx, int fd, struct sockaddr *peer, size_t peerlen); /** * fbCollectorAllocTLS * * @param listener * @param ctx * @param fd * @param peer * @param peerlen * @param err * */ fbCollector_t *fbCollectorAllocTLS( fbListener_t *listener, void *ctx, int fd, struct sockaddr *peer, size_t peerlen, GError **err); /** * fbCollectMessage * * @param collector * @param msgbase * @param msglen * @param err * */ gboolean fbCollectMessage( fbCollector_t *collector, uint8_t *msgbase, size_t *msglen, GError **err); /** * fbCollectorGetFD * * @param collector * * */ int fbCollectorGetFD( fbCollector_t *collector); /** * fbCollectorSetFD * * * */ void fbCollectorSetFD( fbCollector_t *collector, int fd); /** * fbCollectorFree * * @param collector * * */ void fbCollectorFree( fbCollector_t *collector); /** * fbCollectorHasTranslator * * @param collector * * */ gboolean fbCollectorHasTranslator( fbCollector_t *collector); /** * fbCollectMessageBuffer * * used for applications that manage their own connection, file reading, etc. * * @param hdr * @param b_len * @param m_len * @param err * * @return TRUE/FALSE * */ gboolean fbCollectMessageBuffer( uint8_t *hdr, size_t b_len, size_t *m_len, GError **err); #if HAVE_SPREAD /** * fbCollectorTestGroupMembership * * @param collector * @param group_offset * */ gboolean fbCollectorTestGroupMembership( fbCollector_t *collector, int group_offset); #endif /** * fbListenerAppFree * * @param listener * @param ctx * */ void fbListenerAppFree( fbListener_t *listener, void *ctx); /** * fbListenerRemoveLastBuf * * @param fbuf * @param listener * */ void fbListenerRemoveLastBuf( fBuf_t *fbuf, fbListener_t *listener); /** * fbListenerRemove * * @param listener * @param fd * */ void fbListenerRemove( fbListener_t *listener, int fd); /** * fbListenerGetConnSpec * * @param listener * * */ fbConnSpec_t *fbListenerGetConnSpec( fbListener_t *listener); /** * Interrupt the socket for a given collector to stop it from reading * more data * * @param collector pointer to the collector to stop reading from */ void fbCollectorInterruptSocket( fbCollector_t *collector); /** * call appinit from UDP * */ gboolean fbListenerCallAppInit( fbListener_t *listener, fbUDPConnSpec_t *spec, GError **err); /** * Set the session on the fbuf and listener. * */ fbSession_t *fbListenerSetPeerSession( fbListener_t *listener, fbSession_t *session); #endif libfixbuf-1.7.1/include/fixbuf/public.h000644 000770 000024 00000531237 12545036674 022372 0ustar00emilyecoffmessagebus000000 000000 /* ** public.h ** fixbuf IPFIX Implementation Public Interface ** ** ------------------------------------------------------------------------ ** Copyright (C) 2006-2015 Carnegie Mellon University. All Rights Reserved. ** ------------------------------------------------------------------------ ** Authors: Brian Trammell, Dan Ruef ** ------------------------------------------------------------------------ ** Use of the libfixbuf system and related source code is subject to the terms ** of the following licenses: ** ** GNU Lesser GPL (LGPL) Rights pursuant to Version 2.1, February 1999 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract FA8721-05-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** ------------------------------------------------------------------------ */ /** * @mainpage libfixbuf - IPFIX Protocol Library * * \subpage How-To * * @section Introduction * * libfixbuf is a compliant implementation of the IPFIX Protocol, * as defined in the "Specification of the IPFIX Protocol for the Export of IP * Flow Information" (RFC 5101). It supports the information model * defined in "Information Model for IP Flow Information Export" * (RFC 5102), extended as proposed by "Bidirectional Flow Export using * IPFIX" (RFC 5103) to support information elements for representing biflows. * * libfixbuf supports UDP, TCP, SCTP, TLS over TCP, and Spread as transport * protocols. Support for DTLS over UDP and DTLS over SCTP is forthcoming. * It also supports operation as an IPFIX File Writer or IPFIX File Reader as * defined in "An IPFIX-Based File Format" (draft-trammell-ipfix-file, current * revision -05). * * As of version 1.0, libfixbuf supports structured data elements as described * in "Export of Structured Data in IPFIX" (RFC 6313). This adds the ability * to export basicLists, subTemplateLists, and subTemplateMultiLists. * libfixbuf's public API is defined in public.h; see the \ref How-To section * or public.h for general documentation on getting started with libfixbuf, as * well as detailed documentation on the public API calls and data types. * * @section Downloading * * libfixbuf is distributed from http://tools.netsa.cert.org/fixbuf * * @section Building * * libfixbuf uses a reasonably standard autotools-based build system. * The customary build procedure (./configure && make * && make install) should work in most environments. * * libfixbuf requires glib-2.0 version 2.6.4 or later. If built against * version 2.10 or later, it will automatically use the glib slab allocator * for increased memory allocation performance. glib is available on most * modern Linux distributions and BSD ports collections, or in source form from * http://www.gtk.org. * * libfixbuf automatically uses the getaddrinfo(3) facility and the * accompanying dual IPv4/IPv6 stack support if present. getaddrinfo(3) * must be present to export or collect flows over IPv6. * * libfixbuf does not build with SCTP support by default. The --with-sctp * option must be given to the libfixbuf ./configure script to include SCTP * support. Also note that SCTP requires kernel support, and applications * built against libfixbuf with libsctp may fail at runtime if that kernel * support is not present. * * libfixbuf does not build with TLS support by default. The --with-openssl * option must be given to the libfixbuf ./configure script to include TLS * support. * * Spread support requires Spread 4.1 or * later. libfixbuf does not build with Spread support by default. * The --with-spread option must be given to libfixbuf ./configure script to * include Spread support. * * @section Known Issues * * The following are known issues with libfixbuf as of version 1.0.0: * *
    *
  • There is no support for DTLS over UDP or DTLS over SCTP transport.
  • *
  • There is no support for application-selectable SCTP stream assignment * or SCTP partial reliability. Templates are sent reliably on stream 0, * and data sets are sent reliably on stream 1. *
  • *
  • There is no automatic support for periodic template retransmission * or periodic template expiration as required when transporting IPFIX * over UDP. Applications using libfixbuf to transport IPFIX messages * over UDP must maintain these timeouts and manually manage the session. * However, inactive UDP collector sessions are timed out after 30 minutes, * at which time the session is freed and all templates associated with the * session are removed. *
  • *
* * @section Copyright * * libfixbuf is copyright 2005-2015 Carnegie Mellon University, and is released * under the GNU Lesser General Public License (LGPL). See the COPYING file in * the distribution for details. * * libfixbuf was developed at Carnegie Mellon University * by Brian Trammell and the CERT Network Situational Awareness Group * Engineering Team for use in the YAF and SiLK tools. * */ /** * * @page How-To Getting started with libfixbuf * * Include fixbuf/public.h * in order to use the public fixbuf API. * * This documentation uses IPFIX terminology as defined in RFC 5101, * "Specification of the IPFIX Protocol for the Exchange of IP Traffic Flow * Information" * * The following sections provide information on specific libfixbuf usage: * * - \ref export Exporters * - \ref read IPFIX File Collectors * - \ref collect Network Collectors * - \ref udp UDP Collectors * - \ref v9 NetFlow v9 Collectors * - \ref sflow sFlow Collectors * - \ref spread Spread Collectors * - \ref noconnect Connection-less collector * - \ref lists BasicLists, SubTemplateLists, SubTemplateMultiLists * - \ref rfc_5610 RFC 5610 * * @section types Data Types * * public.h defines the data types and routines required to support IPFIX * Exporting Process and IPFIX Collecting Process creation. Each data type is * manipulated primarily by routines named "fb" followed by the type name * (e.g., "Session", "Collector") followed by a description of the routine's * action. The routines operating on the fBuf_t IPFIX Mesaage buffer type are * named beginning with "fBuf". * * The fBuf_t opaque type implements a transcoding IPFIX Message buffer for * both export and collection, and is the "core" interface to the fixbuf * library. * * The fbInfoModel_t opaque type implements an IPFIX Information Model, * including both IANA managed Information Elements and vendor-specific * Information Elements. The fbTemplate_t opaque type implements an IPFIX * Template or an IPFIX Options Template. Both are defined in terms of * Information Elements, represented by the fbInfoElement_t public type. * An fBuf_t message buffer maintains internal Templates, which represent * records within the fixbuf application client, and external Templates, * which represent records as they appear on the wire, for use during * transcoding. For a Spread Exporter, Templates are managed per group. For * a Spread Collector, Templates are managed per Session. * * The state of an IPFIX Transport Session, including IPFIX Message Sequence * Number tracking and the internal and external Templates in use within the * Session, are maintained by the fbSession_t opaque type. * * An Exporting Process' connection to its corresponding Collecting Process * is encapsulated by the fbExporter_t opaque type. Exporters may be created * to connect via the network using one of the supported IPFIX transport * protocols, or to write to IPFIX Files specified by name or by open ANSI C * file pointer. * * A Collecting Process' connection to a corresponding Exporting Process is * encapsulated by the fbCollector_t opaque type. The passive connection used * to listen for connections from Exporting Processes is managed by the * fbListener_t opaque type; Collectors can be made to read from IPFIX Files * specified directly by name or by open ANSI C file pointer, as well. * * Network addresses are specified for Exporters, Collectors, and Listeners * using the fbConnSpec_t and fbTransport_t public types. * * This file also defines the GError error codes used by all the fixbuf types * and routines within the FB_ERROR_DOMAIN domain. * * @page export Exporter Usage * * How-To Export IPFIX: * Each fixbuf application must have a single fbInfoModel_t instance that * represents the Information Elements that the application understands. * The fbInfoModelAlloc() call allocates a new Information Model with the * IANA-managed information elements (current as of the fixbuf release date) * preloaded. Additional vendor-specific information elements may be added * with fbInfoModelAddElement() and fbInfoModelAddElementArray(). * * To create an Exporter, first create an fbSession_t attached to the * application's fbInfoModel_t to hold the Exporter's Transport Session * state using fbSessionAlloc(). If exporting via the Spread protocol, create * an fbSpreadParams_t and set its session to your newly defined session, * group names (a null terminated array), and Spread daemon name. * * Then create an fbExporter_t to encapsulate the connection to the * Collecting Process or the file on disk, using the fbExporterAllocFP(), * fbExporterAllocFile(), fbExporterAllocNet(), fbExporterAllocBuffer(), * or fbExporterAllocSpread() calls. * * With an fbSession_t and an fbExporter_t available, create a buffer for * writing via fBufAllocForExport(). * * Create and populate templates for addition to this session using the * fbTemplate calls, then add them to the session via fbSessionAddTemplate(). * * If exporting via Spread, before calling fbSessionAddTemplate(), set the * group that should receive this template with the fBufSetSpreadExportGroup() * call. If more than 1 group should receive the template, use the * fbSessionAddTemplatesMulticast() which will call fBufSetSpreadExportGroup() * on the given group(s) multicast the template to the given group(s). * For Spread, do not use fbSessionAddTemplate() to send to multiple groups. * * Once the templates have been added to the session, use * fbSessionExportTemplates() to add the templates to the buffer and then * set the internal and external template IDs with fBufSetInternalTemplate() * and fBufSetExportTemplate(). You can then use fBufAppend() to write * records into IPFIX Messages and Messages to the output stream. * * Note that Templates use internal reference counting, so they may be added * to multiple sessions, or to the same session using multiple template IDs or * multiple domains, or as both an internal and an external template on the * same session. * * By default, fBufAppend() will emit an IPFIX Message to the output stream * when the end of the message buffer is reached on write. The * fBufSetAutomaticMode() call can be used to modify this behavior, * causing fBufAppend() to return FB_ERROR_EOM when at end of message. Use * this if your application requires manual control of message export. In this * case, fBufEmit() will emit a Message to the output stream. If using Spread, * call fBufSetSpreadExportGroup() to set the groups to export to on the * buffer before calling fBufAppend(). * * @page read IPFIX File Collectors * * How-To Read IPFIX Files: * * Using fixbuf to read from IPFIX Files as a Collecting Process is very * much like the Export case. Create an fbInfoModel_t using fbInfoModelAlloc() * and any additional, vendor-specific information elements using * fbInfoModelAddElement() or fbInfoModelAddElementArray(). Next create * an fbSession_t using fbSessionAlloc() and add internal templates via * fbSessionAddTemplate(). External templates do not need to be added * for collection, as they will be loaded from templates in the file. * * Then create an fbCollector_t to encapsulate the file, using the * fbCollectorAllocFP() or fbCollectorAllocFile() calls. * * With an fbSession_t and an fbCollector_t available, create a buffer for * writing via fBufAllocForCollection(). Set the internal template * ID with fBufSetInternalTemplate(), and use * fBufNext() to read records from IPFIX Messages and Messages from the * input stream. * * By default, fBufNext() will consume an IPFIX Message from the input stream * when the end of the message buffer is reached on read. The * fBufSetAutomaticMode() call can be used to modify this behavior, * causing fBufNext() to return FB_ERROR_EOM when at end of message. Use * this if your application requires manual control of message collection. * In this case, fBufNextMessage() will consume a Message from the input * stream. * * @page collect Network Collectors * * Listening over the Network - TCP Recommended: * * An additional type, fbListener_t, is used to build Collecting Processes * to listen for connections from IPFIX Exporting Processes via the network. * To use a listener, first create an fbInfoModel_t using fbInfoModelAlloc() * and any additional, vendor-specific information elements using * fbInfoModelAddElement() or fbInfoModelAddElementArray(). Next create * an fbSession_t using fbSessionAlloc() and add internal templates via * fbSessionAddTemplate(). Instead of * maintaining state for a particular Transport Session, this fbSession_t * instance will be used as a template for each Transport Session created * by the listener. * * Then create an fbListener_t to encapsulate a passive socket on the network * to wait for connections from Exporting Processes using the * fbListenerAlloc() call. * * To wait for a connection from an Exporting Process, call fbListenerWait(), * which handles the cloning of the fbSession_t, the creation of the * fbCollector_t, and the creation of the buffer for reading from that * collector, and returns the newly created fBuf_t instance. * * A listener binds to each address returned by getaddrinfo(). Once a * packet has been received, the collector will only read packets on the * address it received the first packet UNLESS fbListenerWait() is called * again. If the application is expecting multiple connections or IPFIX * records from multiple IPFIX (UDP) exporters, then the application should * put the fBuf_t returned from fbListenerWait() into to manual mode by * calling fBufSetAutomaticMode(fbuf, FALSE) and handle FB_ERROR_EOM errors * returned from fBufNext() by calling fbListenerWait() again. * * Each listener tracks every active collector/buffer (i.e., each active * Session) it created; the fbListenerWait() call will return an fBuf_t from * which another IPFIX Message may be read if no new connections are available. * The preferred parameter may be used to request an fBuf_t to try first, to * minimize switching among available Sessions. See the documentation for * fbListenerWait() for more details. * * If an application wants to wait for connections on multiple ports or * multiple transport protocols, the application can use fbListenerGroupWait() * to accept multiple connections. The application should create separate * sessions and fbConnSpec_ts for each fbListener and call fbListenerAlloc() * to allocate each listener. Create an fbListenerGroup_t by calling * fbListenerGroupAlloc() and add each listener to the group using * fbListenerGroupAddListener(). Instead of calling fbListenerWait(), use * the function fbListenerGroupWait() to listen on all addresses in the group. * fbListenerGroupWait() returns an fbListenerGroupResult_t which is a linked * list of results. The fbListenerGroupResult_t contains a pointer to an * fBuf_t and the fbListener_t that created the fBuf_t as well as a pointer * to the next result, if available. Use fbListenerFreeGroupResult() to free * the result when fBufNext() has been called on each fBuf_t. * * The application could also use fbListenerWaitNoCollectors() to handle only * the initial accepting of a connection (for TCP). Once the application * returns to fbListenerWaitNoCollectors(), fixbuf will ignore that socket * descriptor for the length of the connection. * * Additionally, the application can use fbListenerOwnSocketCollectorTCP() * to provide its own socket for listening instead of libfixbuf creating * one for it. * * To reject incoming connections, the application should use the * fbListenerAppInit function callback. This will be called right after * accept() is called (in the TCP case). The application can veto the * connection by returning FALSE. Once the connection is vetoed, fixbuf * will not listen on that socket descriptor. * If the appinit() function should reject a connection the application * should set the error code to FB_ERROR_NLREAD and the application should * ignore FB_ERROR_NLREAD error codes. The appinit() function works slightly * different for UDP. See the udp instructions for how to use appinit() for * collecting IPFIX over UDP. * * @page udp UDP Collectors * * How-To Collect IPFIX over UDP: * * It is not recommended to use UDP for IPFIX transport, since * UDP is not a reliable transport protocol, and therefore cannot guarantee * the delivery of messages. libfixbuf stores sequence numbers and reports * protential loss of messages. Templates over UDP must be re-sent at regular * intervals. Fixbuf does not automatically retransmit messages at regular * intervals, it is left to the application author to call * fbSessionExportTemplates(). In accordance with RFC 5101, the templates * should be resent at least three times in the Template refresh timeout * period. Make sure the record size does not exceed the path MTU. * libfixbuf will return an error if the message exceeds the path MTU. * * A UDP collector session is associated with a unique IP, observation domain * pair. UDP sessions timeout after 30 minutes of inactivity. When a session * times out, all templates and state are discarded, this includes any related * NetFlow v9 templates and/or state. libfixbuf will discard * any data records for which it does not contain a template for. Template IDs * are unique per UDP session (IP and Observation Domain.) Once * templates are refreshed, old templates may not be used or referenced by * the collecting session. A UDP collector manages multiple sessions on * one collector and fbuf. If the application is using the fbListenerAppInit * and fbListenerAppFree functions to maintain context per session, it is * necessary to call fbCollectorGetContext() after each call to fBufNext() to * receive the correct ctx pointer (as opposed to calling it after * fbListenerWait() returns in the TCP case). If the application needs to * manage context PER SESSION, the application must turn on multi-session mode * w/ fbCollectorSetUDPMultiSession() (this allows for backwards compatibility * with old applications.) Previously, the appinit() function was called * only from fbListenerAlloc() for UDP connections, which did not allow the * application the peer information. The appinit() function is now called * during fbListenerAlloc() (with a NULL peer address) and also when * a new UDP connection is made to the collector, giving the application * veto power over session creation. If the application does not call * fbCollectorSetUDPMultiSession(), the application will not receive the * callback to it's appinit() function, which only allows the application * to set one ctx pointer on all sessions. Likewise, appfree() is only * called once, when the collector is freed, if not in multi-session mode. * If the application is in multi-session mode, appfree() will be called * once for each session when the collector is freed AND anytime a session * is timed out. * Note: If the appinit() function returns FALSE, libfixbuf will * reject any subsequent messages from the * peer address, observation domain until the timeout period has expired. * If the appinit() function should reject a "connection" the application * should set the error code to FB_ERROR_NLREAD and return FALSE. * Example usage: * \code{.c} * g_set_error(error, FB_ERROR_DOMAIN, FB_ERROR_NLREAD, "some msg"); * \endcode * * * To only accept IPFIX from one host without using the appinit() and * appfree() functions, it is encouraged to * use fbCollectorSetAcceptOnly(). UDP messages received from other hosts * will return FB_ERROR_NLREAD. The application should ignore errors with * this error code by clearing the error and calling fBufNext(). * * To manage netflow v9 and UDP sessions by port as well as IP and * observation domain, use fbCollectorManageUDPStreamByPort(). Some * netflow v9 devices send two separate streams from different ports to * the same sensor. Unless the observation domain is different on each * of the streams, use fbCollectorManageUDPStreamByPort() to prevent * template confusion between streams. * * * @page v9 NetFlow v9 Collectors * * How-To use libfixbuf as a NetFlow v9 Collector: * * libfixbuf can be used as a NetFlow v9 collector and convert NetFlow to * IPFIX. Follow the steps above to create an fbListener. After creating * the listener, retrieve the collector by calling fbListenerGetCollector() * before calling fbCollectorSetNetflowV9Translator(). Fixbuf can decode all * NetFlow v9 information elements up to 346. Since fixbuf removes the * SysUpTime from the NetFlow v9 Header, when fixbuf encounters elements 21 * and 22 (which rely on the SysUpTime to determine flow start and end times) * it will add IPFIX Element 160 (systemInitTimeMilliseconds) to the template * and corresponding flow record. systemInitTimeMilliseconds is the Packet * Export Time (found in the NetFlow v9 Header) converted to milliseconds * minus the SysUpTime. Also, for arbitrary Cisco Elements (ID > 346), fixbuf * will convert the element ID to 9999 in order to decode the element properly. * The exceptions are elements 33002 (NF_F_FW_EXT_EVENT) and 40005 * (NF_F_FW_EVENT) which are often exported from Cisco's ASA device. These * elements will be converted to their corresponding element id's in * libfixbuf's default Information Model, 9997 and 9998 respectively. * Similarly, the Cisco ASA will also export elements 40001, 40002, 40003, * and 40004. These elements are substituted with the IPFIX elements 225, 226, * 227, and 228 respectively. * * libfixbuf will also convert NetFlow v9 Options Templates and Options Records * to IPFIX. Due to the differences between IPFIX and NetFlow v9 Options * Templates the NetFlow v9 Scope Field Type is dropped and replaced with the * Information Element ID 263, messageScope. The Scope Field Length will * be carried over to the IPFIX Options Template, and the messageScope will * have the length specified by Scope Field Length. This holds true for all * Scope Elements defined in the NetFlow v9 Options Template. In order to * retrieve the value for the Scope Field Type, the IPFIX internal template * should use the messageScope Information Element and use the length * override (the default length for messageScope is 1). * * libfixbuf differentiates Netflow v9 streams by IP and observation domain. * If no activity is seen from a NetFlow v9 exporter within 30 minutes, the * session and all the templates associated with it will be freed. It is best * to set the template timeout period on the device to under 30 minutes. * * fbCollectorGetNetflowMissed() can be used to retrieve the number of * potential missed export packets. This is not the number of FLOW records * that the collector has missed. NetFlow v9 increases sequence numbers * by the number of export packets it has sent, NOT the number of flow * records. An export packet may not contain any flow records. Fixbuf * tries to account for any reboot of the device and not count large * sequence number discrepancies in it's missed count. * * To disable NetFlow v9 log messages such as sequence number mismatch * messages, option template removal messages, and record count discrepancy * messages, run `make clean`, `CFLAGS="-DFB_SUPPRESS_LOGS=1" make -e`, * `make install` when installing libfixbuf. * * @page sflow sFlow Collectors * * How to use libfixbuf to collect sFlow v5 * * libfixbuf can be used to collect sFlow and convert sFlow to * IPFIX. Follow the steps above to create an fbListener. After creating * the listener, retrieve the collector by calling fbListenerGetCollector() * before calling fbCollectorSetSFlowTranslator(). Essentially, the libfixbuf * translator is an IPFIX mediator which converts sFlow to IPFIX. sFlow v5 is * a fixed format protocol. The same steps are used to retrieve flow records * from the buffer, call fBufNext(). The internal template should contain * some subset of the fields listed below. sFlow Data Records will have a * template ID of 0xEEEE and the Options Records will have a template ID of * 0xEEEF. * * Fixbuf first reads the sFlow header to * ensure the buffer contains sFlow v5. Fixbuf currently only has support for * sFlow v5. The sFlow header only contains the time since the device last * rebooted (but not the time of reboot) and this time will be reported in * the systemInitTimeMilliseconds field. Fixbuf records * the time that the sFlow message was received in the * collectionTimeMilliseconds field. Once the first message * has been received, the translator will create an external buffer and export * the fixed templates to the fixbuf session. Note: the first sFlow message * that fixbuf receives will not be processed - this is used to setup the * translation process. The translator will keep track of sequence numbers * per peer (IP)/observation domain (agent ID) by default. Use * fbCollectorManageUDPStreamByPort() to differentiate sessions by IP, port, * and observation domain. There are multiple sequence numbers in sFlow. * Each sFlow message has a sequence number and each sample has a sequence * number. The sFlow message sequence number is used to determine if * sFlow messages have been dropped. Fixbuf will report if either sequence * number is out of sequence and emit a warning. The warning is just for * notification, libfixbuf will process all well-formed samples that it * receives. * * libfixbuf will process Flow Samples (1), Extended Flow Samples (3), Counter * Samples (2), and Extended Counter Samples (4). Any other format will * return an FB_ERROR_SFLOW. Applications should ignore (and potentially log) * FB_ERROR_SFLOW errors. FB_ERROR_SFLOW errors are not fatal. * With an sFlow sample, fixbuf can handle the following formats: * * - Raw Packet Data, enterprise = 0, format = 1 * - Ethernet Frame Data, enterprise = 0, format = 2 * - IPv4 Data, enterprise = 0, format = 3 * - IPv6 Data, enterprise = 0, format = 4 * - Extended Switch data, enterprise = 0, format = 1001 * - Extended Router data, enterprise = 0, format = 1002 * - Extended Gatway Data, enterprise = 0, format = 1003 * * Any other flow sample format will be silently ignored. * Each sFlow flow record can contain the following fields, formats are listed * in the parenthesis: * * IPFIX FIELDS | sFlow FIELDS | Reduced Length * ------------- | ------------- | ------------- * sourceIPv6Address | Ipv6 Address in IPv6 (4) or Raw Packet (1) Data | N * destinationIPv6Address | Ipv6 Address in IPv6 (4) or Raw Packet (1) Data| N * ipNextHopIPv6Address | Extended Router Data (1002) | N * bgpNextHopIPv6Address | Extended Gateway Data (1003) | N * collectorIPv6Address | Message Header Data | N * collectionTimeMilliseconds | Message Header Data | N * systemInitTimeMilliseconds | Message Header Data | N * collectorIPv4Address | Message Header Data | N * protocolIdentifier | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | N * ipClassOfService | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | N * sourceIPv4PrefixLength |Extended Router Data (1002) | N * destinationIPv4PrefixLength | Extended Router Data (1002) | N * sourceIPv4Address | IPv4 (3) or Raw Packet (1) Data | N * destinationIPv4Address | IPv4 (3) or Raw Packet (1) Data| N * octetTotalCount | Flow Sample Header Data | 4 * packetTotalCount | Flow Sample Header Data | 4 * ingressInterface | Flow Sample Header Data | N * egressInterface | Flow Sample Header Data | N * sourceMacAddress | Ethernet (2), IPv4 (3), IPv6 (4) or Raw Packet (1) Data | N * destinationMacAddress | Ethernet (2), IPv4 (3), IPv6 (4) or Raw Packet (1) Data | N * ipNextHopIPv4Address | Extended Router Data (1002) | N * bgpSourceAsNumber | Extended Gateway Data (1003)| N * bgpDestinationAsNumber| Extended Gateway Data (1003) | N * bgpNextHopIPv4Address| Extended Gateway Data (1003) | N * samplingPacketInterval | Message Header Data | N * samplingPopulation| Message Header Data | N * droppedPacketTotalCount| Message Header Data | 4 * selectorId| Message Header Data | 4 * vlanId | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | N * sourceTransportPort | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | N * destinationTransportPort | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | N * tcpControlBits | IPv4 (3) or IPv6 (4) or Raw Packet (1) Data | 2 * dot1qVlanId | Extended Switch Data (1001) | N * postDot1qVlanId | Extended Switch Data (1001) | N * dot1qPriority | Extended Switch Data (1001) | N * * libfixbuf will also convert sFlow Counter Records to Options Records * in IPFIX. libfixbuf will only process the Generic Interface Counters * (format = 1). Other formats will be silently ignored. * The following fields are present in the Counter (Options) Template/Record: * * IPFIX FIELDS | sFlow FIELDS | Reduced Length * ------------- | ------------- | -------------- * collectorIPv6Address | Message Header Data | N * collectionTimeMilliseconds | Message Header Data | N * systemInitTimeMilliseconds | Message Header Data | N * collectorIPv4Address | Message Header Data | N * ingressInterface | Counter Sample Header Data | N * octetTotalCount | ifINOctets (1) | N * ingressInterfaceType | ifType (1) | N * packetTotalCount | ifInUcastPkts (1) | 4 * ingressMulticastPacketTotalCount | ifInMulticastPkts (1) | 4 * ingressBroadcastPacketTotalCount | ifInBroadcastPkts (1) | 4 * notSentPacketTotalCount | ifInDiscards (1) | 4 * droppedPacketTotalCount | ifInErrors (1) | 4 * postOctetTotalCount | ifOutOctets (1) | N * ignoredPacketTotalCount | ifInUnknownProtos (1) | 4 * postPacketTotalCount | ifOutUcastPkts (1) | 4 * egressBroadcastPacketTotalCount | ifOutBroadcastPkts (1) | 4 * selectorId | Message Header Data | 4 * * * fbCollectorSFlowMissed() can be used to retrieve the number of * potential missed export packets. This is not the number of FLOW samples * that the collector has missed. Fixbuf * tries to account for any reboot of the device and not count large * sequence number discrepancies in it's missed count. * * Fixbuf will return FB_ERROR_SFLOW if it tries to process any * malformed samples. * * @page spread Spread Collectors * * How-To use the Spread Protocol: * * The instructions for using Spread in libfixbuf are similar to the * setup for reading from IPFIX files. As described above in the Exporters * section, the first step is to create an fbInfoModel_t and fbSession_t. * Next, create the internal template(s) and add it to the fbSession_t. * Define an fbSpreadParams_t and set the session, groups to subscribe to, * and Spread Daemon name. * Example usage: * \code{.c} * fbSpreadParams_t spread; * char *groups[25]; * groups[0] = strdup("group1"); * groups[1] = '\0'; * spread.daemon = "daemon1" * spread.groups = groups; * spread.session = session; * collector = fbCollectorAllocSpread(0, &spread, &err); * \endcode * * Then create an fbCollector_t to connect and listen to the Spread Daemon * using fbCollectorAllocSpread(). * * With an fbSession_t and fbcollector_t available, create a buffer for * writing via fBufAllocForCollection(). Set the internal template ID with * fBufSetInternalTemplate(), and use fBufNext() to read records from IPFIX * Messages published to the group your collector is subscribing to. * * To view all the Spread Groups that were sent the incoming record, call * fbCollectorGetSpreadReturnGroups() on the collector. * * @page noconnect Connection-less Collector * * How-To use libfixbuf with just a data buffer: * * To use fixbuf independent of the transport mode, the application must * create an fbInfoModel_t using fbInfoModelAlloc() * and any additional, vendor-specific information elements using * fbInfoModelAddElement() or fbInfoModelAddElementArray(). Next create * an fbSession_t using fbSessionAlloc() and add internal templates via * fbSessionAddTemplate(). * The application will handle all connections and reading and simply pass fixbuf * the buffer to be decoded. The buffer must contain valid IPFIX and should * begin with the standard IPFIX header. Ideally, the application should * provide the necessary templates before any data records to ensure that * the application can decode all of the data records. * * The application should NOT create an fbCollector. To create the fBuf, * use fBufAllocForCollection() and set the second parameter to NULL. * The application then has everything needed to start reading from the IPFIX * source. Ideally, the application will read the first 4 bytes of the message * first to determine the length of the next IPFIX message. The first 2 bytes * are the IPFIX version (0x000A) and the third and fourth bytes are the length * of the following IPFIX message (including the IPFIX message header). The * application should then continue reading the length of the IPFIX message * into an allocated buffer. The buffer should then be set on the fBuf by * calling fBufSetBuffer(). The application will continue to call fBufNext() * to receive the data records until fBufNext() returns FALSE with error * code FB_ERROR_BUFSZ. However, if the fBuf is in manual mode * fbufSetAutomaticMode(buf, FALSE) AND the application was reading the * message length, fixbuf will first return an FB_ERROR_EOM which will * signal to the application to perform another read (if the application * ignores FB_ERROR_EOM errors and calls fBufNext(), fBufNext() will then * return FB_ERROR_BUFSZ). This error notifies the application that there is * not enough data in the buffer to read a full IPFIX message. If the * application only read the size of the IPFIX message, the entire buffer * should have been read. However, if the application was reading more than * the IPFIX message length, additional data may remain in the buffer that * belongs to the next IPFIX message. To determine how much data was left * in the buffer unread, fBufRemaining() will return the length * of the buffer that was not processed. That remaining data should be copied * to the beginning of the buffer and the remaining IPFIX message data should * be read. After each read, the application needs to call fBufSetBuffer(). * Note that fBufSetBuffer() sets the collector and exporter on the fBuf to * NULL. The application should clear the FB_ERROR_BUFSZ and/or FB_ERROR_EOM * error when they occur using g_clear_error(). * * fixbuf may return the following error codes if it encounters one * of the below issues. The application should determine the error and * respond appropriately. * * - FB_ERROR_IPFIX * - If the first 2 bytes != 0x000A * - If the length in the header < 16 * - FB_ERROR_EOM * - If the application read only the message length and the application * called fBufSetAutomatic(fbuf, FALSE) (the fBuf is in manual mode). * This means the remaining buffer length == 0 and the application * should clear the error and perform another read * - FB_ERROR_BUFSZ * - If the header message length > the given buffer length * - if the given buffer == NULL * - If the given buffer length < 16 * - If buffer length == 0 * * * Example usage: * \code{.c} * FILE *fp; * uint8_t buf[65535]; * ... * rc = fread(buf, 1, 4, fp); * if (rc > 0) { * len = ntohs(*((uint16_t *)(buf+2))); * rc = fread(buf+4, 1, len-4, fp); * if (rc > 0) { * fBufSetBuffer(fbuf, buf, rc+4); * } else if (feof(fp)) * .... * while (1) { * ret = fBufNext(fbuf, (uint8_t *)rec, &len, &err); * if (FALSE == ret) { * if (g_error_matches(err, FB_ERROR_DOMAIN, FB_ERROR_BUFSZ)){ * rem = fBufRemaining(fbuf); * g_clear_error(&err); * break; * } * } * } * \endcode * * @page lists Lists in IPFIX * * How-To deal with BasicLists, SubTemplateLists, & SubTemplateMultiLists: * * @section general General Information * Each of the list structures uses a nested list of data. * The basic list nests a single information element, while the others use a * nested template. The template used for nesting is part of the listed * templates sent to the collector when the connection is made, or when the * data transfer begins. There is no way to mark a template from this list as * one that will be nested, or one that will be used as the highest level * template. Each of the templates in the list are treated as equals. * * The collector does not learn which template or information element is nested * until the data arrives. This requires flexbility in the collectors to * handle each of the possible results. * * @subsection internalTemplates Internal Templates for Sub Templates * The setting of the internal template has not changed with the addition of * the list structures. The internal template is still used to perform the * initial decoding of the data that arrives at the collector. * * Basic lists are not transcoded in the same way as templates because they * contain just one information element, thus having no order, so the data can * just be parsed and copied to a buffer. * * The question with decoding sub templates becomes, what do we use as an * internal template for any sub templates that arrive? The answer is a new * structure in fixbuf that pairs external and internal template IDs for use * in decoding sub templates. The pairs are added to the session that is used * for the connection, using fbSessionAddTemplatePair(). * * Because the external template IDs are only unique for that session, the * collector must know the IDs of the templates that are collected in order to * pair an internal template with the external template. As a result, callback * functionality has been added to fixbuf to alert the user when a new external * template has arrived. The callback functions are stored in the session * structure, which manages the templates. fbNewTemplateCallback_fn gives the * application a pointer to the template structure, allowing the * application to determine the contents of the template, a template ID to * identify the incoming template, and the session pointer. * This information is sufficient for the application to successfully * add template pairs to the session for sub template decoding. * * The other callback function, fbTemplateCtxCallback2_fn gives the * application the session pointer, the template, the template ID, as well * as a context variable that is stored for the application in the template. * The callback also gives the user another callback that can be used to * free the context variable upon template deletion. * * If the application does not use the callback, or does not add any template * pairs to the session, then fixbuf will transcode each of the sub templates * as if the external and internal template were same. This causes all of the * fields sent over the wire to be transcoded into the data buffer on the * collecting side. The details of that template are passed up to the * collector upon receipt of data so it knows how the data is structured in * the buffer. * * If the application adds any template pair to the list, then the list will be * referenced for each transcode. Any external template the application * wishes to process MUST have an entry in the list. * There are 3 cases for entries in the list: * -# There is no entry for the given external template ID, so the entire * sub template is ignored by the transcoder. * The collector will be given a sub template list (or multi list entry) * struct with the number of elements in the list set to 0, and the data * pointer set to NULL. * -# The listing exists, and the external and internal template IDs are set * to the same value. When decoding, the list of internal templates is * queried to see if a template exists with the same ID as the external * template. If not, the transcoder decodes each of the * information elements, in the same order, into the buffer. This is a * change as setting them equal to each other used to force a full decode. * This change highlights the need for careful template ID management. * -# The listing exists, and the external and internal template IDs are * different. This will transcode in the standard way external templates * have been transcoded into internal templates, selecting the desired * elements (listed in the internal template) from the data that arrived * in the external template. * * * * @subsection iterating Iterating Over the Lists * There are four scenerios in which the user needs to iterate through the * elements in a list, whether to fill in, or process the data: * -# Iterating over the repeated information element data in a basic list * -# Iterating over the decoded data elements in a sub template list * -# Iterating over the entries that make up a sub template multi list * -# Iterating over the docoded data elements in an entry of a sub template * multi list * The two iterating mechanisms are the same in each case: * Each of the function names start with the structure being iterated over, * e.g., fbBasicList, or fbSubTemplateMultiListEntry * -# Indexing * The function used here is (structName)GetIndexed(dataPtr or entry)() * It takes a pointer to the struct, and the index to be retrieved. * Example usage: * for(i = 0; myStructPtr = ...GetIndexedDataPtr(listPtr, i); i++) { * process the data that myStructPtr points to. * } * The loop will end because when i is passed the bounds of the list * the GetIndexedDataPtr() returns NULL. * * -# Incrementing * The function used here is (structName)GetNext(dataPtr or entry)() * It takes a pointer to the struct, and a pointer to an element in the * list. Pass in NULL at the beginning to get the first element back. * Example usage: * \code{.c} * myStructPtr = NULL; * while(myStructPtr = ...GetNextPtr(listPtr, myStructPtr)) { * process the data that myStructPtr points to. * } * \endcode * The loop will end because the function will return NULL when * it gets passed the end of the list. A key part here is * initializing myStructPtr to NULL at the beginning! * * @page rfc_5610 RFC 5610 * * What is RFC 5610? * * RFC 5610 provides a mechanism to export full type information for * Information Elements from the IPFIX Information Model. Libfixbuf * version 1.4 and later provides API functions to create IPFIX * Option Template/Records that can encode the full set of properties * for the definition of an Information Element in order for a * Collecting Process to be able to know how to decode data that * contains enterprise -specific Information Elements. * * @section exp RFC 5610 Exporters * * To create a new enterprise-specific Information Element, the * Exporting Process should define a new information element using * the FB_IE_INIT_FULL macro to provide the name, private enterprise * number, id, length, description, data type, and units of the * information element. The Information Elements should then be * added to the Information Model using fbInfoModelAddElement() or * fbInfoModelAddElementArray(). * * An options template can then be created using * fbInfoElementAllocTypeTemplate(). This creates an option template * that contains all of the necessary properties to define an * Information Element: * * -informationElementRangeBegin * -informationElementRangeEnd * -privateEnterpriseNumber * -informationElementUnits * -informationElementId * -informationElementDataType * -informationElementSemantics * -paddingOctets * -informationElementName * -informationElementDescription * * Then the template can be added to the session using * fbSessionAddTemplate(). Create the exporter and fbuf as * described above for the necessary mode of transport. In order * to use the above template, set the internal template to the * to the options template created above using the template id * that was returned by fbSessionAddTemplate() using fBufSetInternalTemplate(). * Use fBufSetExportTemplate() to set the external template * on the fBuf, then use fbInfoElementWriteOptionsRecord() with * the enterprise-specific Information Element. For Example: * \code{.c} * fbInfoElementWriteOptionsRecord(fbuf, fbInfoModelGetElementByName(infoModel, "myNewElement"), tid, err); * \endcode * * The Options Record will automatically be appended to the fbuf * and will be sent upon calling fBufEmit(). * * @section col RFC 5610 - Collector Usage * * In order to collect the above Options records, the collecting * process can manually define the above Options Template and * provide a template callback function to collect and add * each element to the Information Model using * fbInfoElementAddOptRecElement() and fbInfoModelTypeInfoRecord(). * * OR - the collector can simply use fBufSetAutomaticInsert() * after creating an fBuf to automatically insert any information * elements into the Information Model. Use the FB_IE_UNITS() * and FB_IE_SEMANTIC() macros to query the flags field for the * appropriate field. * */ /** * @file * * Fixbuf IPFIX protocol library public interface * */ #ifndef _FB_PUBLIC_H_ #define _FB_PUBLIC_H_ #include #ifdef __cplusplus extern "C" { #endif #ident "$Id$" /* * Error Handling Definitions */ /** All fixbuf errors are returned within the FB_ERROR_DOMAIN domain. */ #define FB_ERROR_DOMAIN g_quark_from_string("fixbufError") /** No template was available for the given template ID. */ #define FB_ERROR_TMPL 1 /** * End of IPFIX message. Either there are no more records present in the * message on read, or the message MTU has been reached on write. */ #define FB_ERROR_EOM 2 /** * End of IPFIX Message stream. No more messages are available from the * transport layer on read, either because the session has closed, or the * file has been processed. */ #define FB_ERROR_EOF 3 /** * Illegal IPFIX mesaage content on read. The input stream is malformed, or * is not an IPFIX Message after all. */ #define FB_ERROR_IPFIX 4 /** * A message was received larger than the collector buffer size. * Should never occur. This condition is checked at the transport layer * in case future versions of fixbuf support dynamic buffer sizing. */ #define FB_ERROR_BUFSZ 5 /** The requested feature is not yet implemented. */ #define FB_ERROR_IMPL 6 /** An unspecified I/O error occured. */ #define FB_ERROR_IO 7 /** * No data is available for reading from the transport layer. * Either a transport layer read was interrupted, or timed out. */ #define FB_ERROR_NLREAD 8 /** * An attempt to write data to the transport layer failed due to * closure of the remote end of the connection. Currently only occurs with * the TCP transport layer. */ #define FB_ERROR_NLWRITE 9 /** * The specified Information Element does not exist in the Information Model. */ #define FB_ERROR_NOELEMENT 10 /** * A connection or association could not be established or maintained. */ #define FB_ERROR_CONN 11 /** * Illegal NetflowV9 content on a read. Can't parse the Netflow header or * the stream is not a NetflowV9 stream */ #define FB_ERROR_NETFLOWV9 12 /** * Miscellaneous error occured during translator operation */ #define FB_ERROR_TRANSMISC 13 /** * Illegal sFlow content on a read. */ #define FB_ERROR_SFLOW 14 /* * Public Datatypes and Constants */ struct fBuf_st; /** * An IPFIX message buffer. Used to encode and decode records from * IPFIX Messages. The internals of this structure are private to * libfixbuf. */ typedef struct fBuf_st fBuf_t; /** * A variable-length field value. Variable-length information element * content is represented by an fbVarfield_t on the internal side of the * transcoder; that is, variable length fields in an IPFIX Message must be * represented by this structure within the application record. */ typedef struct fbVarfield_st { /** Length of content in buffer. */ size_t len; /** * Content buffer. In network byte order as appropriate. On write, this * buffer will be copied into the message buffer. On read, this buffer * points into the message buffer and must be copied by the caller before * any call to fBufNext(). */ uint8_t *buf; } fbVarfield_t; struct fbInfoModel_st; /** * An IPFIX information model. Contains information element definitions. * The internals of this structure are private to libfixbuf. */ typedef struct fbInfoModel_st fbInfoModel_t; /** * An iterator over the information elements in an information model. */ typedef struct fbInfoModelIter_st { /** * information Model */ const fbInfoModel_t *model; /** * iterator index */ guint index; } fbInfoModelIter_t; /** * NEW Convenience macro for creating full fbInfoElement_t static initializers. * Used for creating information element arrays suitable for passing to * fbInfoModelAddElementArray(). */ #define FB_IE_INIT_FULL(_name_, _ent_, _num_, _len_, _flags_, _min_, _max_, _type_, _desc_)\ { {(const struct fbInfoElement_st*)_name_}, 0, _ent_, _num_, _len_, _flags_, _min_, _max_, _type_, _desc_ } /** * Convenience macro for creating default fbInfoElement_t static initializers. * Used for creating information element arrays suitable for passing to * fbInfoModelAddElementArray(). */ #define FB_IE_INIT(_name_, _ent_, _num_, _len_, _flags_) \ FB_IE_INIT_FULL(_name_, _ent_, _num_, _len_, _flags_, 0, 0, 0, (char*)NULL) /** * Convenience macro defining a null information element initializer to * terminate a constant information element array for passing to * fbInfoModelAddElementArray(). */ #define FB_IE_NULL FB_IE_INIT(NULL, 0, 0, 0, 0) /** * Convenience macro for extracting the information element * semantic value from the flags variable in the fbInfoElement_t struct * */ #define FB_IE_SEMANTIC(flags) ((flags & 0x0000ff00) >> 8) /** * Convenience macro for extracting the information element * units value from the flags variable in the fbInfoElement_t struct * */ #define FB_IE_UNITS(flags) ((flags & 0xFFFF0000) >> 16) /** * Default treatment flags value. Provided for initializer convenience. * Corresponds to octet-array semantics for a non-reversible, non-alien IE. */ #define FB_IE_F_NONE 0x00000000 /** * Information element endian conversion flag. If set, IE is an integer and * will be endian-converted on transcode. */ #define FB_IE_F_ENDIAN 0x00000001 /** * Information element reversible flag. If set for an information element * with an enterprise number of 0 (an IETF/IANA IE), adding the information * element via fbInfoModelAddElement() or fbInfoModelAddElementArray() will * cause a second, reverse information element to be added to the model * following the conventions in IETF Internet-Draft draft-ietf-ipfix-biflow-03. * Note that the reverse PEN has not yet been assigned, so this implementation * uses a provisional reverse IE as defined by the macro FB_IE_PEN_REVERSE. */ #define FB_IE_F_REVERSIBLE 0x00000040 /** * Information element alien flag. If set, IE is enterprise-specific and was * recieved via an external template at a Collecting Process. It is therefore * subject to semantic typing via options (not yet implemented). Do not set this * flag on information elements added programmatically to an information model * via fbInfoModelAddElement() or fbInfoModelAddElementArray(). */ #define FB_IE_F_ALIEN 0x00000080 /** * An Information Element Semantics Flags used to describe an information * element as a quantity. */ #define FB_IE_QUANTITY 0x00000100 /** * An Information Element Semantics Flags used to describe an information * element as a totalCounter. * */ #define FB_IE_TOTALCOUNTER 0x00000200 /** * An Information Element Semantics Flag used to describe an information * element as a deltaCounter. */ #define FB_IE_DELTACOUNTER 0x00000300 /** * An Information Element Semantics Flag used to describe an information * element as an identifier. */ #define FB_IE_IDENTIFIER 0x00000400 /** * An Information Element Semantics Flag used to describe an information * element as a flags element. */ #define FB_IE_FLAGS 0x00000500 /** * An Information Element Semantics Flag used to describe an information * element as a List Element. * */ #define FB_IE_LIST 0x00000600 /** * An Information Element Semantics Flag used to describe an information * element as a Default element. * */ #define FB_IE_DEFAULT 0x00000000 /** * Information Element Units - See RFC 5610 * */ /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_BITS 0x00010000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_OCTETS 0x00020000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_PACKETS 0x00030000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_FLOWS 0x00040000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_SECONDS 0x00050000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_MILLISECONDS 0x00060000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_MICROSECONDS 0x00070000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_NANOSECONDS 0x00080000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_WORDS 0x00090000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_MESSAGES 0x000A0000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_HOPS 0x000B0000 /** * An Information Element Units Flag used to describe the units * of an information element. See RFC 5610 * */ #define FB_UNITS_ENTRIES 0x000C0000 /** * An Information Element Units Flag used to describe the units * of an information element. Recently added for layer 2 frames * */ #define FB_UNITS_FRAMES 0x000D0000 /** * Information element length constant for variable-length IE. */ #define FB_IE_VARLEN 65535 /** * Information element number constant for basic lists * This will change upon updates to the specification. */ #define FB_IE_BASIC_LIST 291 /** * Information element number constant for sub template lists * This will change upon updates to the IPFIX lists specification */ #define FB_IE_SUBTEMPLATE_LIST 292 /** * Information element number constant for sub template multi lists * This will change upon updates to the IPFIX lists specification */ #define FB_IE_SUBTEMPLATE_MULTILIST 293 /** * Private enterprise number for reverse information elements * (see draft-ietf-ipfix-biflow-03 section 6.1). If an information element with * FB_IE_F_REVERSIBLE and a zero enterprise number (i.e., an IANA-assigned * information element) is added to a model, the reverse IE will be generated * by setting the enterprise number to this constant. */ #define FB_IE_PEN_REVERSE 29305 /** * Reverse information element bit for vendor-specific information elements * (see draft-ietf-ipfix-biflow-03 section 6.2). If an information element with * FB_IE_F_REVERSIBLE and a non-zero enterprise number (i.e., a vendor-specific * information element) is added to a model, the reverse IE number will be * generated by ORing this bit with the given forward information element * number. */ #define FB_IE_VENDOR_BIT_REVERSE 0x4000 /** * Generic Information Element ID for undefined Cisco NetFlow v9 Elements. * * */ #define FB_CISCO_GENERIC 9999 /** * Information Element ID for Cisco NSEL Element NF_F_FW_EVENT often * exported by Cisco's ASA Device. This must be converted to a different * Information Element ID due to the reverse IE bit in IPFIX. * Cisco uses IE ID 40005. * http://www.cisco.com/en/US/docs/security/asa/asa82/netflow/netflow.html */ #define FB_CISCO_ASA_EVENT_ID 9998 /** * Information Element ID for Cisco NSEL Element NF_F_FW_EXT_EVENT often * exported by Cisco's ASA Device. This must be converted to a different * Information Element ID due to the reverse IE bit in IPFIX. * Cisco uses IE ID 33002 * http://www.cisco.com/en/US/docs/security/asa/asa82/netflow/netflow.html * More Information about event codes can be found here: * http://www.cisco.com/en/US/docs/security/asa/asa84/system/netflow/netflow.pdf */ #define FB_CISCO_ASA_EVENT_XTRA 9997 /** * Reverse information element name prefix. This string is prepended to an * information element name, and the first character after this string * is capitalized, when generating a reverse information element. */ #define FB_IE_REVERSE_STR "reverse" /** Length of reverse information element name prefix. */ #define FB_IE_REVERSE_STRLEN 7 /** * From RFC 5610: A description of the abstract data type of an IPFIX * information element as registered in the IANA IPFIX IE Data Type * subregistry. */ typedef enum fbInfoElementDataType_en { FB_OCTET_ARRAY, FB_UINT_8, FB_UINT_16, FB_UINT_32, FB_UINT_64, FB_INT_8, FB_INT_16, FB_INT_32, FB_INT_64, FB_FLOAT_32, FB_FLOAT_64, FB_BOOL, FB_MAC_ADDR, FB_STRING, FB_DT_SEC, FB_DT_MILSEC, FB_DT_MICROSEC, FB_DT_NANOSEC, FB_IP4_ADDR, FB_IP6_ADDR, FB_BASIC_LIST, FB_SUB_TMPL_LIST, FB_SUB_TMPL_MULTI_LIST } fbInfoElementDataType_t; /** * A single IPFIX Information Element definition. * An Information Element defines the type of data in each field of * a record. This structure may be contained in an fbInfoModel_t, * in which case the name field contians the information element name, * or an an fbTemplate_t, in which case the canon field references the * fbInfoElement_t contained within the Information Model. */ typedef struct fbInfoElement_st { /** Information element name. */ union { /** * Pointer to canonical copy of IE. * Set by fbInfoElementCopyToTemplate(), * and valid only for template IEs. */ const struct fbInfoElement_st *canon; /** * Information element name. Storage for this is managed * by fbInfoModel. Valid only for model IEs. */ const char *name; } ref; /** * Multiple IE index. Must be 0 for model IEs. * Defines the ordering of identical IEs in templates. * Set and managed automatically by the fbTemplate_t routines. */ uint32_t midx; /** Private Enterprise Number. Set to 0 for IETF-defined IEs. */ uint32_t ent; /** * Information Element number. Does not include the on-wire * enterprise bit; i.e. num & 0x8000 == 0 even if ent > 0. */ uint16_t num; /** Information element length in octets. */ uint16_t len; /** Flags. Bitwise OR of FB_IE_F_* constants. */ /** Use Macros to get units and semantic */ uint32_t flags; /** range min */ uint64_t min; /** range max */ uint64_t max; /** Data Type */ uint8_t type; /** description */ const char *description; } fbInfoElement_t; /** * The corresponding struct to the Information Element Type Options Template. * If collecting this element, use the function fbInfoElementAddOptRecElem() * to add this element to the info model. * */ typedef struct fbInfoElementOptRec_st { /** ie range min */ uint64_t ie_range_begin; /** ie range max */ uint64_t ie_range_end; /** private enterprise number */ uint32_t ie_pen; /** ie units */ uint16_t ie_units; /** information element id */ uint16_t ie_id; /** ie data type */ uint8_t ie_type; /** ie semantic */ uint8_t ie_semantic; /** padding to align with template */ uint8_t padding[6]; /** information element name */ fbVarfield_t ie_name; /** information element description */ fbVarfield_t ie_desc; } fbInfoElementOptRec_t; /** * Template ID argument to pass to fbSessionAddTemplate to automatically * assign a template ID. */ #define FB_TID_AUTO 0 /** * Reserved set ID for template sets. */ #define FB_TID_TS 2 /** * Reserved set ID for options template sets. */ #define FB_TID_OTS 3 /** * Minimum non-reserved template ID available for data sets. */ #define FB_TID_MIN_DATA 256 struct fbTemplate_st; /** * An IPFIX Template or Options Template. Templates define the structure of * data records and options records within an IPFIX Message. * The internals of this structure are private to libfixbuf. */ typedef struct fbTemplate_st fbTemplate_t; /** * Convenience macro defining a null information element specification * initializer to terminate a constant information element specifier array * for passing to fbTemplateAppendSpecArray(). */ #define FB_IESPEC_NULL { NULL, 0, 0 } /** * A single IPFIX Information Element specification. * Used to name an information element for inclusion in a template by * fbTemplateAppendSpecArray(). */ typedef struct fbInfoElementSpec_st { /** Information element name */ char *name; /** * Length override; if nonzero, replace the length of the IE from the * model with this length. Used for reduced-length encoding. */ uint16_t len_override; /** * Application flags word. If nonzero, then the flags argument to * fbTemplateAppendSpec() or fbTemplateAppendSpecArray() MUST match at * least one bit of this flags word in order for the information element * to be appended. */ uint32_t flags; } fbInfoElementSpec_t; struct fbSession_st; /** * An IPFIX Transport Session state container. Though Session creation and * lifetime are managed by the fbCollector_t and fbExporter_t types, each * fBuf_t buffer uses this type to store session state, including internal * and external Templates and Message Sequence Number information. */ typedef struct fbSession_st fbSession_t; /** Transport protocol for connection specifier. */ typedef enum fbTransport_en { /** * Partially reliable datagram transport via SCTP. * Only available if fixbuf was built with SCTP support. */ FB_SCTP, /** Reliable stream transport via TCP. */ FB_TCP, /** Unreliable datagram transport via UDP. */ FB_UDP, /** * Secure, partially reliable datagram transport via DTLS over SCTP. * Only available if fixbuf was built with OpenSSL support. * Requires an OpenSSL implementation of DLTS over SCTP, not yet available. */ FB_DTLS_SCTP, /** * Secure, reliable stream transport via TLS over TCP. * Only available if fixbuf was built with OpenSSL support. */ FB_TLS_TCP, /** * Secure, unreliable datagram transport via DTLS over UDP. * Only available if fixbuf was built with OpenSSL support. * Requires OpenSSL 0.9.8 or later with DTLS support. */ FB_DTLS_UDP, } fbTransport_t; /** * Connection specifier. Used to define a peer address for fbExporter_t, or a * passive address for fbListener_t. */ typedef struct fbConnSpec_st { /** Transport protocol to use */ fbTransport_t transport; /** Hostname to connect/listen to. NULL to listen on all interfaces. */ char *host; /** Service name or port number to connect/listen to. */ char *svc; /** Path to certificate authority file. Only used for OpenSSL transport. */ char *ssl_ca_file; /** Path to certificate file. Only used for OpenSSL transport. */ char *ssl_cert_file; /** Path to private key file. Only used for OpenSSL transport. */ char *ssl_key_file; /** Private key decryption password. Only used for OpenSSL transport. */ char *ssl_key_pass; /** * Pointer to address info cache. Initialize to NULL. * For fixbuf internal use only. */ void *vai; /** * Pointer to SSL context cache. Initialize to NULL. * For fixbuf internal use only. */ void *vssl_ctx; } fbConnSpec_t; /** * Convenience macro defining a null static fbConnSpec_t. */ #define FB_CONNSPEC_INIT { FB_SCTP, NULL, NULL, \ NULL, NULL, NULL, NULL, \ NULL, NULL } #if HAVE_SPREAD /** * Spread connection parameters. Used to define a spread daemon and group * or list of groups for spread. */ #define FB_SPREADPARAMS_INIT { 0, 0, 0 } typedef struct fbSpreadParams_st { /** pointer to the session, this MUST be set to a valid session before * the spec is passed to fbExporterAllocSpread. */ fbSession_t * session; /** pointer to the daemon host address, in Spread format. Must be set * before the spec is passed to fbExporterAllocSpread */ char * daemon; /** pointer to array of group names, must have at least one, and must * be null term array */ char ** groups; } fbSpreadParams_t; #endif /* HAVE_SPREAD */ struct fbExporter_st; /** * IPFIX Exporting Process endpoint. Used to export messages from an associated * IPFIX Message Buffer to a remote Collecting Process, or to an IPFIX File. * The internals of this structure are private to libfixbuf. */ typedef struct fbExporter_st fbExporter_t; struct fbCollector_st; /** * IPFIX Collecting Process endpoint. Used to collect messages into an * associated IPFIX Message Buffer from a remote Exporting Process, or from * an IPFIX File. Use this with the fbListener_t structure to implement a full * Collecting Process, including Transport Session setup. The internals of * this structure are private to libfixbuf. */ typedef struct fbCollector_st fbCollector_t; struct fbListener_st; /** * IPFIX Collecting Process session listener. Used to wait for connections * from IPFIX Exporting Processes, and to manage open connections via a * select(2)-based mechanism. The internals of this structure are private * to libfixbuf. */ typedef struct fbListener_st fbListener_t; /** * ListenerGroup and associated data type definitions */ typedef struct fbListenerEntry_st fbListenerEntry_t; /** * ListenerEntry's make up a listener group as a linked list */ struct fbListenerEntry_st { /** pointer to the next listener entry in the linked list */ fbListenerEntry_t *next; /** pointer to the previous listener entry in the linked list */ fbListenerEntry_t *prev; /** pointer to the listener to add to the list */ fbListener_t *listener; }; /** * typedef for listener group result */ typedef struct fbListenerGroupResult_st fbListenerGroupResult_t; /** * ListenerGroupResult's contain the listener who's listening socket got a new * connection. It is tied to the fBuf_t that is produced for the connection * These make up a linked list as well */ struct fbListenerGroupResult_st { /** Pointer to the next listener group result */ fbListenerGroupResult_t *next; /** pointer to the listener that received a new connection */ fbListener_t *listener; /** pointer to the fbuf created for that new connection */ fBuf_t *fbuf; }; struct fbListenerGroup_st; /** * Structure that holds the listeners that are added to the group. */ typedef struct fbListenerGroup_st fbListenerGroup_t; /** * The callback function to be called when the session receives a new * external template from the connected node. * The point of this callback is to be able to assign an internal template * to a received external template for subTemplates or to apply some * context variable to a template. * The callback should be set using fbSessionAddTemplateCallback() and * that function should be called upon session creation. Libfixbuf often * clones sessions upon receiving a connection (particularly in the UDP case) * and this callback function is carried over to cloned sessions. * * @param session a pointer to the session that received the template * @param tid the template ID for the template that was received * @param tmpl pointer to the template information of the received template * @return NO return value */ typedef void (*fbNewTemplateCallback_fn) ( fbSession_t *session, uint16_t tid, fbTemplate_t *tmpl); /** * A callback function that is called when a template is freed. The free * function should be set during the fbTemplateCtxCallback. * * @param ctx a pointer to the ctx that is stored within the fbTemplate. * @return NO return value */ typedef void (*fbTemplateCtxFree_fn)( void *ctx); /** * A callback function that is called when a template is freed. The free * function should be set during the fbTemplateCtxCallback2. * * @param tmpl_ctx a pointer to the ctx that is stored within the fbTemplate. * @param app_ctx the app_ctx pointer that was passed to the * fbSessionAddTemplateCtxCallback2() call * @return NO return value */ typedef void (*fbTemplateCtxFree2_fn)( void *tmpl_ctx, void *app_ctx); /** * A callback function that will be called when the session receives * a new external template. This callback can be used to assign an * internal template to an incoming external template for nested template * records using fbSessionAddTemplatePair() or to apply some context variable * to a template. The fbNewTemplateCallback_fn is retained for backwards * compatibility. * * The callback should be set using fbSessionAddTemplateCtxCallback() and * that function should be called after fbSessionAlloc(). Libfixbuf often * clones session upon receiving a connection (particularly in the UDP case * since a collector and fbuf can have multiple sessions) and this callback * is carried over to cloned sessions. * * This callback function does not provide a way for the caller to pass * their application's context into the function for making a C closure. * For that, use fbSessionAddTemplateCtxCallback2(). * * @param session a pointer to the session that received the template * @param tid the template ID for the template that was received * @param tmpl pointer to the template information of the received template * @param ctx pointer that is stored in the fbTemplate structure. * @param fn a callback function that should be called to free the ctx * when the template is freed/replaced. * @return NO return value **/ typedef void (*fbTemplateCtxCallback_fn) ( fbSession_t *session, uint16_t tid, fbTemplate_t *tmpl, void **ctx, fbTemplateCtxFree_fn *fn); /** * A callback function that will be called when the session receives * a new external template. This callback can be used to assign an * internal template to an incoming external template for nested template * records using fbSessionAddTemplatePair() or to apply some context variable * to a template. The fbNewTemplateCallback_fn is retained for backwards * compatibility. * * The callback should be set using fbSessionAddTemplateCtxCallback2() and * that function should be called after fbSessionAlloc(). Libfixbuf often * clones session upon receiving a connection (particularly in the UDP case * since a collector and fbuf can have multiple sessions) and this callback * is carried over to cloned sessions. * * @param session a pointer to the session that received the template * @param tid the template ID for the template that was received * @param tmpl pointer to the template information of the received template * @param app_ctx the app_ctx pointer that was passed to the * fbSessionAddTemplateCtxCallback2() call * @param tmpl_ctx pointer that is stored in the fbTemplate structure. * @param fn a callback function that should be called to free the ctx * when the template is freed/replaced. * @return NO return value **/ typedef void (*fbTemplateCtxCallback2_fn) ( fbSession_t *session, uint16_t tid, fbTemplate_t *tmpl, void *app_ctx, void **tmpl_ctx, fbTemplateCtxFree2_fn *fn); /** * The following Semantic values are for use in the structured Data Types: * basicLists, subTemplateLists, and subTemplateMultiLists. */ /** * Semantic field for indicating the value has not been set */ #define FB_LIST_SEM_UNDEFINED 0xFF /** * Semantic field for none-of value defined in RFC 6313 */ #define FB_LIST_SEM_NONE_OF 0x00 /** * Semantic field for exactly-one-of value defined in RFC 6313 */ #define FB_LIST_SEM_EXACTLY_ONE_OF 0x01 /** * Semantic field for the one-or-more-of value defined in RFC 6313 */ #define FB_LIST_SEM_ONE_OR_MORE_OF 0x02 /** * Semantic field for the all-of value defined in RFC 6313 */ #define FB_LIST_SEM_ALL_OF 0x03 /** * Semantic field for the ordered value defined in RFC 6313 */ #define FB_LIST_SEM_ORDERED 0x04 /** * validates the value of the semantic field, * * @param semantic The value of the semantic field to be validated * * @return TRUE is valid {0xFF, 0x00-0x04}, FALSE if not */ gboolean fbListValidSemantic( uint8_t semantic); /****** BASICLIST FUNCTIONS AND STRUCTS *******/ /** * A basic list element in a template which structure represents a * basic list on the internal side, basic lists in an IPFIX Message must * be represented by this structure within the application record. */ typedef struct fbBasicList_st { /** pointer to the information element that is repeated in the list */ const fbInfoElement_t *infoElement; /** pointer to the memory that stores the elements in the list */ uint8_t *dataPtr; /** number of elements in the list */ uint16_t numElements; /** length of the buffer used to store the elements in the list */ uint16_t dataLength; /** semantic field to describe the list */ uint8_t semantic; } fbBasicList_t; /** * allocates a Basic List Structure * * @return a pointer a to the allocated basic list in memory */ fbBasicList_t* fbBasicListAlloc( void); /** * Initializes the basic list structure based on the parameters. * This function allocates a buffer large enough to hold * num elements amount of the infoElements. * * @param basicListPtr a pointer to the basic list structure to fill * @param semantic the semantic value to be used in the basic list * @param infoElement a pointer to the info element to be used in the list * @param numElements number of elements in the list * @return a pointer to the memory where the list data is to be written */ void* fbBasicListInit( fbBasicList_t *basicListPtr, uint8_t semantic, const fbInfoElement_t *infoElement, uint16_t numElements); /** * use this function to initialize the basic list, but it gets the pointer * to a buffer and its length allocated independently from these functions * This will generally be used by a collector that does not want to * free and allocate new buffers for each incoming message * * @param basicListPtr a pointer to the basic list structure to fill * @param semantic the semantic value to be used in the basic list * @param infoElement a pointer to the info element to be used in the list * @param numElements number of elements in the list * @param dataLength length of the buffer passed to the function * @param dataPtr pointer to the buffer previously allocated for the list * @return a pointer to the beginning of the buffer on success, NULL on failure */ void* fbBasicListInitWithOwnBuffer( fbBasicList_t *basicListPtr, uint8_t semantic, const fbInfoElement_t *infoElement, uint16_t numElements, uint16_t dataLength, uint8_t *dataPtr); /** * This initializes a basic list structure for collection. The key * part of this function is it sets the dataPtr to NULL. * If your basic list is declared as a pointer, then allocated using * something like g_slice_alloc0 which sets it all to zero, you do not * need to call this function. But if your basic list struct isn't * a pointer, there dataPtr parameter will be set to garbage, which will * break other fixbuf calls, so this function is required * * @param basicListPtr pointer to the basic list to be initialized * @return NONE */ void fbBasicListCollectorInit( fbBasicList_t *basicListPtr); /** * Get Semantic field for Basic List * presumably used in collectors after decoding * * @param basicListPtr pointer to the basic list to retrieve the semantic from * @return the 8-bit semantic value describing the basic list */ uint8_t fbBasicListGetSemantic( fbBasicList_t *basicListPtr); /** * Sets the semantic for describing a basic list * generally used in exporters before decoding * * @param basicListPtr pointer to the basic list to set the semantic * @param semantic value to set the semantic field to * @return NONE */ void fbBasicListSetSemantic( fbBasicList_t *basicListPtr, uint8_t semantic); /** * This function returns a pointer to the information element used in the list * it is mainly used in collectors to retrieve information * * @param basicListPtr pointer to the basic list to get the infoElement from * @return pointer to the information element from the list */ const fbInfoElement_t* fbBasicListGetInfoElement( fbBasicList_t *basicListPtr); /** * * @param basicListPtr pointer to the basic list to get the data pointer from * @return the pointer to the data held by the basic list */ void* fbBasicListGetDataPtr( fbBasicList_t *basicListPtr); /** * Function retrieves the index'th element in the list * index is 0-based. Goes from 0 - (numElements-1) * @param basicListPtr pointer to the basic list to retrieve the dataPtr * @param bl_index the index of the element to retrieve * @return a pointer to the data in the index'th slot in the list, NULL * if the index is past the bounds of the list */ void* fbBasicListGetIndexedDataPtr( fbBasicList_t *basicListPtr, uint16_t bl_index); /** * Function returns the next element in the list based on the currentPtr * @param basicListPtr pointer to the basic list * @param currentPtr pointer to the current element being used. Set to NULL * to retrieve the first element. * @return a pointer to the next data slot, based on the current pointer. * NULL if the new pointer is passed the end of the buffer */ void* fbBasicListGetNextPtr( fbBasicList_t *basicListPtr, void *currentPtr); /** * Free the current data pointer, allocating a new buffer to accomodate * the new number of elements. The remaining parameters are unchanged. * If the number of elements hasn't changed * the original buffer is used and its pointer is returned * @param basicList pointer to the basic list to realloc * @param newNumElements new number of elements to allocate for the list * @return pointer to the data pointer for the list after realloc */ void* fbBasicListRealloc( fbBasicList_t *basicList, uint16_t newNumElements); /** * Allocates an additional elememnt into the basic list * must be called after calling BasicListInit * @param basicList pointer to the basic list to add elements to * @param numNewElements number of elements to add to the list * @return a pointer to the newly allocated element(s) */ void* fbBasicListAddNewElements( fbBasicList_t *basicList, uint16_t numNewElements); /** * Clear the parameters of the basic list and free the data buffer * @param basicListPtr pointer to the basic list to clear * @return NONE */ void fbBasicListClear( fbBasicList_t *basicListPtr); /** * Clear the parameters of the basic list, but do not free the buffer. * This should get used when the user provides their own buffer * @param basicList pointer to the basic list to clear without freeing * @return NONE */ void fbBasicListClearWithoutFree( fbBasicList_t *basicList); /** * Clear the basic list, then free the basic list pointer * @param basicListPtr pointer to the basic list to free * @return NONE */ void fbBasicListFree( fbBasicList_t *basicListPtr); /******* END OF BASICLIST ********/ /******* SUBTEMPLATELIST FUNCTIONS ****/ /** * Structure used to hold information of a sub template list. * This structure is filled in by the user in an exporter to tell * fixbuf how to encode the data. * This structure is filled in by the transcoder in a collector, * feeding the useful information up to the user */ typedef struct fbSubTemplateList_st { /** length of the allocated buffer used to hold the data */ /** I made this a union to allow this to work on 64-bit archs */ union { size_t length; uint64_t extra; } dataLength; /** pointer to the template used to structure the data */ const fbTemplate_t *tmpl; /** pointer to the buffer used to hold the data */ uint8_t *dataPtr; /** ID of the template used to structure the data */ uint16_t tmplID; /** number of elements in the list */ uint16_t numElements; /** value used to describe the contents of the list, all-of, one-of, etc*/ uint8_t semantic; } fbSubTemplateList_t; /** * Allocates a subTemplateList_t * Based on how subTemplateLists will be used and set up amidst data * structures, this function may never be used * @return pointer to the new sub template list */ fbSubTemplateList_t* fbSubTemplateListAlloc( void); /** * Initializes a subTemplateList structure and alloc's the dataPtr * to get a buffer able to hold numElements in the template * This will mainly be used in exporters preparing to encode * * @param sTL pointer to the sub template list to initialize * @param semantic the semantic value used to describe the list contents * @param tmplID id of the template used for encoding the list data * @param tmpl pointer to the template struct used for encoding the list data * @param numElements number of elements in the list * @return a pointer to the allocated buffer (location of first element) */ void* fbSubTemplateListInit( fbSubTemplateList_t *sTL, uint8_t semantic, uint16_t tmplID, const fbTemplate_t *tmpl, uint16_t numElements); /** * Initializes the subTemplateList but does not allocate a buffer. It * accepts a previously allocated buffer and data length and uses it. * This will generally be used in collectors providing their own buffer * * @param subTemplateList pointer to the sub template list to initialize * @param semantic the semantic value used to describe the list contents * @param tmplID id of the template used for encoding the list data * @param tmpl pointer to the template struct used for encoding the list data * @param numElements number of elements in the list * @param dataLength length of the data buffer * @param dataPtr pointer to the previously allocated data buffer * @returns a pointer to that buffer */ void* fbSubTemplateListInitWithOwnBuffer( fbSubTemplateList_t *subTemplateList, uint8_t semantic, uint16_t tmplID, const fbTemplate_t *tmpl, uint16_t numElements, uint16_t dataLength, uint8_t *dataPtr); /** * Initializes a sub template list variable on a collector. If the * fbSubTemplateList variable is in a struct, it will likely not be set to 0's * If not, the dataPtr will not be NULL, so the transcoder will not allocate * the right memory for it, as it will assuming it's set up. This will break. * Call this function right after declaring the struct variable that contains * the fbSubTemplateList. It only needs to be called once for each STL * @param STL pointer to the sub template list to initialize for collection * @return NONE */ void fbSubTemplateListCollectorInit( fbSubTemplateList_t *STL); /** * Returns a pointer to the buffer that contains the data for the list * @param subTemplateListPtr pointer to the STL to get the pointer from * @return a pointer to the data buffer used by the sub template list */ void* fbSubTemplateListGetDataPtr( const fbSubTemplateList_t *subTemplateListPtr); /** * This function is used to iterate over the elements in the list by * passing in a counter to indicate which element is to be returned * @param subTemplateListPtr pointer to the STL * @param index The index of the element to be retrieved (0-based) * @return a pointer to the desired element. NULL if index >= numElements */ void* fbSubTemplateListGetIndexedDataPtr( const fbSubTemplateList_t *subTemplateListPtr, uint16_t index); /** * This function also traverses the elements in the list by accepting * a pointer to the last element the user accessed, moves it to the next * element and returns a pointer to the next element. A current element of * NULL tells the function to return the first element in the list. * @param subTemplateListPtr pointer to the STL to get data from * @param currentPtr pointer to the last element accessed. NULL causes the * pointer to the first element to be returned * @return the pointer to the next element in the list. Returns NULL if * currentPtr points to the last element in the list. */ void* fbSubTemplateListGetNextPtr( const fbSubTemplateList_t *subTemplateListPtr, void *currentPtr); /** * Sets the semantic parameter of a subTemplateList * @param subTemplateListPtr pointer to the sub template list * @param semantic Semantic value for the list * @return NONE */ void fbSubTemplateListSetSemantic( fbSubTemplateList_t *subTemplateListPtr, uint8_t semantic); /** * Gets the semantic value from a sub template list * @param subTemplateListPtr pointer to the sub template list * @return the semantic field from the list */ uint8_t fbSubTemplateListGetSemantic( fbSubTemplateList_t *subTemplateListPtr); /** * Gets the template pointer from the list structure * @param subTemplateListPtr pointer to the sub template list * @return a pointer to the template used by the sub template list */ const fbTemplate_t* fbSubTemplateListGetTemplate( fbSubTemplateList_t *subTemplateListPtr); /** * Gets the template ID for the template used by the list * @param subTemplateListPtr pointer to the sub template list * @return the template ID used by the sub template list */ uint16_t fbSubTemplateListGetTemplateID( fbSubTemplateList_t *subTemplateListPtr); /** * Free the current data pointer, allocating a new buffer to accomodate * the new number of elements. The remaining parameters are unchanged. * If the number of elements hasn't changed * the original buffer is used and its pointer is returned * * @param subTemplateList pointer to the sub template list to realloc * @param newNumElements value for the new number of elements for the list * @return pointer to the data buffer after realloc */ void* fbSubTemplateListRealloc( fbSubTemplateList_t *subTemplateList, uint16_t newNumElements); /** * Allocates space for a number of additional element in the sub template list * must be called after the list has been fbSubTemplateListInit()'d * * @param subTemplateList pointer to the sub template list * @param numNewElements number of new elements to add to the list * @return a pointer to the first newly allocated element */ void* fbSubTemplateListAddNewElements( fbSubTemplateList_t *subTemplateList, uint16_t numNewElements); /** * Clears a subtemplate list struct, notably freeing the dataPtr and setting * it to NULL. * This should be used after each call to fBufNext: * If the dataPtr is not NULL in DecodeSubTemplateList, it will not allocate * new memory for the new record, which could cause a buffer overflow if the * new record has a longer list than the current one. * An alternative is to allocate a large buffer and assign it to dataPtr * on your own, then never clear it with this. Be certain this buffer is * longer than needed for all possible lists * @param subTemplateListPtr pointer to the sub template list to clear * @return NONE */ void fbSubTemplateListClear( fbSubTemplateList_t *subTemplateListPtr); /** * Clears the sub template list parameters but does not free the data ptr. * This is used in conjuction with STLInitOwnBuffer because that buffer * is allocated at the beginning by the user and will be freed at the end * by the user, outside of fixbuf api calls * @param subTemplateListPtr pointer to the sub template list to clear * @return NONE */ void fbSubTemplateListClearWithoutFree( fbSubTemplateList_t *subTemplateListPtr); /** * Frees and clears a subTemplateList struct. This frees the dataPtr AND * frees the memory pointed to by the subTemplateListPtr * Used in conjunction with subTemplateListAlloc(), unlikely to be used * @param subTemplateListPtr pointer to the sub template list to free * @return NONE */ void fbSubTemplateListFree( fbSubTemplateList_t *subTemplateListPtr); /********* END OF SUBTEMPLATELIST **********/ /** * Entries contain the same type of information at SubTemplateLists: * template ID and template pointers to describe the data * the number of data elements and the data pointer and data length * * Sub template multi lists are inherently nested constructions. * At a high level, they are a list of sub template lists. * The first level is a list of fbSubTemplateMultiListEntry_t's, which each * contain the information that describes the data contained in them. * Initializing a fbSubTemplateMultiList_t with a semantic and number of * elements returns memory that contains numElements blocks of memory * containing fbSubTemplateMultiListEntry_t's. It is not ready to accept * data. Each of the fbSubTemplateMultiListEntry_t's needed to be set up * then data is copied into the entries. */ typedef struct fbSubTemplateMultiListEntry_st { /** pointer to the template used to structure the data in this entry */ fbTemplate_t *tmpl; /** pointer to the buffer used to hold the data in this entry */ uint8_t *dataPtr; /** length of the buffer used to hold the data in this entry */ size_t dataLength; /** ID of the template used to structure the data in this entry */ uint16_t tmplID; /** number of elements in this entry */ uint16_t numElements; } fbSubTemplateMultiListEntry_t; /** * Multilists just contain the semantic to describe the sub lists, * the number of sub lists, and a pointer to the first entry */ typedef struct fbSubTemplateMultiList_st { /** pointer to the first entry in the multi list */ fbSubTemplateMultiListEntry_t *firstEntry; /** number of sub template lists in the multi list */ uint16_t numElements; /** value used to describe the list of sub templates */ uint8_t semantic; } fbSubTemplateMultiList_t; /** * Allocates a subTemplateMultiList_t * Based on how subTemplateMultiLists will be used and * set up amidst data structures, this function may never be used * * @return pointer to the new sub template multi list */ fbSubTemplateMultiList_t* fbSubTemplateMultiListAlloc( void); /** * Initializes the multi list with semantic, numbers of elements, * and allocates memory to store numElements worth of entries * * @param STML pointer to the sub template multi list to initialize * @param semantic value used to describe the entries in the multi list * @param numElements number of entries in the multi list * @return pointer to the first uninitialized entry */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListInit( fbSubTemplateMultiList_t *STML, uint8_t semantic, uint16_t numElements); /** * Sets the semantic field for the multi list * @param STML pointer to the sub template multi list * @param semantic Value for the semantic field of the sub template multi list * @return NONE */ void fbSubTemplateMultiListSetSemantic( fbSubTemplateMultiList_t *STML, uint8_t semantic); /** * Get the semantic paramter from the multi list * @param STML pointer to the sub template multi list * @return semantic parameter describing the contents of the multi list */ uint8_t fbSubTemplateMultiListGetSemantic( fbSubTemplateMultiList_t *STML); /** * Clears all of the entries (frees their data pointers), then frees the * memory containing the entries * @param STML pointer to the sub template mutli list to clear * @return NONE */ void fbSubTemplateMultiListClear( fbSubTemplateMultiList_t *STML); /** * Clears the memory used by the entries of a sub template multi list * NOTE: if any of those entries contain another layer of structures, that * second layer must be freed by the user, this function cannot do that. * example: an entry's template contains an element of type basicList. The * memory used by that basicList isn't freed by this function * @param STML pointer to the sub template multi list * @return NONE */ void fbSubTemplateMultiListClearEntries( fbSubTemplateMultiList_t *STML); /** * Clears the multi list, then frees the memory pointed to by STML * @param STML pointer to the sub template multi list * @return NONE */ void fbSubTemplateMultiListFree( fbSubTemplateMultiList_t *STML); /** * Clears the entries used by the multi list, then if newNumElements * is different than numElements, frees the entries buffer and allocates * a new one. * * @param STML pointer to the sub template mutli list * @param newNumEntries the new number of entries for the STML * @return pointer to the first entry */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListRealloc( fbSubTemplateMultiList_t *STML, uint16_t newNumEntries); /** * Adds entries to the multi list of entries * can only be run after the list has been initialized * * @param STML pointer to the sub template multi list * @param numNewEntries number of entries to add to the list * @return a pointer to the new entry */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListAddNewEntries( fbSubTemplateMultiList_t *STML, uint16_t numNewEntries); /** * Retrieve the first entry in the multi list * @param STML pointer to the sub template multi list * @return pointer to the first entry used by the list */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetFirstEntry( fbSubTemplateMultiList_t *STML); /** * Retrieve a pointer to the entry of a specific index. The entry indexes * are zero based. NULL is returned if the index requested is too high * @param STML pointer to the sub template mutli list * @param index index of the entry to be returned * @return the index'th entry used by the list. NULL If index >= numElements */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetIndexedEntry( fbSubTemplateMultiList_t *STML, uint16_t index); /** * This function also traverses the elements in the list by accepting * a pointer to the last element the user accessed, moves it to the next * element and returns a pointer to the next element. A current element of * NULL tells the function to return the first element in the list. * @param STML pointer to the sub template multi list to get data from * @param currentEntry pointer to the last element accessed. * NULL means none have been accessed yet * @return the pointer to the next element in the list. Returns the NULL * if currentEntry points to the last entry. */ fbSubTemplateMultiListEntry_t* fbSubTemplateMultiListGetNextEntry( fbSubTemplateMultiList_t *STML, fbSubTemplateMultiListEntry_t *currentEntry); /** * Initializes the multi list entry with the template values, * and allocates the memory used by the entry to hold the data. * * @param entry pointer to the entry to initialize * @param tmplID ID of the template used to structure the data elements * @param tmpl pointer to the template used to structure the data elements * @param numElements number of data elements in the entry * * @return pointer to the data buffer to be filled in */ void* fbSubTemplateMultiListEntryInit( fbSubTemplateMultiListEntry_t *entry, uint16_t tmplID, fbTemplate_t *tmpl, uint16_t numElements); /** * Frees the memory for the data used by the entry, then allocates * a new buffer based on the size of the template and newNumElements. * (if numElements doesn't change, the pointer is returned without freeing * and allocating) * * @param entry pointer to the entry to realloc * @param newNumElements the new number of elements for the entry * @return pointer to buffer to write data to */ void *fbSubTemplateMultiListEntryRealloc( fbSubTemplateMultiListEntry_t *entry, uint16_t newNumElements); /** * Allocates space for a number of additional elements in the sub * template multi list entry. May only be called after the STML entry * has been initialized with fbSubTemplateMultiListEntryInit(). * * @param entry pointer to the STML entry to add additional elements to * @param numNewElements number of new elements to add to the STML entry * @return a pointer to the first newly allocated element */ void* fbSubTemplateMultiListEntryAddNewElements( fbSubTemplateMultiListEntry_t *entry, uint16_t numNewElements); /** * Frees the memory pointed to by the data buffer holding the data elements * * @param entry pointer to the entry to clear the contents of. * @return NONE */ void fbSubTemplateMultiListEntryClear( fbSubTemplateMultiListEntry_t *entry); /** * Retrieves the data pointer for this entry * * @param entry pointer to the entry to get the data pointer from * @return pointer to the buffer used to store data for this entry */ void* fbSubTemplateMultiListEntryGetDataPtr( fbSubTemplateMultiListEntry_t *entry); /** * This function traverses the elements in the entry by accepting * a pointer to the last element the user accessed, moves it to the next * element and returns a pointer to the next element. A current element of * NULL tells the function to return the first element in the list. * @param entry pointer to the entry to get the next element from * @param currentPtr pointer to the last element accessed. NULL means return a pointer to the first element. * @return the pointer to the next element in the list. Returns NULL if * currentPtr points to the last element in the list */ void* fbSubTemplateMultiListEntryNextDataPtr( fbSubTemplateMultiListEntry_t *entry, void *currentPtr); /** * Returns a pointer to a data element in the entry based on the index. * If the index is >= to the number of elements in the list, NULL is returned. * The elements are 0-based, so index = 0 is returns the first elements. * * @param entry pointer to the entry to get a data pointer from. * @param index the number of the element in the list to return * @return the pointer to the index'th element used by the entry * NULL if the index is >= numElements */ void* fbSubTemplateMultiListEntryGetIndexedPtr( fbSubTemplateMultiListEntry_t *entry, uint16_t index); /** * Retrieve the template pointer used to structure the data elements * * @param entry pointer to the entry to get the template from * @return the template pointer used to describe the contents of the entry */ const fbTemplate_t* fbSubTemplateMultiListEntryGetTemplate( fbSubTemplateMultiListEntry_t *entry); /** * Retrieve the template ID for the template used to structure the data * * @param entry pointer to the entry to get the template ID from * @returns the template ID for template that describes the data */ uint16_t fbSubTemplateMultiListEntryGetTemplateID( fbSubTemplateMultiListEntry_t *entry); /************** END OF STML FUNCTIONS *********** */ /** * Clear all of the memory that fixbuf allocated during * transcode of this record. This will free all of the memory * allocated for list structures when fixbuf was encoding or * decoding the record. The template provided is the internal * template that was set on the fBuf before fBufNext() or * fBufAppend() was called with the data. The template MUST * match the record or bad things WILL happen without indication. * This does not free the record itself. It will only free any * list information elements and nested list information elements. * * @param template pointer to the internal template that MUST match the record * @param record pointer to the data * @return NONE */ void fBufListFree( fbTemplate_t *tmpl, uint8_t *record); /** * Allocates and returns a fbListenerGroup with no entries * * @return a pointer to the created fbListenerGroup_t, or NULL on error */ fbListenerGroup_t* fbListenerGroupAlloc( void); /** * frees a listener group * * @param group fbListenerGroup * @return nothing */ void fbListenerGroupFree( fbListenerGroup_t *group); /** * Adds a previously allocated listener to the previously allocated group. * The listener is placed at the head of the list * * @param group pointer to the allocated group to add the listener to * @param listener pointer to the listener structure to add to the group * @return 0 upon success. "1" if entry couldn't be allocated * "2" if either of the incoming pointers are NULL */ int fbListenerGroupAddListener( fbListenerGroup_t *group, const fbListener_t *listener); /** * Removes the listener from the group. * IT DOES NOT FREE THE LISTENER OR THE GROUP * * @param group pointer to the group to remove from the listener from * @param listener pointer to the listener to remove from the group * @return 0 on success, and "1" if the listener is not found * "2" if either of the pointers are NULL */ int fbListenerGroupDeleteListener( fbListenerGroup_t *group, const fbListener_t *listener); /** * Similar to fbListenerWait, except that is looks for connections for * multiple listeners. It takes a previously allocated and filled * listener group. It returns a pointer to the head of a list of * listenerGroupResults. * @param group pointer to the group of listeners to wait on * @param err error string structure seen throughout fixbuf * @return pointer to the head of the listener group result list * NULL on error, and sets the error string */ fbListenerGroupResult_t* fbListenerGroupWait( fbListenerGroup_t *group, GError **err); /** * Free the fbListenerGroupResult_t returned from fbListenerGroupWait * * @param result fbListenerGroupResult_t * @return nothing */ void fbListenerFreeGroupResult( fbListenerGroupResult_t *result); /** * Returns an fBuf wrapped around an independently managed socket and a * properly created listener for TCP connections. * The caller is only responsible for creating the socket. * The existing collector code will close the socket and cleanup everything. * * @param listener pointer to the listener to wrap around the socket * @param sock the socket descriptor of the independently managed socket * @param err standard fixbuf err structure pointer * @return pointer to the fbuf for the collector. * NULL if sock is 0, 1, or 2 (stdin, stdout, or stderr) */ fBuf_t *fbListenerOwnSocketCollectorTCP( fbListener_t *listener, int sock, GError **err); /** * Same as fbListenerOwnSocketCollectorTCP but for TLS (not tested) * * @param listener pointer to the listener to wait on * @param sock independently managed socket descriptor * @param err standard fixbuf err structure pointer * @return pointer to the fbuf for the collector * NULL if sock is 0, 1, or 2 (stdin, stdout, or stderr) */ fBuf_t *fbListenerOwnSocketCollectorTLS( fbListener_t *listener, int sock, GError **err); /** * Interrupts the select call of a specific collector by way of its fBuf. * This is mainly used by fbListenerInterrupt to interrupt all of the * collector sockets well. */ void fBufInterruptSocket( fBuf_t *fbuf); /** * Application context initialization function type for fbListener_t. * This function is called after accept(2) for TCP or SCTP with the peer * address in the peer argument. For UDP, it is called during fbListener_t * initialization and the peer address will be NULL. If the Collector is in * multi-session mode, the appinit function will be called when a new UDP * connection occurs with the peer address, similiar to the TCP case. Use * fbCollectorSetUDPMultiSession() to turn on multi-session mode * (off by default). The application may veto fbCollector_t creation by * returning FALSE. In multi-session mode, if the connection is to be ignored, * the application should set error code FB_ERROR_NLREAD on the err and return * FALSE. If the application returns FALSE, fixbuf will maintain information * about that peer, and will reject connections from that peer until shutdown * or until that session times out. Fixbuf will return FB_ERROR_NLREAD for * previously rejected sessions. * The context (returned via out-parameter ctx) will be * stored in the fbCollector_t, and is retrievable via a call to * fbCollectorGetContext(). If not in multi-session mode and using the appinit * fn, the ctx will be associated with all UDP sessions. */ typedef gboolean (*fbListenerAppInit_fn) ( fbListener_t *listener, void **ctx, int fd, struct sockaddr *peer, size_t peerlen, GError **err); /** * Application context free function type for fbListener_t. * If the Collector is in multi-session mode (see appinit fn), then the * appfree function will be called if a session is timed out (does not receive * a UDP message for more than 30 minutes.) * Called during fbCollector_t cleanup. */ typedef void (*fbListenerAppFree_fn) ( void *ctx); /* * Public Function Calls. These calls will remain available and retain * their functionality in all subsequent versions of libfixbuf. */ /** * Set the internal template on a buffer to the given template ID. The internal * template describes the format of the record pointed to by the recbase * parameter to fBufAppend() (for export) and fBufNext() (for collection). The * given template ID must identify a current internal template in the buffer's * associated session. * * An internal template must be set on a buffer before calling fBufAppend() or * fBufNext(). * * @param fbuf an IPFIX message buffer * @param int_tid template ID of the new internal template * @param err An error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fBufSetInternalTemplate( fBuf_t *fbuf, uint16_t int_tid, GError **err); /** * Set the external template for export on a buffer to the given template ID. * The external template describes the record that will be written to the * IPFIX message. The buffer must be initialized for export. The given ID is * scoped to the observation domain of the associated session * (see fbSessionSetDomain()), and must identify a current external template * for the current domain in the buffer's associated session. * * An export template must be set on a buffer before calling fBufAppend(). * * @param fbuf an IPFIX message buffer * @param ext_tid template ID of the new external template within the * current domain. * @param err An error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fBufSetExportTemplate( fBuf_t *fbuf, uint16_t ext_tid, GError **err); #if HAVE_SPREAD /** * fBufSetSpreadExportGroup * * This function checks to see if the groups you are setting on the buffer * are different than the groups previously set. If so, it will emit the * buffer, set the first group on the session (to get templates & sequence * numbers) and THEN set the desired group(s) for export on a buffer. This * should be called before setting external templates with * fbSessionAddTemplate() and before calling fBufAppend(). If using * fbSessionAddTemplatesMulticast(), it is not necessary to call this before * because it is called within this function. * * @param fbuf an IPFIX message buffer * @param groups an array of Spread Export Groups * @param num_groups number of groups from groups to be added * @param err an error description, set on failure. */ void fBufSetSpreadExportGroup( fBuf_t *fbuf, char **groups, int num_groups, GError **err); #endif /** * Set the automatic mode flag on a buffer. In automatic mode, a call to * fBufAppend() or fbSessionExportTemplates() that overruns the available space * in the buffer will cause a call to fBufEmit() to emit the message in the * buffer to the exporter before starting a new message; and a call to * fBufNext() that overruns the buffer will cause a call to fBufNextMessage() * to read another message from the collector before attempting to read a * record. In manual mode, end of message on any buffer read/write call * results in FB_ERROR_EOM. Buffers are created in automatic mode by default. * * @param fbuf an IPFIX message buffer * @param automatic TRUE for this buffer to be automatic, FALSE for manual. */ void fBufSetAutomaticMode( fBuf_t *fbuf, gboolean automatic); /** * Set the automatic insert flag on a buffer. In automatic insert mode, * any information element type records that are collected, will automatically * be inserted into the information model that is set on the fbuf's session. * This allows an application to retrieve information about a non-standard * information. This should be called after the fbuf is created. This * function creates the internal template for the Info Element Type Record * and adds it to the session. * * @param fbuf an IPFIX message buffer * @param err Gerror pointer * @return TRUE or FALSE if the internal template could not be * created */ gboolean fBufSetAutomaticInsert( fBuf_t *fbuf, GError **err); /** * Retrieve the session associated with a buffer. * * @param fbuf an IPFIX message buffer * @return the associated session */ fbSession_t *fBufGetSession( fBuf_t *fbuf); /** * Free a buffer. Also frees any associated session, exporter, or collector, * closing exporting process or collecting process endpoint connections * and removing collecting process endpoints from any listeners, as necessary. * * @param fbuf an IPFIX message buffer */ void fBufFree( fBuf_t *fbuf); /** * Allocate a new buffer for export. Associates the buffer with a given * session and exporting process endpoint; these become owned by the buffer. * Session and exporter are freed by fBufFree. Must never be freed by user * * @param session a session initialized with appropriate * internal and external templates * @param exporter an exporting process endpoint * @return a new IPFIX message buffer, owning the session and exporter, * for export use via fBufAppend() and fBufEmit(). */ fBuf_t *fBufAllocForExport( fbSession_t *session, fbExporter_t *exporter); /** * Retrieve the exporting process endpoint associated with a buffer. * The buffer must have been allocated with fBufAllocForExport(); * otherwise, returns NULL. * * @param fbuf an IPFIX message buffer * @return the associated exporting process endpoint */ fbExporter_t *fBufGetExporter( fBuf_t *fbuf); /** * Associate an exporting process endpoint with a buffer. * The exporter will be used to write IPFIX messgaes to a transport. * The exporter becomes owned by the buffer; any previous exporter * associated with the buffer is closed if necessary and freed. * * @param fbuf an IPFIX message buffer * @param exporter an exporting process endpoint */ void fBufSetExporter( fBuf_t *fbuf, fbExporter_t *exporter); /** * Retrieve the length of the buffer that is remaining after * processing. An IPFIX collector that is not using fixbuf to * handle connections would use this function upon receiving an * FB_ERROR_BUFSZ error to determine how many bytes are left in the * buffer (set by fBufSetBuffer) that are not processed. * * @param fbuf an IPFIX message buffer * @return length of buffer not read * */ size_t fBufRemaining( fBuf_t *fbuf); /** * Set a buffer on an fBuf for collection. This can be used * by applications that want to handle their own connections, file reading, * etc. This call should be made after the call to read and before * calling fBufNext. fBufNext will return FB_ERROR_BUFSZ when there is not * enough buffer space to read a full IPFIX message. * * @param fbuf an IPFIX message buffer * @param buf the data buffer to use for processing IPFIX * @param buflen the length of IPFIX data in buf * */ void fBufSetBuffer( fBuf_t *fbuf, uint8_t *buf, size_t buflen); /** * Append a record to a buffer. Uses the present internal template set via * fBufSetInternalTemplate() to describe the record of size recsize located * in memory at recbase. Uses the present export template set via * fBufSetExportTemplate() to describe the record structure to be written to * the buffer. Information Elements present in the external template that are * not present in the internal template are transcoded into the message as * zeroes. If the buffer is in automatic mode, may cause a message to be * emitted via fBufEmit() if there is insufficient space in the buffer for * the record. * * If the internal template contains any variable length Information Elements, * those must be represented in the record by fbVarfield_t structures. * * @param fbuf an IPFIX message buffer * @param recbase pointer to internal record * @param recsize size of internal record in bytes * @param err an error description, set on failure. * Must not be NULL, as it is used internally in * automatic mode to detect message restart. * @return TRUE on success, FALSE on failure. */ gboolean fBufAppend( fBuf_t *fbuf, uint8_t *recbase, size_t recsize, GError **err); /** * Emit the message currently in a buffer using the associated exporting * process endpoint. * * @param fbuf an IPFIX message buffer * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fBufEmit( fBuf_t *fbuf, GError **err); /** * Set the export time on the message currently in a buffer. This will be used * as the export time of the message created by the first call to fBufAppend() * after the current message, if any, is emitted. Use 0 for the export time * to cause the export time to be taken from the system clock at message * creation time. * * @param fbuf an IPFIX message buffer * @param extime the export time in epoch seconds. */ void fBufSetExportTime( fBuf_t *fbuf, uint32_t extime); /** * Allocate a new buffer for collection. Associates the buffer with a given * session and collecting process endpoint; these become owned by the buffer. * Session and collector are freed by fBufFree. Must not be freed by user * * @param session a session initialized with appropriate * internal templates * @param collector an collecting process endpoint * @return a new IPFIX message buffer, owning the session and collector, * for collection use via fBufNext() and fBufNextMessage(). */ fBuf_t *fBufAllocForCollection( fbSession_t *session, fbCollector_t *collector); /** * Retrieve the collecting process endpoint associated with a buffer. * The buffer must have been allocated with fBufAllocForCollection(); * otherwise, returns NULL. * * @param fbuf an IPFIX message buffer * @return the associated collecting process endpoint */ fbCollector_t *fBufGetCollector( fBuf_t *fbuf); /** * Associate an collecting process endpoint with a buffer. * The collector will be used to read IPFIX messgaes from a transport. * The collector becomes owned by the buffer; any previous collector * associated with the buffer is closed if necessary and freed. * * @param fbuf an IPFIX message buffer * @param collector an collecting process endpoint */ void fBufSetCollector( fBuf_t *fbuf, fbCollector_t *collector); /** * Retrieve a record from a buffer. Uses the external template taken from * the message to read the next record available from a data set in the message. * Copies the record to a buffer at recbase, with a maximum record size * pointed to by recsize, described by the present internal template set via * fBufSetInternalTemplate(). Reads and processes any templates and options * templates between the last record read (or beginning of message) and the * next data record. Information Elements present in the internal template * that are not present in the external template are transcoded into the * record at recbase as zeroes. If the buffer is in automatic mode, may cause * a message to be read via fBufNextMessage() if there are no more records * available in the message buffer. * * If the internal template contains any variable length Information Elements, * those must be represented in the record at recbase by fbVarfield_t * structures. * * @param fbuf an IPFIX message buffer * @param recbase pointer to internal record buffer; will contain * record data after call. * @param recsize On call, pointer to size of internal record buffer * in bytes. Contains number of bytes actually transcoded * at end of call. * @param err an error description, set on failure. * Must not be NULL, as it is used internally in * automatic mode to detect message restart. * @return TRUE on success, FALSE on failure. */ gboolean fBufNext( fBuf_t *fbuf, uint8_t *recbase, size_t *recsize, GError **err); /** * Read a new message into a buffer using the associated collecting * process endpoint. Called by fBufNext() on end of message in automatic * mode; should be called after an FB_ERROR_EOM return from fBufNext in * manual mode, or to skip the current message and go on to the next * in the stream. * * @param fbuf an IPFIX message buffer * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fBufNextMessage( fBuf_t *fbuf, GError **err); /** * Retrieve the export time on the message currently in a buffer. * * @param fbuf an IPFIX message buffer * @return the export time in epoch seconds. */ uint32_t fBufGetExportTime( fBuf_t *fbuf); /** * Retrieve the external template used to read the last record from the buffer. * If no record has been read, returns NULL. Stores the external template ID * within the current domain in ext_tid, if not NULL. * * This routine is not particularly useful to applications, as it would be * called after the record described by the external template had been * transcoded, and as such could not be used to select an * appropriate internal template for a given external template. However, * it is used by fBufNextCollectionTemplate(), and may be useful in certain * contexts, so is made public. * * Usually, you'll want to use fBufNextCollectionTemplate() instead. * * @param fbuf an IPFIX message buffer * @param ext_tid pointer to external template ID storage, or NULL. * @return the external template describing the last record read. */ fbTemplate_t *fBufGetCollectionTemplate( fBuf_t *fbuf, uint16_t *ext_tid); /** * Retrieve the external template that will be used to read the next record * from the buffer. If no next record is available, returns NULL. Stores the * external template ID within the current domain in ext_tid, if not NULL. * Reads and processes any templates and options * templates between the last record read (or beginning of message) and the * next data record. If the buffer is in automatic mode, may cause * a message to be read via fBufNextMessage() if there are no more records * available in the message buffer. * * @param fbuf an IPFIX message buffer * @param ext_tid pointer to external template ID storage, or NULL. * @param err an error description, set on failure. * Must not be NULL, as it is used internally in * automatic mode to detect message restart. * @return the external template describing the last record read. */ fbTemplate_t *fBufNextCollectionTemplate( fBuf_t *fbuf, uint16_t *ext_tid, GError **err); /** * Allocate a new information model. The information model will contain all * the default information elements in the IANA-managed number space, and may * be extended via fbInfoModelAddElement() and fbInfoModelAddElementArray(). * * An Information Model is required to create Templates and Sessions. Each * application should have only one Information Model. * * @return a new Information Model */ fbInfoModel_t *fbInfoModelAlloc(void); /** * Free an information model. Must not be called until all sessions and * templates depending on the information model have also been freed; i.e., * at application cleanup time. * * @param model An information model */ void fbInfoModelFree( fbInfoModel_t *model); /** * Add a single information element to an information * model. The information element is assumed to be in "canonical" form; that * is, its ref.name field should contain the information element name. The * information element and its name are copied into the model; the caller may * free or reuse its storage after this call. * * See fbInfoModelAddElementArray() for a more convenient method of statically * adding information elements to information models. * * @param model An information model * @param ie Pointer to an information element to copy into the model */ void fbInfoModelAddElement( fbInfoModel_t *model, fbInfoElement_t *ie); /** * Add multiple information elements in an array to an information * model. The information elements are assumed to be in "canonical" form; that * is, their ref.name fields should contain the information element name. Each * information element and its name are copied into the model; the caller may * free or reuse its storage after this call. * * The ie parameter points to the first information element in an array, * usually statically initialized with an array of FB_IE_INIT macros followed * by an FB_IE_NULL macro. * @param model An information model * @param ie Pointer to an IE array to copy into the model */ void fbInfoModelAddElementArray( fbInfoModel_t *model, fbInfoElement_t *ie); /** * Return a pointer to the canonical information element within an information * model given the information element name. The returned information element * is owned by the information model and must not be modified. * * @param model An information model * @param name The name of the information element to look up * @return The named information element within the model, * or NULL if no such element exists. */ const fbInfoElement_t *fbInfoModelGetElementByName( fbInfoModel_t *model, const char *name); /** * Return a pointer to the canonical information element within an information * model given the information element ID and enterprise ID. The returned * information element is owned by the information model and must not be * modified. * * @param model An information model * @param id An information element id * @param ent An enterprise id * @return The named information element within the model, or NULL * if no such element exists. */ const fbInfoElement_t *fbInfoModelGetElementByID( fbInfoModel_t *model, uint16_t id, uint32_t ent); /** * Return the number of information elements in the information model. * * @param model An information model * @return The number of information elements in the * information model */ guint fbInfoModelCountElements( const fbInfoModel_t *model); /** * Initialize an information model iterator for iteration. * * @param iter A pointer to the iterator to initialize * @param model An information model */ void fbInfoModelIterInit( fbInfoModelIter_t *iter, const fbInfoModel_t *model); /** * Return a pointer to the next information element in the information * model. Returns NULL once all information elements have been * returned. * * @param iter An information model iterator * @return The next information element within the model, or NULL * if there are no more elements. */ const fbInfoElement_t *fbInfoModelIterNext( fbInfoModelIter_t *iter); /** * Allocate the Options Template that will be used to define Information * Element Type Records. This function does not add the template to the * session or fbuf. This function allocates the template, appends the * appropriate elements to the template, and sets the scope on the template. * See RFC 5610 for more info. * * @param model A pointer to an existing info model * @param err GError * @return The pointer to the newly allocated template. * */ fbTemplate_t *fbInfoElementAllocTypeTemplate( fbInfoModel_t *model, GError **err); /** * Export an options record to the given fbuf with information element type * information about the given information element. See RFC 5610 for details. * Use fbInfoElementAllocTypeTemplate() and add the returned template * to the session, before calling this function. * * @param fbuf An existing fbuf * @param model_ie A pointer to the information element to export type info. * @param tid The template id of the Options Template. * @param err GError * @return TRUE if successful, FALSE if an error occurred. */ gboolean fbInfoElementWriteOptionsRecord( fBuf_t *fbuf, const fbInfoElement_t *model_ie, uint16_t tid, GError **err); /** * Add an element that we received via an Options Record to the given info * model. Returns True if the element was successfully added. False, if * it couldn't be added. This function will not add elements that have a * private enterprise number of 0, for security reasons. * * @param model An information model * @param rec A pointer to the received fbInfoElementOptRec. * @return TRUE if item was successfully added to info model. * */ gboolean fbInfoElementAddOptRecElement( fbInfoModel_t *model, fbInfoElementOptRec_t *rec); /** * Checks to see if the template contains all of the elements the RFC 5610 * info element type record should contain. If so, and the fbuf is in * "automatic insert" mode, we'll insert the elements in our own info model. * * @param tmpl A pointer to the template * @return TRUE if template contains all the info elements * */ gboolean fbInfoModelTypeInfoRecord( fbTemplate_t *tmpl); /** * Allocate a new empty template. The template will be associated with the * given Information Model, and only able to use Information Elements defined * within that Information Model. Templates may be associated with multiple * sessions, with different template IDs each time, and as such are * reference counted and owned by sessions. A template must be associated * with at least one session or it will be leaked; each template is freed * after its last associated session is freed. * * Use fbTemplateAppend(), fbTemplateAppendSpec(), and * fbTemplateAppendSpecArray() to "fill in" a template after creating it, * and before associating it with any session. * * @param model An information model * @return a new, empty Template. */ fbTemplate_t *fbTemplateAlloc( fbInfoModel_t *model); /** * Append an information element to a template. The information element is taken * to be an example; the canonical element from the template's associated model * is looked up by enterprise and element number and copied. If no information * element exists in the model with the given enterprise and element number, * it is copied to the model with the name "_alienInformationElement". * * This call is intended primarily for use by fBuf_t's template reader, but can * also be useful to simulate receipt of templates over the wire. * * @param tmpl Template to append information element to * @param ex_ie Example IE to add to the template * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fbTemplateAppend( fbTemplate_t *tmpl, fbInfoElement_t *ex_ie, GError **err); /** * Append an information element described by specifier to a template. * The information element named by the specifier is copied from the template's * associated model, and the length and flags are overriden from the specifier. * * @param tmpl Template to append information element to. * @param spec Specifier describing information element to append. * @param flags Application flags. Must match one bit of spec flags word * or the append will be silently skipped. Used for * building multiple templates with different information * element features from a single specifier. * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fbTemplateAppendSpec( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags, GError **err); /** * Append information elements described by a specifier array to a template. * The information elements named by the specifiers are copied from the * template's associated model, and the length and flags are overriden from * each specifier. The array is read until the FB_IESPEC_NULL convenience macro * is encountered. * * @param tmpl Template to append information element to. * @param spec Pointer to first specifier in specifier array to append. * @param flags Application flags. Must contain all bits of spec flags word * or the append will be silently skipped. Used for * building multiple templates with different information * element features from a single specifier. * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fbTemplateAppendSpecArray( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags, GError **err); /** * Determine number of information elements in a template. * * @param tmpl A template * @return information element count */ uint32_t fbTemplateCountElements( fbTemplate_t *tmpl); /** * Set the number of information elements in a template that are scope. This * causes the template to become an options template, and must be called after * all the scope information elements have been appended to the template. * * @param tmpl Template to set scope on * @param scope_count Number of scope information elements */ void fbTemplateSetOptionsScope( fbTemplate_t *tmpl, uint16_t scope_count); /** * Determine number of scope information elements in a template. The template * is an options template if nonzero. * * @param tmpl A template * @return scope information element count */ uint32_t fbTemplateGetOptionsScope( fbTemplate_t *tmpl); /** * Determine if a template contains a given information element. Matches against * information element private enterprise number, number, and multiple-IE index * (i.e., to determine if a given template contains six instances of a given * information element, set ex_ie->midx = 5 before this call). * * @param tmpl Template to search * @param ex_ie Pointer to an information element to search for * @return TRUE if the template contains the given IE */ gboolean fbTemplateContainsElement( fbTemplate_t *tmpl, const fbInfoElement_t *ex_ie); /** * Determine if a template contains at least one instance of a given * information element, specified by name in the template's information model. * * @param tmpl Template to search * @param spec Specifier of information element to search for * @return TRUE if the template contains the given IE */ gboolean fbTemplateContainsElementByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec); /** * Determine if a template contains at least one instance of each * information element in a given information element specifier array. * * @param tmpl Template to search * @param spec Pointer to specifier array to search for * @return TRUE if the template contains all the given IEs */ gboolean fbTemplateContainsAllElementsByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec); /** * Determine if a template contains at least one instance of each * information element in a given information element specifier array that * match the given flags argument. * * @param tmpl Template to search * @param spec Pointer to specifier array to search for * @param flags Flags to match info elements * @return TRUE if the template contains all the given IEs */ gboolean fbTemplateContainsAllFlaggedElementsByName( fbTemplate_t *tmpl, fbInfoElementSpec_t *spec, uint32_t flags); /** * Return the information element in the template referenced by the index * * @param tmpl Pointer to the template * @param IEindex index of the information element to return * @return A pointer to the information element at index IEindex, * NULL if IEindex is greater than number of elements */ fbInfoElement_t* fbTemplateGetIndexedIE( fbTemplate_t *tmpl, uint32_t IEindex); /** * Free a template if it is not currently in use by any Session. Use this * to clean up while creating templates in case of error. * * @param tmpl template to free */ void fbTemplateFreeUnused( fbTemplate_t *tmpl); /** * Get the ctx pointer associated with a Template. The ctx pointer * is typically set during the template callback when the new template * is received. * @param tmpl Template Pointer * @return ctx The application Context Pointer */ void *fbTemplateGetContext( fbTemplate_t *tmpl); /** * Allocate a transport session state container. The new session is associated * with the given information model, contains no templates, and is usable * either for collection or export. * * Each fbExporter_t, fbListener_t, and fbCollector_t must have its own * session; session state cannot be shared. * * The fbSession_t returned by this function is not freed by calling * fBufFree() or fbListenerFree(). It should be freed by the application * by calling fbSessionFree(). * * @param model An information model. Not freed by sessionFree. Must be freed by user after calling SessionFree * @return a new, empty session state container. */ fbSession_t *fbSessionAlloc( fbInfoModel_t *model); /** * fbSessionGetInfoModel * * @param session * @return a pointer to the info model for the session * * */ fbInfoModel_t *fbSessionGetInfoModel( fbSession_t *session); /** * This function sets the callback to let the user know when a new template * has arrived from the connected IPFIX node. Assigning a callback here * is NOT required. Not using one will cause all sub templates to be fully * decoded, transcoding all information elements in the external template. * * This function should be called after fbSessionAlloc(). Fixbuf often * clones sessions upon receiving a connection. In the TCP case, the * application has access to the session right after fbListenerWait() returns * by calling fBufGetSession(). In the UDP case, the application does * not have access to the fbSession until after a call to fBufNext() for * fBufNextCollectionTemplate() and by this time the application may have * already received some templates. Therefore, it is important to call this * function before fBufNext(). Any callbacks added to the session will be * carried over to cloned sessions. * * In order to add application context to a template use the newer API call * fbSessionAddTemplateCtxCallback2() instead. * * @param session pointer to the session to assign the callback to * @param callback the function to be called when a new template is received * @return NONE */ void fbSessionAddTemplateCallback( fbSession_t *session, fbNewTemplateCallback_fn callback); /** * This function sets the callback that allows the application to set its * own context variable with a new incoming template. Assigning a callback * is not required and is only useful if the application either needs to * store some information about the template or to prevent certain nested * templates from being transcoded. If the application's template contains * a subTemplateMultiList or subTemplateList and the callback is not used, * all incoming templates contained in these lists will be fully transcoded * and the application is responsible for freeing any nested lists contained * within those objects. * * This function should be called after fbSessionAlloc(). Fixbuf often * clones sessions upon receiving a connection. In the TCP case, the * application has access to the session right after fbListenerWait() returns * by calling fBufGetSession(). In the UDP case, the application does * not have access to the fbSession until after a call to fBufNext() for * fBufNextCollectionTemplate() and by this time the application may have * already received some templates. Therefore, it is important to call this * function before fBufNext(). Any callbacks added to the session will be * carried over to cloned sessions. * * This function replaced the deprecated function * fbSessionAddTemplateCallback(), and should be used with the * fbNewTemplateCallback_fn. This function should be used with the * fbTemplateCtxCallback_fn. * * The callback function passed to this function does not provide a way for * the caller to pass their application's context into the function for * making a C closure. For that, use fbSessionAddTemplateCtxCallback2(). * (Only one of fbSessionAddTemplateCtxCallback() and * fbSessionAddTemplateCtxCallback2() should be used. * * @param session pointer session to assign the callback to * @param callback the function that should be called when a new template * is received * @return NONE */ void fbSessionAddTemplateCtxCallback( fbSession_t *session, fbTemplateCtxCallback_fn callback); /** * This function sets the callback that allows the application to set its * own context variable with a new incoming template. Assigning a callback * is not required and is only useful if the application either needs to * store some information about the template or to prevent certain nested * templates from being transcoded. If the application's template contains * a subTemplateMultiList or subTemplateList and the callback is not used, * all incoming templates contained in these lists will be fully transcoded * and the application is responsible for freeing any nested lists contained * within those objects. * * This function should be called after fbSessionAlloc(). Fixbuf often * clones sessions upon receiving a connection. In the TCP case, the * application has access to the session right after fbListenerWait() returns * by calling fBufGetSession(). In the UDP case, the application does * not have access to the fbSession until after a call to fBufNext() for * fBufNextCollectionTemplate() and by this time the application may have * already received some templates. Therefore, it is important to call this * function before fBufNext(). Any callbacks added to the session will be * carried over to cloned sessions. * * This function updates and subsumes the functionality of * fbSessionAddTemplateCtxCallback() by adding an application context * pointer. (Only one of fbSessionAddTemplateCtxCallback() and * fbSessionAddTemplateCtxCallback2() should be used.) * * @param session pointer session to assign the callback to * @param callback the function that should be called when a new template * is received * @param app_ctx parameter that gets passed onto the callback function * @return NONE */ void fbSessionAddTemplateCtxCallback2( fbSession_t *session, fbTemplateCtxCallback2_fn callback, void *app_ctx); /** * Adds an external-internal template pair to the session. This tells the * transcoder which internal template to use for a given external template * used in a sub template list, or a sub template multi list. * * If the value of int_tid is 0, it tells fixbuf NOT to decode any list where * the external template is ent_tid. This allows a collector to specify which * templates that are included in lists it can handle. * * If ent_tid and int_tid are set equal to each other, it tells the transcoder * to decode all of the fields from the external template, by using the * external template also as the internal template (lining up all the fields) * The exception to this is if there is an existing internal template with * the same template ID as the external template. In this case, the internal * template with the appropriate ID will be used. To avoid this potentially * unintended consequence, be careful and deliberate with template IDs. * * @param session pointer to the session to add the pair to * @param ent_tid the external template ID * @param int_tid the internal template ID used to decode the data when the associated external template is used * @return NONE */ void fbSessionAddTemplatePair( fbSession_t *session, uint16_t ent_tid, uint16_t int_tid); /** * remove a template pair from the list * this is called by fixbuf when a template is revoked from the session by * the node on the other end of the connection * * @param session pointer to the session to remove the pair from * @param ext_tid the external template ID for the pair * @return NONE */ void fbSessionRemoveTemplatePair( fbSession_t *session, uint16_t ext_tid); /** * Function to find a pair, uniquely identified by the external ID, and return * the associated internal template ID * * @param session pointer to the session used to find the pair * @param ext_tid external template ID used to find a pair * @return the internal template ID from the pair. 0 if the pair isn't found */ uint16_t fbSessionLookupTemplatePair( fbSession_t *session, uint16_t ext_tid); /** * Free a transport session state container. This is done automatically when * freeing the listener or buffer with which the session is * associated. Use this call if a session needs to be destroyed before it * is associated. * * @param session session state container to free. */ void fbSessionFree( fbSession_t *session); /** * Reset the external state (sequence numbers and templates) in a session * state container. * * FIXME: Verify that this call actually makes sense; either that a session * is reassociatable with a new collector, or that you need to do this when * reassociating a collector with a connection. Once this is done, rewrite * this documentation * * @param session session state container to reset */ void fbSessionResetExternal( fbSession_t *session); /** * Set the current observation domain on a session. The domain * is used to scope sequence numbers and external templates. This is called * automatically during collection, but must be called to set the domain * for export before adding external templates or writing records. * * Notice that a domain change does not automatically cause any associated * export buffers to emit messages; a domain change takes effect with the * next message started. Therefore, call fBufEmit() before setting the domain * on the buffer's associated session. * * @param session a session state container * @param domain ID of the observation domain to set */ void fbSessionSetDomain( fbSession_t *session, uint32_t domain); /** * Retrieve the current domain on a session. * * @param session a session state container * @return the ID of the session's current observation domain */ uint32_t fbSessionGetDomain( fbSession_t *session); /** * Retrieve collector that was created with the session * * @param session a session state container * @return fbCollector_t the collector that was created with the session * */ fbCollector_t *fbSessionGetCollector( fbSession_t *session); #if HAVE_SPREAD /** * fbSessionAddTemplatesMulticast * * Set and send templates for 1 or more groups. * This loops through the groups and adds the template to each * group's session and adds the template to the buffer. * This function is really meant for external templates, since * they are exported, although can be used for internal templates. * Since internal templates are not managed per group, they can simply * be added with fbSessionAddTemplate(). * It is necessary to use this function if you plan on managing * templates per group. Using fbSessionAddTemplate() will not allow * you to send a tmpl(s) to more than 1 group. * * @param session a session state container * @param group group names * @param internal TRUE for internal tmpl, FALSE for external * @param tid template id * @param tmpl pointer to template with template id tid * @param err error mesasge */ gboolean fbSessionAddTemplatesMulticast( fbSession_t *session, char **groups, gboolean internal, uint16_t tid, fbTemplate_t *tmpl, GError **err); #endif /** * Export a single external template in the current domain of a given session. * Writes the template to the associated export buffer. May cause a message to * be emitted if the associated export buffer is in automatic mode, or return * with FB_ERROR_EOM if the associated export buffer is not in automatic mode. * * @param session a session state container associated with an export buffer * @param tid template ID within current domain to export * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fbSessionExportTemplate( fbSession_t *session, uint16_t tid, GError **err); /** * Export all external templates in the current domain of a given session. * Writes templates to the associated export buffer. May cause a message to * be emitted if the associated export buffer is in automatic mode, or return * with FB_ERROR_EOM if the associated export buffer is not in automatic mode. * * @param session a session state container associated with an export buffer * @param err an error description, set on failure. * @return TRUE on success, FALSE on failure. */ gboolean fbSessionExportTemplates( fbSession_t *session, GError **err); /** * Add a template to a session. If external, adds the template to the current * domain, and exports the template if the session is associated with an export * buffer. Assigns the template ID given in tid, or assigns a template ID if * tid is FB_TID_AUTO. * If using FB_TID_AUTO, external templates start at 256 and count up, internal * templates start at 65535 and count down. This is to avoid inadvertant * unrelated external and internal templates having the same ID * * @param session A session state container * @param internal TRUE if the template is internal, FALSE if external. * @param tid Template ID to assign, replacing any current template * in case of collision; or FB_TID_AUTO to assign a new tId. * @param tmpl Template to add * @param err An error description, set on failure * @return the template ID of the added template, or 0 on failure. */ uint16_t fbSessionAddTemplate( fbSession_t *session, gboolean internal, uint16_t tid, fbTemplate_t *tmpl, GError **err); /** * Remove a template from a session. If external, removes the template from * the current domain, and exports a template revocation set if the session is * associated with an export buffer. * * @param session A session state container * @param internal TRUE if the template is internal, FALSE if external. * @param tid Template ID to remove. * @param err An error description, set on failure * @return TRUE on success, FALSE on failure. */ gboolean fbSessionRemoveTemplate( fbSession_t *session, gboolean internal, uint16_t tid, GError **err); /** * Retrieve a template from a session by ID. If external, retrieves the * template within the current domain. * * @param session A session state container * @param internal TRUE if the template is internal, FALSE if external. * @param tid ID of the template to retrieve. * @param err An error description, set on failure. * @return The template with the given ID, or NULL on failure. */ fbTemplate_t *fbSessionGetTemplate( fbSession_t *session, gboolean internal, uint16_t tid, GError **err); /** * Allocate an exporting process endpoint for a network connection. * The remote collecting process is specified by the given connection specifier. * The underlying socket connection will not be opened until the first message * is emitted from the buffer associated with the exporter. * * @param spec remote endpoint connection specifier. A copy is made for the exporter, it is freed later. User is responsible for original spec pointer * @return a new exporting process endpoint */ fbExporter_t *fbExporterAllocNet( fbConnSpec_t *spec); #if HAVE_SPREAD /** * fbCollectorGetSpreadReturnGroups * * This function is useful if need to know what groups were set on the message. * Also useful if you are subscribed to more than 1 group, or want to know * what other groups the message published to. * * @param collector * @param array of groups * @return number in the array of groups */ int fbCollectorGetSpreadReturnGroups( fbCollector_t *collector, char *groups[]); /** * Allocate an exporting process endpoint for a Spread connection. * This connection will use the Spread toolkit for exporting and collecting * IPFIX records. Note that the connection to the Spread daemon will not * take place until the first message is emitted from the buffer. * This is not synonymous with appending the first record to the buffer. * NOTE: unlike the other connection specifiers, the session MUST be set * in the fbSpreadSpec_t structure BEFORE it is passed to this method. * * @param params Spread connection specifier * @return a new exporting process endpoint */ fbExporter_t *fbExporterAllocSpread( fbSpreadParams_t *params ); #endif /* HAVE_SPREAD */ /** * Allocate an exporting process endpoint for a named file. The underlying * file will not be opened until the first message is emitted from the * buffer associated with the exporter. * * @param path pathname of the IPFIX File to write, or "-" to * open standard output. Path is duplicated and handled. * Original pointer is up to the user. * @return a new exporting process endpoint */ fbExporter_t *fbExporterAllocFile( const char *path); /** * Allocate an exporting process for a buffer. The underlying * buffer will be allocated to the given size. * * @param buf buffer that will be allocated and used to copy IPFIX to. * @param bufsize size of buffer that will be allocated. * * @return a new exporting process endpoint */ fbExporter_t *fbExporterAllocBuffer( uint8_t *buf, uint16_t bufsize); /** * Allocate an exporting process endpoint for an opened ANSI C file pointer. * * @param fp open file pointer to write to. File pointer is created and freed outside of the Exporter functions. * @return a new exporting process endpoint */ fbExporter_t *fbExporterAllocFP( FILE *fp); /** * Set the SCTP stream for the next message exported. To change the SCTP * stream used for export, first emit any message in the exporter's associated * buffer with fbufEmit(), then use this call to set the stream for the next * message. This call cancels automatic stream selection, use * fbExporterAutoStream() to re-enable it. This call is a no-op for non-SCTP * exporters. * * @param exporter an exporting process endpoint. * @param sctp_stream SCTP stream to use for next message. */ void fbExporterSetStream( fbExporter_t *exporter, int sctp_stream); /** * Enable automatic SCTP stream selection for the next message exported. * Automatic stream selection is the default; use this call to re-enable it * on a given exporter after using fbExporterSetStream(). With automatic * stream selection, the minimal behavior specified in the original IPFIX * protocol (RFC xxxx) is used: all templates and options templates are * exported on stream 0, and all data is exported on stream 1. This call is a * no-op for non-SCTP exporters. * * @param exporter an exporting process endpoint. */ void fbExporterAutoStream( fbExporter_t *exporter); /** * Force the file or socket underlying an exporting process endpoint to close. * No effect on open file endpoints. The file or socket may be reopened on a * subsequent message emission from the associated buffer. * * @param exporter an exporting process endpoint. */ void fbExporterClose( fbExporter_t *exporter); /** * Get the (transcoded) message length that was copied to the * exporting buffer upon fBufEmit(). * * @param exporter an exporting process endpoint. */ size_t fbExporterGetMsgLen( fbExporter_t *exporter); /** * Allocate a collecting process endpoint for a named file. The underlying * file will be opened immediately. * * @param ctx application context; for application use, retrievable * by fbCollectorGetContext * @param path path of file to read, or "-" to read standard input. Used to get fp, user creates and frees. * @param err An error description, set on failure. * @return a collecting process endpoint, or NULL on failure. */ fbCollector_t *fbCollectorAllocFile( void *ctx, const char *path, GError **err); /** * Allocate a collecting process endpoint for an open file. * * @param ctx application context; for application use, retrievable * by fbCollectorGetContext * @param fp file pointer to file to read. Created and freed by user. Must be kept around for the life of the collector. * @return a collecting process endpoint. */ fbCollector_t *fbCollectorAllocFP( void *ctx, FILE *fp); #if HAVE_SPREAD /** * Allocate a collecting process endpoint for the Spread transport. * * @param ctx application context * @param params point to fbSpreadSpec_t containing Spread params * @param err error description, set on failure * * @return a collecting endpoint, or null on failure */ fbCollector_t *fbCollectorAllocSpread( void *ctx, fbSpreadParams_t *params, GError **err ); #endif /* HAVE_SPREAD */ /** * Retrieve the application context associated with a collector. This context * is taken from the ctx argument of fbCollectorAllocFile() or * fbCollectorAllocFP(), or passed out via the ctx argument to the * appinit function argument to fbListenerAlloc(). * * @param collector a collecting process endpoint. * @return the application context */ void *fbCollectorGetContext( fbCollector_t *collector); /** * Close the file or socket underlying a collecting process endpoint. * No effect on open file endpoints. If the collector is attached to a * buffer managed by a listener, the buffer will be removed from the * listener (that is, it will not be returned by subsequent fbListenerWait() * calls). * * @param collector a collecting process endpoint. */ void fbCollectorClose( fbCollector_t *collector); /** * Set the collector to only receive from the given IP address over UDP. * The port will be ignored. Use fbListenerGetCollector() to get the pointer * to the collector after calling fbListenerAlloc(). ONLY valid for UDP. * Set the address family in address. * * @param collector pointer to collector * @param address pointer to sockaddr struct with IP address and family. * @param address_length address length * */ void fbCollectorSetAcceptOnly( fbCollector_t *collector, struct sockaddr *address, size_t address_length); /** * Allocate a listener. The listener will listen on a specified local endpoint, * and create a new collecting process endpoint and collection buffer for each * incoming connection. Each new buffer will be associated with a clone of * a given session state container. * * The application may associate context with each created collecting process * endpoint, or veto a connection attempt, via a function colled on each * connection attempt passed in via the appinit parameter. If this function * will create application context, provide a function via the * appfree parameter which will free it. * * The fbListener_t returned should be freed by the application by calling * fbListenerFree(). * * @param spec local endpoint connection specifier. A copy is made of this, which is freed by listener. Original pointer freeing is up to the user. * @param session session state container to clone for each collection buffer * created by the listener. Not freed by listener. Must * be kept alive while listener exists. * @param appinit application connection initiation function. Called on each * collection attempt; vetoes connection attempts and creates * application context. * @param appfree application context free function. * @param err An error description, set on failure. * @return a new listener, or NULL on failure. */ fbListener_t *fbListenerAlloc( fbConnSpec_t *spec, fbSession_t *session, fbListenerAppInit_fn appinit, fbListenerAppFree_fn appfree, GError **err); /** * Free a listener. Stops listening on the local endpoint, and frees any * open buffers still managed by the listener. * * @param listener a listener */ void fbListenerFree( fbListener_t *listener); /** * Wait on a listener. Accepts pending connections from exporting processes. * Returns the next collection buffer with available data to read; if the * collection buffer returned by the last call to fbListenerWait() is available, * it is preferred. Blocks forever (or until fbListenerInterrupt() is called) * if no messages or connections are available. * * To effectively use fbListenerWait(), the application should set up an * session state container with internal templates, call fbListenerWait() * to accept a first connection, then read records from the collector buffer * to end of message (FB_ERROR_EOM). At end of message, the application should * then call fbListenerWait() to accept pending connections or switch to * another collector buffer with available data. Note that each collector * buffer returned created by fbListenerWait() is set to automatic mode using * fBufSetAutomaticMode(). To modify this behavior, call * fBufSetAutomaticMode(fbuf, TRUE) on the fbuf returned from this function. * * @param listener a listener * @param err An error description, set on failure. * @return a collection buffer with available data, or NULL on failure. */ fBuf_t *fbListenerWait( fbListener_t *listener, GError **err); /** * Waits for an incoming connection, just like fbListenerWait, except that * this function doesn't monitor active collectors. This allows for a * multi threaded application to have one thread monitoring the listeners, * and one keeping track of collectors * @param listener The listener to wait for connections on * @param err An error description, set on failure. * @return a collection buffer for the new connection, NULL on failure. */ fBuf_t *fbListenerWaitNoCollectors( fbListener_t *listener, GError **err); /** * Cause the current or next call to fbListenerWait to unblock and return. * Use this from a thread or a signal handler to interrupt a blocked listener. * * @param listener listener to interrupt. */ void fbListenerInterrupt( fbListener_t *listener); /** *fbListenerGetCollector * * If a collector is associated with the listener class, this will return a * handle to the collector state structure. * * @param listener handle to the listener state * @param collector pointer to a collector state pointer, set on return * if there is no error * * @param err a GError structure holding an error message on error * * @return FALSE on error, check err, TRUE on success * */ gboolean fbListenerGetCollector( fbListener_t *listener, fbCollector_t **collector, GError **err); /** * fbCollectorClearTranslator * * this removes an input translator from a given * collector such that it will operate on IPFIX * protocol again * * @param collector the collector on which to remove * the translator * * @param err when an error occurs, a Glib GError * structure is set with an error description * * @return TRUE on success, FALSE on failure */ gboolean fbCollectorClearTranslator( fbCollector_t *collector, GError **err); /** *fbCollectorSetNetflowV9Translator * * this sets the collector input translator * to convert NetFlowV9 into IPFIX for the * given collector * * @param collector pointer to the collector state * to perform Netflow V9 conversion on * @param err GError structure that holds the error * message if an error occurs * * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetNetflowV9Translator( fbCollector_t *collector, GError **err); /** *fbCollectorSetSFlowTranslator * * this sets the collector input translator * to convert SFlow into IPFIX for the * given collector * * @param collector pointer to the collector state * to perform SFlow conversion on * @param err GError structure that holds the error * message if an error occurs * * * @return TRUE on success, FALSE on error */ gboolean fbCollectorSetSFlowTranslator( fbCollector_t *collector, GError **err); /** * fbCollectorGetNetflowMissed * * Returns the number of potential missed export packets of the Netflow * v9 session that is currently set on the collector (the session is set on * the collector when an export packet is received) if peer is NULL. If peer * is set, this will look up the session for that peer/obdomain pair and return * the missed export packets associated with that peer and obdomain. If * peer/obdomain pair doesn't exist, this function returns 0. * This can't return the number of missed flow records since Netflow v9 * increases sequence numbers by the number of export packets it has sent, * NOT the number of flow records (like IPFIX and netflow v5 does). * * @param collector * @param peer [OPTIONAL] peer address of NetFlow v9 exporter * @param peerlen size of peer object * @param obdomain observation domain of NetFlow v9 exporter * @return number of missed packets since beginning of session * */ uint32_t fbCollectorGetNetflowMissed( fbCollector_t *collector, struct sockaddr *peer, size_t peerlen, uint32_t obdomain); /** * fbCollectorGetSFlowMissed * * Returns the number of potential missed export packets of the * SFlow session that is identified with the given ip/agentID. The agent * ID is a field that is in the sFlow header and is sent with every * packet. Fixbuf keeps track of sequence numbers for sFlow sessions * per agent ID. * * @param collector * @param peer address of exporter to lookup * @param peerlen sizeof(peer) * @param obdomain observation domain of peer exporter * @return number of missed packets since beginning of session * */ uint32_t fbCollectorGetSFlowMissed( fbCollector_t *collector, struct sockaddr *peer, size_t peerlen, uint32_t obdomain); /** * Retrieves information about the node connected to this collector * * @param collector pointer to the collector to get peer information from * @return pointer to sockaddr structure containing IP information of peer */ struct sockaddr* fbCollectorGetPeer( fbCollector_t *collector); /** * Retrieves the observation domain of the node connected to the UDP collector. * The observation domain only gets set on the collector when collecting * via UDP. If the collector is using another mode of transport, use * fbSessionGetDomain(). * * @param collector * */ uint32_t fbCollectorGetObservationDomain( fbCollector_t *collector); /** * Attempt to maintain backwards compatibility with UDP. As of version 1.2, * fixbuf calls the appinit functions when a new UDP connection occurs, as * opposed to calling it during fbListenerAlloc. To maintain compatibility, * with old applications, fixbuf will still call appinit in fbListenerAlloc * with a null peer address. If UDP multi session is turned on, it will ALSO * call appinit() when a new UDP connection occurs. Likewise with appfree(). * Call fbListenerGetCollector() to obtain collector. * * @param collector pointer to collector associated with listener. * @param multi_session TRUE if multi-session enabled, FALSE by default. */ void fbCollectorSetUDPMultiSession( fbCollector_t *collector, gboolean multi_session); /** * An attempt to fix what some netflow v9 exporters do wrong. * Netflow v9 rfc 3954 states that collectors should use a combination of * peer IP address and observation domain to manage netflow streams. * However, some devices send two separate streams on the same IP, obdomain, * and the only way to differentiate is by using peer port. Turning this * flag on will prevent fixbuf from zeroing out the port before comparing * sockaddr structs and makes fixbuf manage streams by ip, port, and obdomain. * * @param collector pointer to collector associated with listener. * @param manage_port TRUE if fixbuf should manage UDP streams by port, * FALSE by default. * */ void fbCollectorManageUDPStreamByPort( fbCollector_t *collector, gboolean manage_port); #ifdef __cplusplus } /* extern "C" */ #endif #endif libfixbuf-1.7.1/doc/Doxyfoot.html000644 000770 000024 00000000227 12545036674 021271 0ustar00emilyecoffmessagebus000000 000000 libfixbuf-1.7.1/doc/doxygen.css000644 000770 000024 00000056354 12545036674 020773 0ustar00emilyecoffmessagebus000000 000000 /* The standard CSS for doxygen 1.8.5 */ body { padding: 16px 0; margin: 0; } .contents, .page-footer, #l-footer { padding: 16px; } /* @group Heading Levels */ h1.groupheader { font-size: 150%; } .title { font: 400 14px/28px Roboto,sans-serif; font-size: 150%; font-weight: bold; margin: 10px 2px; } h2.groupheader { border-bottom: 1px solid #879ECB; color: #354C7B; font-size: 150%; font-weight: normal; margin-top: 1.75em; padding-top: 8px; padding-bottom: 4px; width: 100%; } h3.groupheader { font-size: 100%; } h1, h2, h3, h4, h5, h6 { -webkit-transition: text-shadow 0.5s linear; -moz-transition: text-shadow 0.5s linear; -ms-transition: text-shadow 0.5s linear; -o-transition: text-shadow 0.5s linear; transition: text-shadow 0.5s linear; margin-right: 15px; } h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { text-shadow: 0 0 15px cyan; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { margin-top: 2px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #3D578C; font-weight: normal; text-decoration: none; } .contents a:visited { color: #4665A2; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #9CAFD4; color: #ffffff; border: 1px double #869DCA; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code, a.code:visited, a.line, a.line:visited { color: #4665A2; } a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { color: #4665A2; } /* @end */ dl.el { margin-left: -1cm; } pre.fragment { border: 1px solid #C4CFE5; background-color: #FBFCFD; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; font-family: monospace, fixed; font-size: 105%; } div.fragment { padding: 0px; margin: 0px; background-color: #FBFCFD; border: 1px solid #C4CFE5; } div.line { font-family: monospace, fixed; font-size: 13px; min-height: 13px; line-height: 1.0; text-wrap: unrestricted; white-space: -moz-pre-wrap; /* Moz */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS3 */ word-wrap: break-word; /* IE 5.5+ */ text-indent: -53px; padding-left: 53px; padding-bottom: 0px; margin: 0px; -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } div.line.glow { background-color: cyan; box-shadow: 0 0 10px cyan; } span.lineno { padding-right: 4px; text-align: right; border-right: 2px solid #0F0; background-color: #E8E8E8; white-space: pre; } span.lineno a { background-color: #D8D8D8; } span.lineno a:hover { background-color: #C8C8C8; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; border: solid thin #333; border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); } div.groupHeader { margin-left: 16px; margin-top: 12px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { padding: 16px 0; margin: 0; } td.indexkey { background-color: #EBEFF6; font-weight: bold; border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; white-space: nowrap; vertical-align: top; } td.indexvalue { background-color: #EBEFF6; border: 1px solid #C4CFE5; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #EEF1F7; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } address.footer { text-align: right; padding-right: 12px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } blockquote { background-color: #F7F8FB; border-left: 2px solid #9CAFD4; margin: 0 24px 0 4px; padding: 0 12px 0 16px; } /* @end */ /* .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } */ td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #A3B4D7; } th.dirtab { background: #EBEFF6; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #4A6AAA; } hr.footer { height: 1px; } /* @group Member Descriptions */ table.memberdecls { border-spacing: 0px; padding: 0px; } .memberdecls td, .fieldtable tr { -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } .memberdecls td.glow, .fieldtable tr.glow { background-color: cyan; box-shadow: 0 0 15px cyan; } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #F9FAFC; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memSeparator { border-bottom: 1px solid #DEE4F0; line-height: 1px; margin: 0px; padding: 0px; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memItemRight { width: 100%; } .memTemplParams { color: #4665A2; white-space: nowrap; font-size: 80%; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #4665A2; font-weight: normal; margin-left: 9px; } .memnav { background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .mempage { width: 100%; } .memitem { padding: 0; margin-bottom: 10px; margin-right: 5px; -webkit-transition: box-shadow 0.5s linear; -moz-transition: box-shadow 0.5s linear; -ms-transition: box-shadow 0.5s linear; -o-transition: box-shadow 0.5s linear; transition: box-shadow 0.5s linear; display: table !important; width: 100%; } .memitem.glow { box-shadow: 0 0 15px cyan; } .memname { font-weight: bold; margin-left: 6px; } .memname td { vertical-align: bottom; } .memproto, dl.reflist dt { border-top: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); border-top-right-radius: 4px; border-top-left-radius: 4px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 4px; -moz-border-radius-topleft: 4px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 4px; -webkit-border-top-left-radius: 4px; } .memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 10px 2px 10px; background-color: #FBFCFD; border-top-width: 0; background-image:url('nav_g.png'); background-repeat:repeat-x; background-color: #FFFFFF; /* opera specific markup */ border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; /* webkit specific markup */ -webkit-border-bottom-left-radius: 4px; -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } dl.reflist dt { padding: 5px; } dl.reflist dd { margin: 0px 0px 10px 0px; padding: 5px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } .paramname code { line-height: 14px; } .params, .retval, .exception, .tparams { margin-left: 0px; padding-left: 0px; } .params .paramname, .retval .paramname { font-weight: bold; vertical-align: top; } .params .paramtype { font-style: italic; vertical-align: top; } .params .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } table.mlabels { border-spacing: 0px; } td.mlabels-left { width: 100%; padding: 0px; } td.mlabels-right { vertical-align: bottom; padding: 0px; white-space: nowrap; } span.mlabels { margin-left: 8px; } span.mlabel { background-color: #728DC1; border-top:1px solid #5373B4; border-left:1px solid #5373B4; border-right:1px solid #C4CFE5; border-bottom:1px solid #C4CFE5; text-shadow: none; color: white; margin-right: 4px; padding: 2px 3px; border-radius: 3px; font-size: 7pt; white-space: nowrap; vertical-align: middle; } /* @end */ /* these are for tree view when not used as main index */ div.directory { margin: 10px 0px; border-top: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; width: 100%; } .directory table { border-collapse:collapse; } .directory td { margin: 0px; padding: 0px; vertical-align: top; } .directory td.entry { white-space: nowrap; padding-right: 6px; padding-top: 3px; } .directory td.entry a { outline:none; } .directory td.entry a img { border: none; } .directory td.desc { width: 100%; padding-left: 6px; padding-right: 6px; padding-top: 3px; border-left: 1px solid rgba(0,0,0,0.05); } .directory tr.even { padding-left: 6px; background-color: #F7F8FB; } .directory img { vertical-align: -30%; } .directory .levels { white-space: nowrap; width: 100%; text-align: right; font-size: 9pt; } .directory .levels span { cursor: pointer; padding-left: 2px; padding-right: 2px; color: #3D578C; } div.dynheader { margin-top: 8px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } address { font-style: normal; color: #2A3D61; } table.doxtable { border-collapse:collapse; margin-top: 4px; margin-bottom: 4px; } table.doxtable td, table.doxtable th { border: 1px solid #2D4068; padding: 3px 7px 2px; } table.doxtable th { background-color: #374F7F; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; } table.fieldtable { /*width: 100%;*/ margin-bottom: 10px; border: 1px solid #A8B8D9; border-spacing: 0px; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); } .fieldtable td, .fieldtable th { padding: 3px 7px 2px; } .fieldtable td.fieldtype, .fieldtable td.fieldname { white-space: nowrap; border-right: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; vertical-align: top; } .fieldtable td.fieldname { padding-top: 3px; } .fieldtable td.fielddoc { border-bottom: 1px solid #A8B8D9; /*width: 100%;*/ } .fieldtable td.fielddoc p:first-child { margin-top: 0px; } .fieldtable td.fielddoc p:last-child { margin-bottom: 2px; } .fieldtable tr:last-child td { border-bottom: none; } .fieldtable th { background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; font-size: 90%; color: #253555; padding-bottom: 4px; padding-top: 5px; text-align:left; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom: 1px solid #A8B8D9; } .tabsearch { top: 0px; left: 10px; height: 36px; background-image: url('tab_b.png'); z-index: 101; overflow: hidden; font-size: 13px; } .navpath ul { font-size: 11px; background-image:url('tab_b.png'); background-repeat:repeat-x; background-position: 0 -5px; height:30px; line-height:30px; color:#8AA0CC; border:solid 1px #C2CDE4; overflow:hidden; margin:0px; padding:0px; } .navpath li { list-style-type:none; float:left; padding-left:10px; padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } .navpath li.navelem a { height:32px; display:block; text-decoration: none; outline: none; color: #283A5D; font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); text-decoration: none; } .navpath li.navelem a:hover { color:#6884BD; } .navpath li.footer { list-style-type:none; float:right; padding-left:10px; padding-right:15px; background-image:none; background-repeat:no-repeat; background-position:right; color:#364D7C; font-size: 8pt; } div.summary { float: right; font-size: 8pt; padding-right: 5px; width: 50%; text-align: right; } div.summary a { white-space: nowrap; } div.ingroups { font-size: 8pt; width: 50%; text-align: left; } div.ingroups a { white-space: nowrap; } div.header { background-image:url('nav_h.png'); background-repeat:repeat-x; background-color: #F9FAFC; margin: 0px; border-bottom: 1px solid #C4CFE5; } div.headertitle { padding: 5px 5px 5px 10px; } dl { padding: 0 0 0 10px; } /* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ dl.section { margin-left: 0px; padding-left: 0px; } dl.note { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #D0C000; } dl.warning, dl.attention { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #FF0000; } dl.pre, dl.post, dl.invariant { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00D000; } dl.deprecated { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #505050; } dl.todo { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00C0E0; } dl.test { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #3030E0; } dl.bug { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #C08050; } dl.section dd { margin-bottom: 6px; } #projectlogo { text-align: center; vertical-align: bottom; border-collapse: separate; } #projectlogo img { border: 0px none; } #projectname { font: 300% Tahoma, Arial,sans-serif; margin: 0px; padding: 2px 0px; } #projectbrief { font: 120% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #projectnumber { font: 50% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #titlearea { padding: 0px; margin: 0px; width: 100%; border-bottom: 1px solid #5373B4; } .image { text-align: center; } .dotgraph { text-align: center; } .mscgraph { text-align: center; } .caption { font-weight: bold; } div.zoom { border: 1px solid #90A5CE; } dl.citelist { margin-bottom:50px; } dl.citelist dt { color:#334975; float:left; font-weight:bold; margin-right:10px; padding:5px; } dl.citelist dd { margin:2px 0; padding:5px 0; } div.toc { padding: 14px 25px; background-color: #F4F6FA; border: 1px solid #D8DFEE; border-radius: 7px 7px 7px 7px; float: right; height: auto; margin: 0 20px 10px 10px; width: 200px; } div.toc li { background: url("bdwn.png") no-repeat scroll 0 5px transparent; font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; margin-top: 5px; padding-left: 10px; padding-top: 2px; } div.toc h3 { font: bold 12px/1.2 Arial,FreeSans,sans-serif; color: #4665A2; border-bottom: 0 none; margin: 0; } div.toc ul { list-style: none outside none; border: medium none; padding: 0px; } div.toc li.level1 { margin-left: 0px; } div.toc li.level2 { margin-left: 15px; } div.toc li.level3 { margin-left: 30px; } div.toc li.level4 { margin-left: 45px; } .inherit_header { font-weight: bold; color: gray; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .inherit_header td { padding: 6px 0px 2px 5px; } .inherit { display: none; } tr.heading h2 { margin-top: 12px; margin-bottom: 4px; } /* tooltip related style info */ .ttc { position: absolute; display: none; } #powerTip { cursor: default; white-space: nowrap; background-color: white; border: 1px solid gray; border-radius: 4px 4px 4px 4px; box-shadow: 1px 1px 7px gray; display: none; font-size: smaller; max-width: 80%; opacity: 0.9; padding: 1ex 1em 1em; position: absolute; z-index: 2147483647; } #powerTip div.ttdoc { color: grey; font-style: italic; } #powerTip div.ttname a { font-weight: bold; } #powerTip div.ttname { font-weight: bold; } #powerTip div.ttdeci { color: #006318; } #powerTip div { margin: 0px; padding: 0px; font: 12px/16px Roboto,sans-serif; } #powerTip:before, #powerTip:after { content: ""; position: absolute; margin: 0px; } #powerTip.n:after, #powerTip.n:before, #powerTip.s:after, #powerTip.s:before, #powerTip.w:after, #powerTip.w:before, #powerTip.e:after, #powerTip.e:before, #powerTip.ne:after, #powerTip.ne:before, #powerTip.se:after, #powerTip.se:before, #powerTip.nw:after, #powerTip.nw:before, #powerTip.sw:after, #powerTip.sw:before { border: solid transparent; content: " "; height: 0; width: 0; position: absolute; } #powerTip.n:after, #powerTip.s:after, #powerTip.w:after, #powerTip.e:after, #powerTip.nw:after, #powerTip.ne:after, #powerTip.sw:after, #powerTip.se:after { border-color: rgba(255, 255, 255, 0); } #powerTip.n:before, #powerTip.s:before, #powerTip.w:before, #powerTip.e:before, #powerTip.nw:before, #powerTip.ne:before, #powerTip.sw:before, #powerTip.se:before { border-color: rgba(128, 128, 128, 0); } #powerTip.n:after, #powerTip.n:before, #powerTip.ne:after, #powerTip.ne:before, #powerTip.nw:after, #powerTip.nw:before { top: 100%; } #powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { border-top-color: #ffffff; border-width: 10px; margin: 0px -10px; } #powerTip.n:before { border-top-color: #808080; border-width: 11px; margin: 0px -11px; } #powerTip.n:after, #powerTip.n:before { left: 50%; } #powerTip.nw:after, #powerTip.nw:before { right: 14px; } #powerTip.ne:after, #powerTip.ne:before { left: 14px; } #powerTip.s:after, #powerTip.s:before, #powerTip.se:after, #powerTip.se:before, #powerTip.sw:after, #powerTip.sw:before { bottom: 100%; } #powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { border-bottom-color: #ffffff; border-width: 10px; margin: 0px -10px; } #powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { border-bottom-color: #808080; border-width: 11px; margin: 0px -11px; } #powerTip.s:after, #powerTip.s:before { left: 50%; } #powerTip.sw:after, #powerTip.sw:before { right: 14px; } #powerTip.se:after, #powerTip.se:before { left: 14px; } #powerTip.e:after, #powerTip.e:before { left: 100%; } #powerTip.e:after { border-left-color: #ffffff; border-width: 10px; top: 50%; margin-top: -10px; } #powerTip.e:before { border-left-color: #808080; border-width: 11px; top: 50%; margin-top: -11px; } #powerTip.w:after, #powerTip.w:before { right: 100%; } #powerTip.w:after { border-right-color: #ffffff; border-width: 10px; top: 50%; margin-top: -10px; } #powerTip.w:before { border-right-color: #808080; border-width: 11px; top: 50%; margin-top: -11px; } @media print { #top { display: none; } #side-nav { display: none; } #nav-path { display: none; } body { overflow:visible; } h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } .summary { display: none; } .memitem { page-break-inside: avoid; } #doc-content { margin-left:0 !important; height:auto !important; width:auto !important; overflow:inherit; display:inline; } } libfixbuf-1.7.1/doc/Doxyhead.html000644 000770 000024 00000002671 12545036674 021230 0ustar00emilyecoffmessagebus000000 000000 fixbuf- Documentation
libfixbuf-1.7.1/doc/LICENSE.txt000644 000770 000024 00000004610 12545036674 020413 0ustar00emilyecoffmessagebus000000 000000 Use of the libfixbuf system and related source code is subject to the terms of the following licenses: GNU Lesser General Public License (LGPL) Rights pursuant to Version 2.1, February 1999 Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013 NO WARRANTY ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE DELIVERABLES UNDER THIS LICENSE. Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie Mellon University, its trustees, officers, employees, and agents from all claims or demands made against them (and any related losses, expenses, or attorney's fees) arising out of, or relating to Licensee's and/or its sub licensees' negligent use or willful misuse of or negligent conduct or willful misconduct regarding the Software, facilities, or other rights or assistance granted by Carnegie Mellon University under this License, including, but not limited to, any claims of product liability, personal injury, death, damage to property, or violation of any laws or regulations. Carnegie Mellon University Software Engineering Institute authored documents are sponsored by the U.S. Department of Defense under Contract FA8721-05-C-0003. Carnegie Mellon University retains copyrights in all material produced under this contract. The U.S. Government retains a non-exclusive, royalty-free license to publish or reproduce these documents, or allow others to do so, for U.S. Government purposes only pursuant to the copyright license under the contract clause at 252.227.7013. libfixbuf-1.7.1/doc/news2xhtml.pl000755 000770 000024 00000003610 12406304621 021224 0ustar00emilyecoffmessagebus000000 000000 #!/usr/bin/perl $project = $ARGV[0] or die; $license = $ARGV[1] or die; if ($ARGV[2]) { # If provided, we'll only spit out elements for this number # of releases. We'll still show history for the others, but won't # provide download links for them. $relkeep = $ARGV[2]; } print < HEAD $ul = 0; $li = 0; local $/="undef"; $content = ; $relcount = 0; # This regexp is pretty liberal, so as to be able to grok most NEWS formats. while($content =~ /^Version (\d[^:]*?):?\s+\(?([^\n]+?)\)?\s*$\s*=+\s*((?:.(?!Version))+)/msg) { $ver = $1; $date = $2; $notes = $3; $relcount++; print < $ver $date RELHEAD1 ; if ($relkeep == undef || $relcount <= $relkeep) { print < RELHEAD2 ; } print <
    RELHEAD3 ; # First, see if items are delimited by \n\n if ($notes =~m@(.+?)\n\n+?@) { while ($notes =~m@(.+?)\n\n+?@msg) { print "\t\t
  • $1
  • \n"; } # The last item will be skipped if there aren't two blank lines # at the end, so we look for that and fix it here. if ($notes =~ /(.+?)(?:\n(?!\n))$/) { print "\t\t
  • $1
  • \n"; } } # Otherwise, assume items are delimited by \n else { while ($notes =~m@(.*?)\n+@msg) { print "\t\t
  • $1
  • \n"; } } print < RELTAIL ; } print < TAIL