diff --git a/.gitignore b/.gitignore index 620d3dc8a49200fcfae26619eb8a01741fcc41c5..50b970e27c91e25f2c273aaf35a93e5f5d0ece8b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ *.lai *.la *.a + +#qmake +*.pro.user +Makefile diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000000000000000000000000000000000..d159169d1050894d3ea3b98e1c965c4058208fe1 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile new file mode 100644 index 0000000000000000000000000000000000000000..7ba5acf497cc8a7303b30a099a81db8e5f6c9988 --- /dev/null +++ b/doxygen/Doxyfile @@ -0,0 +1,336 @@ + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = mcproxy +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = ../docs +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = . +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = ../doxygen/graphics/ +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Sebastian Woelke +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_RELPATH = http://www.mathjax.org/mathjax +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES + diff --git a/doxygen/Doxyfile_local b/doxygen/Doxyfile_local new file mode 100644 index 0000000000000000000000000000000000000000..61228c35f8cc56f7c6e7346db99354e3083741c0 --- /dev/null +++ b/doxygen/Doxyfile_local @@ -0,0 +1,336 @@ + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = mcproxy +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = ../docs +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../mcproxy/ +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = graphics/ +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = TracHeader.html +HTML_FOOTER = TracFooter.html +HTML_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Sebastian Woelke +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_RELPATH = http://www.mathjax.org/mathjax +SEARCHENGINE = NO +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES + diff --git a/doxygen/Doxyfile_old_local b/doxygen/Doxyfile_old_local new file mode 100644 index 0000000000000000000000000000000000000000..82e2747952f512576a5c8a1288b6f35e5477bc80 --- /dev/null +++ b/doxygen/Doxyfile_old_local @@ -0,0 +1,1705 @@ +# Doxyfile 1.7.3 + +# 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 +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = mcproxy + +# 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 = 0.2 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# 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 = ../docs/ + +# 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: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# 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 = NO + +# 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 = NO + +# 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 = YES + +# 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 if your file system +# 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 regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# 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 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 = NO + +# 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 + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# 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 makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_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 + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = YES + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# 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 = YES + +# 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 = NO + +# 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 this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = 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 = YES + +# 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 FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = 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 = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = 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 + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = 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 macro 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 macros 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 = NO + +# 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 NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = 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 <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> 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 = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# 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 = NO + +# 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 + +# The WARN_NO_PARAMDOC option can be enabled 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 = YES + +# 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 = pfx/lpfst/ pfx/ utils/ transport transport/ +INPUT = ../mcproxy/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# 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++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# 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 = YES + +# 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 = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system 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 EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# 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 = graphics/ + +# 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 <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> 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 or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +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 + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# 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 +# 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 +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = 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 = YES + +# 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 + +# 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 = TracHeader.html +HTML_FOOTER = TracFooter.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 = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# 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 HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# 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 compiled 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 CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# 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 + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# 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 [0,1..20]) +# that doxygen will group on one line in the generated HTML documentation. +# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value 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 (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = 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 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# 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. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +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, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# 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 = YES + +# 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 = YES + +# 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 + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = 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 = YES + +# 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 that overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these 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 = YES + +# 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 also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# 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 + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# 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 = NO + +# 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 = NO + +# 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 options 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 CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller 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 caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a 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, svg, gif or svg. +# 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 MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# 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 the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. 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 = YES + +# 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 diff --git a/doxygen/TracFooter.html b/doxygen/TracFooter.html new file mode 100755 index 0000000000000000000000000000000000000000..139597f9cb07c5d48bed18984ec4747f4b4f3438 --- /dev/null +++ b/doxygen/TracFooter.html @@ -0,0 +1,2 @@ + + diff --git a/doxygen/TracHeader.html b/doxygen/TracHeader.html new file mode 100755 index 0000000000000000000000000000000000000000..6e3090510c12cba7f04687e8595da3756cba040f --- /dev/null +++ b/doxygen/TracHeader.html @@ -0,0 +1,432 @@ +<style type="text/css"> +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font: normal Arial, Verdana, Geneva, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + #background-color: #e8eef2; + #border: 1px solid #84b0c7; + #text-align: center; + margin-left: 12px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover { + text-decoration: none; + background-color: #f2f2ff +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +BODY { + background: white; + color: black; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +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 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.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%; +} +a { + color: #1A41A8; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eef3f5; + border-width: 1px; + border-style: solid; + border-color: #dedeee; + -moz-border-radius: 8px 8px 8px 8px; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #d5e1e8; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #84b0c7; + font-weight: bold; + -moz-border-radius: 8px 8px 8px 8px; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #602020; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} + + +</style> + diff --git a/doxygen/auto_refresh-sh~ b/doxygen/auto_refresh-sh~ new file mode 100644 index 0000000000000000000000000000000000000000..c183e600087668f576869fe9c97b4138027abcf2 --- /dev/null +++ b/doxygen/auto_refresh-sh~ @@ -0,0 +1,2 @@ +#!/bin/bash +#refres doxygen on trac diff --git a/doxygen/graphics/interaction.png b/doxygen/graphics/interaction.png new file mode 100644 index 0000000000000000000000000000000000000000..913b24902be298a780017cc635a9985972833f1b Binary files /dev/null and b/doxygen/graphics/interaction.png differ diff --git a/doxygen/graphics/overview.png b/doxygen/graphics/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..bd393e4a2a1054a52e7304478fea84b3f99c63ff Binary files /dev/null and b/doxygen/graphics/overview.png differ diff --git a/mcproxy/.clang_complete b/mcproxy/.clang_complete new file mode 100644 index 0000000000000000000000000000000000000000..a2c237f2a8defb52b7d4e8ef7c1786a725dda30b --- /dev/null +++ b/mcproxy/.clang_complete @@ -0,0 +1,47 @@ +-DDEBUG +-include src/main.cpp +-include src/hamcast_logging.cpp + +-include src/utils/mc_socket.cpp +-include src/utils/addr_storage.cpp +-include src/utils/mroute_socket.cpp +-include src/utils/if_prop.cpp + +-include src/proxy/proxy.cpp +-include src/proxy/sender.cpp +-include src/proxy/receiver.cpp +-include src/proxy/mld_receiver.cpp +-include src/proxy/igmp_receiver.cpp +-include src/proxy/mld_sender.cpp +-include src/proxy/igmp_sender.cpp +-include src/proxy/proxy_instance.cpp +-include src/proxy/routing.cpp +-include src/proxy/worker.cpp +-include src/proxy/timing.cpp +-include src/proxy/check_if.cpp +-include src/proxy/check_source.cpp + +-include include/hamcast_logging.h + +-include include/utils/mc_socket.hpp +-include include/utils/addr_storage.hpp +-include include/utils/mc_timers_values.hpp +-include include/utils/mroute_socket.hpp +-include include/utils/if_prop.hpp + +-include include/proxy/proxy.hpp +-include include/proxy/sender.hpp +-include include/proxy/receiver.hpp +-include include/proxy/mld_receiver.hpp +-include include/proxy/igmp_receiver.hpp +-include include/proxy/mld_sender.hpp +-include include/proxy/igmp_sender.hpp +-include include/proxy/proxy_instance.hpp +-include include/proxy/message_queue.hpp +-include include/proxy/message_format.hpp +-include include/proxy/routing.hpp +-include include/proxy/worker.hpp +-include include/proxy/timing.hpp +-include include/proxy/check_if.hpp +-include include/proxy/check_source.hpp + diff --git a/mcproxy/Makefile b/mcproxy/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..849ba8a2b421c0d4aa3df791268a311fb423b444 --- /dev/null +++ b/mcproxy/Makefile @@ -0,0 +1,508 @@ +############################################################################# +# Makefile for building: mcproxy +# Generated by qmake (3.0) (Qt 5.0.1) on: pe kes�kuuta 21 23:14:06 2013 +# Project: mcproxy.pro +# Template: app +# Command: /usr/lib/x86_64-linux-gnu/qt5/bin/qmake -o Makefile mcproxy.pro +############################################################################# + +MAKEFILE = Makefile + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = +CFLAGS = -m64 -pipe -g -Wall -W -fPIE $(DEFINES) +CXXFLAGS = -m64 -pipe -ggdb -pedantic -ansi -g -Wall -W -fPIE $(DEFINES) +INCPATH = -I/usr/share/qt5/mkspecs/linux-g++-64 -I. +LINK = g++ +LFLAGS = -m64 +LIBS = $(SUBLIBS) -L/usr/lib -lboost_thread -lboost_date_time -lboost_system +AR = ar cqs +RANLIB = +QMAKE = /usr/lib/x86_64-linux-gnu/qt5/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = cp -f +COPY_DIR = cp -f -R +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = src/main.cpp \ + src/hamcast_logging.cpp \ + src/utils/mc_socket.cpp \ + src/utils/addr_storage.cpp \ + src/utils/mroute_socket.cpp \ + src/utils/if_prop.cpp \ + src/proxy/proxy.cpp \ + src/proxy/sender.cpp \ + src/proxy/receiver.cpp \ + src/proxy/mld_receiver.cpp \ + src/proxy/igmp_receiver.cpp \ + src/proxy/mld_sender.cpp \ + src/proxy/igmp_sender.cpp \ + src/proxy/proxy_instance.cpp \ + src/proxy/routing.cpp \ + src/proxy/worker.cpp \ + src/proxy/timing.cpp \ + src/proxy/check_if.cpp \ + src/proxy/check_source.cpp +OBJECTS = main.o \ + hamcast_logging.o \ + mc_socket.o \ + addr_storage.o \ + mroute_socket.o \ + if_prop.o \ + proxy.o \ + sender.o \ + receiver.o \ + mld_receiver.o \ + igmp_receiver.o \ + mld_sender.o \ + igmp_sender.o \ + proxy_instance.o \ + routing.o \ + worker.o \ + timing.o \ + check_if.o \ + check_source.o +DIST = /usr/share/qt5/mkspecs/features/spec_pre.prf \ + /usr/share/qt5/mkspecs/common/shell-unix.conf \ + /usr/share/qt5/mkspecs/common/unix.conf \ + /usr/share/qt5/mkspecs/common/linux.conf \ + /usr/share/qt5/mkspecs/common/gcc-base.conf \ + /usr/share/qt5/mkspecs/common/gcc-base-unix.conf \ + /usr/share/qt5/mkspecs/common/g++-base.conf \ + /usr/share/qt5/mkspecs/common/g++-unix.conf \ + /usr/share/qt5/mkspecs/qconfig.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_core.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_gui.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_network.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_sql.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_xml.pri \ + /usr/share/qt5/mkspecs/features/qt_functions.prf \ + /usr/share/qt5/mkspecs/features/qt_config.prf \ + /usr/share/qt5/mkspecs/linux-g++-64/qmake.conf \ + /usr/share/qt5/mkspecs/features/spec_post.prf \ + /usr/share/qt5/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt5/mkspecs/features/default_pre.prf \ + /usr/share/qt5/mkspecs/features/unix/default_pre.prf \ + /usr/share/qt5/mkspecs/features/debug.prf \ + /usr/share/qt5/mkspecs/features/default_post.prf \ + /usr/share/qt5/mkspecs/features/shared.prf \ + /usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf \ + /usr/share/qt5/mkspecs/features/warn_on.prf \ + /usr/share/qt5/mkspecs/features/wayland-scanner.prf \ + /usr/share/qt5/mkspecs/features/testcase_targets.prf \ + /usr/share/qt5/mkspecs/features/exceptions.prf \ + /usr/share/qt5/mkspecs/features/yacc.prf \ + /usr/share/qt5/mkspecs/features/lex.prf \ + mcproxy.pro \ + mcproxy.pro +QMAKE_TARGET = mcproxy +DESTDIR = +TARGET = mcproxy + + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + { test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9]\+\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true + +Makefile: mcproxy.pro /usr/share/qt5/mkspecs/linux-g++-64/qmake.conf /usr/share/qt5/mkspecs/features/spec_pre.prf \ + /usr/share/qt5/mkspecs/common/shell-unix.conf \ + /usr/share/qt5/mkspecs/common/unix.conf \ + /usr/share/qt5/mkspecs/common/linux.conf \ + /usr/share/qt5/mkspecs/common/gcc-base.conf \ + /usr/share/qt5/mkspecs/common/gcc-base-unix.conf \ + /usr/share/qt5/mkspecs/common/g++-base.conf \ + /usr/share/qt5/mkspecs/common/g++-unix.conf \ + /usr/share/qt5/mkspecs/qconfig.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_core.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_gui.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_network.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_sql.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri \ + /usr/share/qt5/mkspecs/modules/qt_lib_xml.pri \ + /usr/share/qt5/mkspecs/features/qt_functions.prf \ + /usr/share/qt5/mkspecs/features/qt_config.prf \ + /usr/share/qt5/mkspecs/linux-g++-64/qmake.conf \ + /usr/share/qt5/mkspecs/features/spec_post.prf \ + /usr/share/qt5/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt5/mkspecs/features/default_pre.prf \ + /usr/share/qt5/mkspecs/features/unix/default_pre.prf \ + /usr/share/qt5/mkspecs/features/debug.prf \ + /usr/share/qt5/mkspecs/features/default_post.prf \ + /usr/share/qt5/mkspecs/features/shared.prf \ + /usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf \ + /usr/share/qt5/mkspecs/features/warn_on.prf \ + /usr/share/qt5/mkspecs/features/wayland-scanner.prf \ + /usr/share/qt5/mkspecs/features/testcase_targets.prf \ + /usr/share/qt5/mkspecs/features/exceptions.prf \ + /usr/share/qt5/mkspecs/features/yacc.prf \ + /usr/share/qt5/mkspecs/features/lex.prf \ + mcproxy.pro + $(QMAKE) -o Makefile mcproxy.pro +/usr/share/qt5/mkspecs/features/spec_pre.prf: +/usr/share/qt5/mkspecs/common/shell-unix.conf: +/usr/share/qt5/mkspecs/common/unix.conf: +/usr/share/qt5/mkspecs/common/linux.conf: +/usr/share/qt5/mkspecs/common/gcc-base.conf: +/usr/share/qt5/mkspecs/common/gcc-base-unix.conf: +/usr/share/qt5/mkspecs/common/g++-base.conf: +/usr/share/qt5/mkspecs/common/g++-unix.conf: +/usr/share/qt5/mkspecs/qconfig.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_core.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_gui.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_network.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_sql.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri: +/usr/share/qt5/mkspecs/modules/qt_lib_xml.pri: +/usr/share/qt5/mkspecs/features/qt_functions.prf: +/usr/share/qt5/mkspecs/features/qt_config.prf: +/usr/share/qt5/mkspecs/linux-g++-64/qmake.conf: +/usr/share/qt5/mkspecs/features/spec_post.prf: +/usr/share/qt5/mkspecs/features/exclusive_builds.prf: +/usr/share/qt5/mkspecs/features/default_pre.prf: +/usr/share/qt5/mkspecs/features/unix/default_pre.prf: +/usr/share/qt5/mkspecs/features/debug.prf: +/usr/share/qt5/mkspecs/features/default_post.prf: +/usr/share/qt5/mkspecs/features/shared.prf: +/usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf: +/usr/share/qt5/mkspecs/features/warn_on.prf: +/usr/share/qt5/mkspecs/features/wayland-scanner.prf: +/usr/share/qt5/mkspecs/features/testcase_targets.prf: +/usr/share/qt5/mkspecs/features/exceptions.prf: +/usr/share/qt5/mkspecs/features/yacc.prf: +/usr/share/qt5/mkspecs/features/lex.prf: +mcproxy.pro: +qmake: FORCE + @$(QMAKE) -o Makefile mcproxy.pro + +qmake_all: FORCE + +dist: + @test -d .tmp/mcproxy1.0.0 || $(MKDIR) .tmp/mcproxy1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/mcproxy1.0.0/ && (cd `dirname .tmp/mcproxy1.0.0` && $(TAR) mcproxy1.0.0.tar mcproxy1.0.0 && $(COMPRESS) mcproxy1.0.0.tar) && $(MOVE) `dirname .tmp/mcproxy1.0.0`/mcproxy1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/mcproxy1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +doc: + doxygen ../doxygen/Doxyfile + +check: first + +compiler_wayland-server-header_make_all: +compiler_wayland-server-header_clean: +compiler_wayland-client-header_make_all: +compiler_wayland-client-header_clean: +compiler_wayland-code_make_all: +compiler_wayland-code_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: + +####### Compile + +main.o: src/main.cpp include/hamcast_logging.h \ + include/utils/if_prop.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mroute_socket.hpp \ + include/proxy/proxy.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/proxy/worker.hpp \ + include/proxy/routing.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/receiver.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_source.hpp \ + include/proxy/check_if.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o src/main.cpp + +hamcast_logging.o: src/hamcast_logging.cpp include/hamcast_logging.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o hamcast_logging.o src/hamcast_logging.cpp + +mc_socket.o: src/utils/mc_socket.cpp include/hamcast_logging.h \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mc_socket.o src/utils/mc_socket.cpp + +addr_storage.o: src/utils/addr_storage.cpp include/hamcast_logging.h \ + include/utils/addr_storage.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o addr_storage.o src/utils/addr_storage.cpp + +mroute_socket.o: src/utils/mroute_socket.cpp include/hamcast_logging.h \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mroute_socket.o src/utils/mroute_socket.cpp + +if_prop.o: src/utils/if_prop.cpp include/hamcast_logging.h \ + include/utils/if_prop.hpp \ + include/utils/addr_storage.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o if_prop.o src/utils/if_prop.cpp + +proxy.o: src/proxy/proxy.cpp include/hamcast_logging.h \ + include/proxy/proxy.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/proxy/worker.hpp \ + include/proxy/routing.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/receiver.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_source.hpp \ + include/proxy/igmp_receiver.hpp \ + include/proxy/mld_receiver.hpp \ + include/proxy/check_if.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o proxy.o src/proxy/proxy.cpp + +sender.o: src/proxy/sender.cpp include/hamcast_logging.h \ + include/proxy/sender.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/if_prop.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o sender.o src/proxy/sender.cpp + +receiver.o: src/proxy/receiver.cpp include/hamcast_logging.h \ + include/proxy/receiver.hpp \ + include/proxy/worker.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o receiver.o src/proxy/receiver.cpp + +mld_receiver.o: src/proxy/mld_receiver.cpp include/hamcast_logging.h \ + include/proxy/mld_receiver.hpp \ + include/proxy/receiver.hpp \ + include/proxy/worker.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/routing.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_source.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mld_receiver.o src/proxy/mld_receiver.cpp + +igmp_receiver.o: src/proxy/igmp_receiver.cpp include/hamcast_logging.h \ + include/proxy/igmp_receiver.hpp \ + include/proxy/receiver.hpp \ + include/proxy/worker.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/routing.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_source.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o igmp_receiver.o src/proxy/igmp_receiver.cpp + +mld_sender.o: src/proxy/mld_sender.cpp include/hamcast_logging.h \ + include/proxy/mld_sender.hpp \ + include/proxy/sender.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/if_prop.hpp \ + include/utils/mc_timers_values.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mld_sender.o src/proxy/mld_sender.cpp + +igmp_sender.o: src/proxy/igmp_sender.cpp include/hamcast_logging.h \ + include/proxy/igmp_sender.hpp \ + include/proxy/sender.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/if_prop.hpp \ + include/utils/mc_timers_values.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o igmp_sender.o src/proxy/igmp_sender.cpp + +proxy_instance.o: src/proxy/proxy_instance.cpp include/hamcast_logging.h \ + include/proxy/proxy_instance.hpp \ + include/utils/addr_storage.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/proxy/worker.hpp \ + include/proxy/routing.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/receiver.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_source.hpp \ + include/utils/mc_timers_values.hpp \ + include/proxy/igmp_receiver.hpp \ + include/proxy/mld_receiver.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o proxy_instance.o src/proxy/proxy_instance.cpp + +routing.o: src/proxy/routing.cpp include/hamcast_logging.h \ + include/proxy/routing.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/if_prop.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o routing.o src/proxy/routing.cpp + +worker.o: src/proxy/worker.cpp include/hamcast_logging.h \ + include/proxy/worker.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/utils/addr_storage.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o worker.o src/proxy/worker.cpp + +timing.o: src/proxy/timing.cpp include/hamcast_logging.h \ + include/proxy/timing.hpp \ + include/proxy/message_format.hpp \ + include/utils/addr_storage.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/worker.hpp \ + include/proxy/routing.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp \ + include/utils/if_prop.hpp \ + include/proxy/sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/receiver.hpp \ + include/proxy/check_source.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o timing.o src/proxy/timing.cpp + +check_if.o: src/proxy/check_if.cpp include/hamcast_logging.h \ + include/proxy/check_if.hpp \ + include/utils/if_prop.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o check_if.o src/proxy/check_if.cpp + +check_source.o: src/proxy/check_source.cpp include/hamcast_logging.h \ + include/utils/addr_storage.hpp \ + include/proxy/check_source.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/mc_socket.hpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o check_source.o src/proxy/check_source.cpp + +####### Install + +install_target: first FORCE + @test -d $(INSTALL_ROOT)/usr/local/bin || $(MKDIR) $(INSTALL_ROOT)/usr/local/bin + -$(INSTALL_PROGRAM) "$(QMAKE_TARGET)" "$(INSTALL_ROOT)/usr/local/bin/$(QMAKE_TARGET)" + +uninstall_target: FORCE + -$(DEL_FILE) "$(INSTALL_ROOT)/usr/local/bin/$(QMAKE_TARGET)" + -$(DEL_DIR) $(INSTALL_ROOT)/usr/local/bin/ + + +install: install_target FORCE + +uninstall: uninstall_target FORCE + +FORCE: + diff --git a/mcproxy/include/hamcast_logging.h b/mcproxy/include/hamcast_logging.h new file mode 100644 index 0000000000000000000000000000000000000000..34b71bd32dd26d18076e931e066fdd81eb58b8ce --- /dev/null +++ b/mcproxy/include/hamcast_logging.h @@ -0,0 +1,116 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Dominik Charousset <dominik.charousset@haw-hamburg.de> + */ + +#ifndef HAMCAST_LOGGING_H +#define HAMCAST_LOGGING_H + +#ifdef __cplusplus +#include <sstream> +extern "C" { +#endif + +#define HC_LOG_TRACE_LVL 0x0100 +#define HC_LOG_DEBUG_LVL 0x0200 +#define HC_LOG_INFO_LVL 0x0300 +#define HC_LOG_WARN_LVL 0x0400 +#define HC_LOG_ERROR_LVL 0x0500 +#define HC_LOG_FATAL_LVL 0x0600 + +typedef void (*hc_log_fun_t)(int, const char*, const char*); + +/** + * @brief Get a pointer to the current active log function. + */ +hc_log_fun_t hc_get_log_fun(); + +/** + * @brief Set the log function to @p function_ptr. + */ +void hc_set_log_fun(hc_log_fun_t function_ptr); + +/** + * @brief Invokes the function pointer returned by {@link hc_get_log_fun()} + * if not NULL. + */ +void hc_log(int log_lvl, const char* function_name, const char* log_msg); + +/** + * @brief Get a default logging implementation (one logfile per thread). + * @param log_lvl The desired logging level. + */ +void hc_set_default_log_fun(int log_lvl); + +#ifdef __cplusplus +} +#endif + +#ifdef __GNUC__ +# define HC_FUN __PRETTY_FUNCTION__ +#else +# define HC_FUN __FUNCTION__ +#endif + +#ifdef __cplusplus + +#define HC_DO_LOG(message, loglvl) \ + { \ + std::ostringstream scoped_oss; \ + scoped_oss << message; \ + std::string scoped_osss = scoped_oss.str(); \ + hc_log( loglvl , HC_FUN , scoped_osss.c_str()); \ + } ((void) 0) + +namespace { +template<int m_lvl> +struct HC_trace_helper +{ + const char* m_fun; + HC_trace_helper(const char* fun, const std::string& initmsg) : m_fun(fun) + { + std::string msg = "ENTER"; + if (!initmsg.empty()) + { + msg += ": "; + msg += initmsg; + } + hc_log(m_lvl, m_fun, msg.c_str()); + } + ~HC_trace_helper() { hc_log(m_lvl, m_fun, "LEAVE"); } +}; +} + +#define HC_LOG_TRACE(message) \ + ::std::ostringstream hc_trace_helper_##__LINE__ ; \ + hc_trace_helper_##__LINE__ << message ; \ + ::HC_trace_helper< HC_LOG_TRACE_LVL > hc_fun_HC_trace_helper_##__LINE__ \ + ( HC_FUN , hc_trace_helper_##__LINE__ .str() ) + +#else +# define HC_DO_LOG(message, loglvl) hc_log( loglvl , HC_FUN , message) +# define HC_LOG_TRACE(message) HC_DO_LOG(message, HC_LOG_TRACE_LVL) +#endif + +#define HC_LOG_DEBUG(message) HC_DO_LOG(message, HC_LOG_DEBUG_LVL) +#define HC_LOG_INFO(message) HC_DO_LOG(message, HC_LOG_INFO_LVL) +#define HC_LOG_WARN(message) HC_DO_LOG(message, HC_LOG_WARN_LVL) +#define HC_LOG_ERROR(message) HC_DO_LOG(message, HC_LOG_ERROR_LVL) +#define HC_LOG_FATAL(message) HC_DO_LOG(message, HC_LOG_FATAL_LVL) + +#endif // HAMCAST_LOGGING_H diff --git a/mcproxy/include/proxy/check_if.hpp b/mcproxy/include/proxy/check_if.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2aa4445586088e36061f8812e785bc87d8f8b060 --- /dev/null +++ b/mcproxy/include/proxy/check_if.hpp @@ -0,0 +1,89 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_proxy Proxy + * @{ + */ + +#ifndef CHECK_IF_H +#define CHECK_IF_H + +#include "include/utils/if_prop.hpp" +#include "vector" + +/** + * @brief Monitored the running state of the network interfaces. + */ +class check_if +{ +private: + int m_addr_family; + + if_prop m_if_property_a; + if_prop m_if_property_b; + if_prop* m_current_prop; + + std::vector<int> m_check_lst; + std::vector<int> m_swap_to_up; + std::vector<int> m_swap_to_down; + +public: + + /** + * @brief Create a check_if instance. + */ + check_if(); + + //return all dont running interfaces + /** + * @brief Initialize check_if for a specific IP version. + * @param check_lst a list of monitored interface indexes + * @param addr_family used IP version (AF_INET or AF_INET6) + * @return Return all dont running interfaces to have an consistent start state. + */ + std::vector<int> init(std::vector<int>& check_lst, int addr_family); + + /** + * @brief Trigger the monitoring. + * @return Return true on success. + */ + bool check(); + + /** + * @brief Return the interface indexes who swap their running state to up after the last monitoring trigger. + */ + std::vector<int> swap_to_up(); + + /** + * @brief Return the interface indexes who swap their running state to down after the last monitoring trigger. + */ + std::vector<int> swap_to_down(); + + /** + * @brief Test the functionality of check_if. + */ + static void test_check_if(); +}; + +#endif // CHECK_IF_H +/** @} */ diff --git a/mcproxy/include/proxy/check_source.hpp b/mcproxy/include/proxy/check_source.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f35712903a964533c112ade232e8d94b61a92c01 --- /dev/null +++ b/mcproxy/include/proxy/check_source.hpp @@ -0,0 +1,100 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_proxy_instance Proxy Instance + * @{ + */ + +#ifndef CHECK_SOURCE_H +#define CHECK_SOURCE_H + +//#include "include/utils/mc_tables.hpp" +#include <map> +#include "include/utils/mroute_socket.hpp" + +//-------------------------------------------------- +/** + * @brief Data structure to save a specific multicast route + * @param first source address + * @param second group address + **/ +typedef std::pair<addr_storage, addr_storage> src_grp_pair; + +//-------------------------------------------------- +/** + * @brief Data structure to save a packet counter for a specific multicast route + * @param first (source address, group address) #src_grp_pair + * @param second counter for received packets + */ +typedef std::map<src_grp_pair, int> pkt_cnt_map; + +/** + * @brief Pair for #pkt_cnt_map. + * @param first (source address, group address) #src_grp_pair + * @param second counter for received packets + */ +typedef std::pair<src_grp_pair, int> pkt_cnt_pair; + +//-------------------------------------------------- + +/** + * @brief Monitored the forwarding rules in the Linux kernel table. If a source is unused for + * a long time when it can be removed. + */ +class check_source{ +private: + int m_addr_family; + + mroute_socket* m_sock; + + pkt_cnt_map m_check_src_a; + pkt_cnt_map m_check_src_b; + pkt_cnt_map* m_current_check; + +public: + + /** + * @brief Initialize check_source. + * @param addr_family used IP version (AF_INET or AF_INET6) + * @return Return true on success. + */ + bool init(int addr_family, mroute_socket* sock ); + + /** + * @brief Trigger the monitoring. + * @return Return true on success. + */ + bool check(); + + /** + * @brief Check wether an unique forwarding rule is unused since the last monitoring trigger. + * @param vif virutal interface of the forwarding rule + * @param src_addr source address of the forwarding rule + * @param g_addr multicast group address of the forwarding rule + */ + bool is_src_unused(int vif, addr_storage src_addr, addr_storage g_addr); + +}; + +#endif // CHECK_IF_H +/** @} */ diff --git a/mcproxy/include/proxy/igmp_receiver.hpp b/mcproxy/include/proxy/igmp_receiver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6979abcb056a0cc8daff52abbefcef1dceccf357 --- /dev/null +++ b/mcproxy/include/proxy/igmp_receiver.hpp @@ -0,0 +1,63 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_receiver Receiver + * @{ + */ + +#ifndef IGMP_RECEIVER_HPP +#define IGMP_RECEIVER_HPP + +#include "include/proxy/receiver.hpp" + +/** + * @brief Size of the router alert option. + */ +#define IGMP_RECEIVER_IPV4_ROUTER_ALERT_OPT_SIZE 4 //RFC 2711 + +/** + * @brief Cache Miss message received form the Linux Kernel identified by this ip verion. + */ +#define IGMP_RECEIVER_KERNEL_MSG 0 + +/** + * @brief Receive IGMP messages. + */ +class igmp_receiver : public receiver { +private: + + int get_ctrl_min_size(); + int get_iov_min_size(); + void analyse_packet(struct msghdr* msg, int info_size); + + //return the interface index to addr, on error return 0 + int map_ip2if_index(const addr_storage& src_addr); +public: + /** + * @brief Create an igmp_receiver. + */ + igmp_receiver(); +}; + +#endif // IGMP_RECEIVER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/igmp_sender.hpp b/mcproxy/include/proxy/igmp_sender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fc87b828b4fac869c6666deefd5c8b5dcfa33bfd --- /dev/null +++ b/mcproxy/include/proxy/igmp_sender.hpp @@ -0,0 +1,59 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_sender Sender + * @{ + */ + +#ifndef IGMP_SENDER_HPP +#define IGMP_SENDER_HPP + +#include "include/proxy/sender.hpp" + +/** + * @brief Generates IGMP messages. + */ +class igmp_sender : public sender{ +private: + enum msg_type { //for intern type handling + GENERAL_QUERY, GROUP_SPECIFIC_QUERY + }; + + bool create_mc_query(msg_type type, unsigned char* buf,const addr_storage* g_addr=NULL); + int get_msg_min_size(); +public: + /** + * @brief Create an igmp_sender. + */ + igmp_sender(); + + bool init(int addr_family, int version); + + bool send_general_query(int if_index); + bool send_group_specific_query(int if_index, const addr_storage& g_addr); + bool send_report(int if_index, const addr_storage& g_addr); + bool send_leave(int if_index, const addr_storage& g_addr); +}; + +#endif // IGMP_SENDER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/message_format.hpp b/mcproxy/include/proxy/message_format.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f1a89c98561c05d43bbe1294e91cf980b5f00285 --- /dev/null +++ b/mcproxy/include/proxy/message_format.hpp @@ -0,0 +1,417 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_communication Communication + * @{ + */ + +#ifndef MESSAGE_FORMAT_HPP +#define MESSAGE_FORMAT_HPP + +#include "include/hamcast_logging.h" +#include "include/utils/addr_storage.hpp" +#include <sys/socket.h> +#include <boost/intrusive_ptr.hpp> +#include <iostream> +#include <string> +#include <list> + +#include <sstream> +#include <boost/thread.hpp> + + +/** + * @brief Message container implements an intrusive pointer to save a + * pointer of a message with a reference counter. + */ +struct intrusive_message{ + intrusive_message(): refs(0) {} + +private: + int refs; + boost::mutex m_global_lock; + + /** + * @brief Release the memory space of the message if no one refer to this message. + */ + friend inline void intrusive_ptr_release(struct intrusive_message* p){ + HC_LOG_TRACE(""); + + p->m_global_lock.lock(); + if(--p->refs == 0 ) { + HC_LOG_DEBUG("del element"); + p->m_global_lock.unlock(); + delete p; + return; + } + HC_LOG_DEBUG("release ref ==> now: " << p->refs); + p->m_global_lock.unlock(); + } + + /** + * @brief Increment the reference counter if + */ + friend inline void intrusive_ptr_add_ref(struct intrusive_message* p){ + HC_LOG_TRACE(""); + + boost::lock_guard<boost::mutex> lock(p->m_global_lock); + p->refs++; + HC_LOG_DEBUG("add ref ==> now: " << p->refs); + } +}; + +//##-- generic struct for message_queue --## +/** + * @brief Generic message for the #message_queue. + */ +typedef struct { + + /** + * @brief Available message types. + */ + enum message_type{ + TEST_MSG /** Test message type to test the message queue and the intrusive pointer. */, + CLOCK_MSG /** Message type used from module @ref mod_timer. */, + RECEIVER_MSG /** Message type used from module @ref mod_receiver. */, + CONFIG_MSG /** Message type used from module @ref mod_proxy to set and delete interfaces of the proxy instances. */, + EXIT_CMD /** Message type to stop the proxy instances. */, + DEBUG_MSG /** Message type to collect debug information for the module @ref mod_proxy. */ + }; + + std::string msg_type_to_string(){ + HC_LOG_TRACE(""); + switch(type){ + case TEST_MSG: return "TEST_MSG"; + case CLOCK_MSG: return "CLOCK_MSG"; + case RECEIVER_MSG: return "RECEIVER_MSG"; + case DEBUG_MSG: return "DEBUG_MSG"; + case EXIT_CMD: return "EXIT_CMD"; + case CONFIG_MSG: return "CONFIG_MSG"; + default: return "ERROR"; + } + } + + /** + * @brief Message type of the Message. + */ + message_type type; + + /** + * @brief Intrusive pointer to the message contain. + */ + boost::intrusive_ptr<struct intrusive_message> msg; +} proxy_msg; + + +//##-- possible messages --## +/** + * @brief Test message to test the message queue and the intrusive pointer. + */ +struct test_msg: public intrusive_message{ + /** + * @brief Create a test_msg. + */ + test_msg(int value): m_value(value) { + HC_LOG_TRACE(""); + } + + ~test_msg(){ + HC_LOG_TRACE(""); + } + + /** + * @brief Do some output. + */ + void test(){ + HC_LOG_TRACE(""); + std::cout << "Test Message value:" << m_value << std::endl; + } +private: + int m_value; +}; + +//message_type: CLOCK_MSG +/** + * @brief Message used from module @ref mod_timer. It is the contain of a reminder. + */ +struct clock_msg: public intrusive_message{ + + /** + * @brief A module @ref mod_timer can remind about this actions. + */ + enum clock_action{ + SEND_GQ_TO_ALL /** Send to all downstreams General Queries. */, + SEND_GSQ /** Send a Group Specific Query to an interface and to a group. */, + DEL_GROUP /** Delete a group from an interface. */, + SEND_GQ /** not implementeted at the moment. */ + }; + + /** + * @brief Constructor used for the actions DEL_GROUP, SEND_GQ and SEND_GSQ. + * @param type type of the clock action + * @param if_index actionfor a specific interface index + * @param g_addr action for a specific multicast group + */ + clock_msg(clock_action type, int if_index, addr_storage g_addr){ + HC_LOG_TRACE(""); + this->type = type; + this->if_index = if_index; + this->g_addr = g_addr; + } + + /** + * @brief Constructor used for the action SEND_GQ_TO_ALL. + * @param type type of the clock action + */ + clock_msg(clock_action type){ + this->type = type; + } + + ~clock_msg(){ + HC_LOG_TRACE(""); + } + + /** + * @brief Type of the clock message. + */ + clock_action type; + + /** + * @brief Action on a specific interface index. + */ + int if_index; + + /** + * @brief Action for a specific multicast group. + */ + addr_storage g_addr; +}; + +//message_type: RECEIVER_MSG +/** + * @brief Message used from module @ref mod_receiver to inform the + * module @ref mod_proxy_instance of received a message. + */ +struct receiver_msg: public intrusive_message{ + + /** + * @brief A module @ref mod_receiver can receive the following messages. + */ + enum receiver_action{ + JOIN /** a Join message for a specific group on a specific interface */, + LEAVE /** a Leave message for a specific group on a specific interface */, + CACHE_MISS /** a Cache Miss message from the Linux Kernel */ + }; + + //CACHE_MISS + /** + * @brief Constructor used for the action CACHE_MISS. + * @param type type of the receiver action + * @param if_index action for a specific interface index + * @param src_addr action for a specific source + * @param g_addr action for a specific multicast group + */ + receiver_msg(receiver_action type, int if_index, addr_storage src_addr, addr_storage g_addr): + type(type), if_index(if_index), src_addr(src_addr), g_addr(g_addr) { + HC_LOG_TRACE(""); + } + + //JOIN, LEAVE + /** + * @brief Constructor used for the actions JOIN and LEAVE. + * @param type type of the receiver action + * @param if_index action for a specific interface index + * @param g_addr action for a specific multicast group + */ + receiver_msg(receiver_action type, int if_index, addr_storage g_addr): + type(type), if_index(if_index), g_addr(g_addr) { + HC_LOG_TRACE(""); + } + + ~receiver_msg(){ + HC_LOG_TRACE(""); + } + + /** + * @brief Type of the receiver message. + */ + receiver_action type; + + /** + * @brief Action on a specific interface index. + */ + int if_index; + + /** + * @brief Action for a specific source address. + */ + addr_storage src_addr; + + /** + * @brief Action for a specific multicast group. + */ + addr_storage g_addr; + +}; + +//message_type: CONFIG_MSG +/** + * @brief Message used from module @ref mod_proxy to + * set and delete interfaces of the proxy instances. + */ +struct config_msg: public intrusive_message{ + + /** + * @brief configure types for proxy instances + */ + enum config_action{ + ADD_DOWNSTREAM /** downstreams can be added to a proxy instance*/, + DEL_DOWNSTREAM /** downstreams can be delete form a proxy instance */, + SET_UPSTREAM /** an upstream can be changed */ + }; + + //routing_action: ADD_VIF and DEL_VIF + /** + * @brief Create a config_msg. + * @param type configuration type + * @param if_index index of the to change interface + * @param vif virtual index of the to change interface + */ + config_msg(config_action type,int if_index, int vif): + type(type), if_index(if_index), vif(vif) { + HC_LOG_TRACE(""); + } + + ~config_msg(){ + HC_LOG_TRACE(""); + } + + /** + * @brief Type of the config_msg. + */ + config_action type; + + /** + * @brief Action on a specific interface index. + */ + int if_index; + + /** + * @brief Action on a virtual interface index. + */ + int vif; +}; + +//message_type: DEBUG_MSG +/** + * @brief Message to collect debug information for the module @ref mod_proxy. + */ +struct debug_msg: public intrusive_message{ +public: + + /** + * @brief Level of detail to collect debug informaiton. + */ + enum lod{ //level of detail + LESS=0 /** low level of detail */, + NORMAL=1 /** normal level of detail */, + MORE=2 /** high level of detail */, + MORE_MORE=3 /** highest level of detail */ + }; + + /** + * @brief Create a debug message. + * @param details level of detail to collect debug information + * @param counter how many proxy instances have to collect debug information + * @param timeout_msec if a proxy instance dont response it will be ignored after a period of time + */ + debug_msg(lod details, int counter, int timeout_msec): level_of_detail(details), m_counter(counter), m_timeout_msec(timeout_msec){ + HC_LOG_TRACE(""); + HC_LOG_DEBUG("counter: " << m_counter); + } + + ~debug_msg(){ + HC_LOG_TRACE(""); + } + + /** + * @brief Add debug information as string. + */ + void add_debug_msg(std::string debug_input){ + HC_LOG_TRACE(""); + { + boost::lock_guard<boost::mutex> lock(m_global_lock); + m_str << debug_input << std::endl; + m_counter--; + } + cond_all_done.notify_all(); + } + + /** + * @brief Get true if all proxy instances response. + */ + bool all_done(){ + HC_LOG_TRACE(""); + boost::lock_guard<boost::mutex> lock(m_global_lock); + return m_counter <= 0; + } + + /** + * @brief Get all debug information. + */ + std::string get_debug_msg(){ + HC_LOG_TRACE(""); + boost::lock_guard<boost::mutex> lock(m_global_lock); + return m_str.str(); + } + + /** + * @brief Wait until all proxy instances has response or the timeout expires. + */ + void join_debug_msg(){ + boost::unique_lock<boost::mutex> lock(m_global_lock); + while(m_counter > 0){ + cond_all_done.timed_wait(lock,boost::posix_time::millisec(m_timeout_msec)); + } + m_counter = 0; + } + + /** + * @brief Get the level of detail. + */ + lod get_level_of_detail(){ + return level_of_detail; + } + +private: + lod level_of_detail; + std::stringstream m_str; + boost::mutex m_global_lock; + boost::condition_variable cond_all_done; + int m_counter; + int m_timeout_msec; + +}; + +#endif // MESSAGE_FORMAT_HPP +/** @} */ diff --git a/mcproxy/include/proxy/message_queue.hpp b/mcproxy/include/proxy/message_queue.hpp new file mode 100644 index 0000000000000000000000000000000000000000..580c369f20ab70fa90d2218e1970043b47d6a4f6 --- /dev/null +++ b/mcproxy/include/proxy/message_queue.hpp @@ -0,0 +1,140 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_communication Communication + * @brief The module Communication provide a communication with a synchronised + * job queue, messaging formats and wrapper to hide the details. + * @{ + */ + +#ifndef MESSAGE_QUEUE_HPP +#define MESSAGE_QUEUE_HPP + +#include <boost/thread/pthread/mutex.hpp> +#include <boost/thread/pthread/condition_variable.hpp> +#include <queue> +using namespace std; + +/** + * @brief Fixed sized synchronised job queue. + */ +template< typename T> +class message_queue{ +private: + message_queue(); + + queue<T> m_q; + unsigned int m_size; + + boost::mutex m_global_lock; + boost::condition_variable cond_full; + boost::condition_variable cond_empty; +public: + /** + * @brief Create a message_queue with a fixed size. + * @param size size of the message_queue. + */ + message_queue(int size); + + /** + * @brief Return true if the message queue is empty. + */ + bool is_empty(); + + /** + * @brief Return the current size of the message queue. + */ + unsigned int current_size(); + + /** + * @brief Return the set size. + */ + int max_size(); + + /** + * @brief add an element on tail and wait if full. + */ + void enqueue(T t); + + /** + * @brief get and el element on head and wait if empty. + */ + T dequeue(void); +}; + +template< typename T> +message_queue<T>::message_queue(int size){ + m_size = size; +} + +template< typename T> +bool message_queue<T>::is_empty(){ + boost::lock_guard<boost::mutex> lock(m_global_lock); + + return m_q.empty(); +} + + +template< typename T> +unsigned int message_queue<T>::current_size(){ + boost::lock_guard<boost::mutex> lock(m_global_lock); + + return m_q.size(); +} + +template< typename T> +int message_queue<T>::max_size(){ + return m_size; +} + +template< typename T> +void message_queue<T>::enqueue(T t){ + { + boost::unique_lock<boost::mutex> lock(m_global_lock); + while(m_q.size() >= m_size){ + cond_full.wait(lock); + } + + m_q.push(t); + } + cond_empty.notify_one(); +} + +template< typename T> +T message_queue<T>::dequeue(void){ + T t; + { + boost::unique_lock<boost::mutex> lock(m_global_lock); + while(m_q.size() == 0){ + cond_empty.wait(lock); + } + + t= m_q.front(); + m_q.pop(); + } + cond_full.notify_one(); + return t; +} + +#endif // MESSAGE_QUEUE_HPP +/** @} */ diff --git a/mcproxy/include/proxy/mld_receiver.hpp b/mcproxy/include/proxy/mld_receiver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d9e7c654847e4569e86e28b26e5cdf3090a03d6e --- /dev/null +++ b/mcproxy/include/proxy/mld_receiver.hpp @@ -0,0 +1,53 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_receiver Receiver + * @{ + */ + +#ifndef MLD_RECEIVER_HPP +#define MLD_RECEIVER_HPP + +#include "include/proxy/receiver.hpp" + +/** + * @brief Cache Miss message received form the Linux Kernel identified by this ip verion. + */ +#define MLD_RECEIVER_KERNEL_MSG 0 + +/** + * @brief Receive MLD messages. + */ +class mld_receiver : public receiver { +private: + int get_ctrl_min_size(); + int get_iov_min_size(); + void analyse_packet(struct msghdr* msg, int info_size); +public: + bool init(int addr_family, int version, mroute_socket* mrt_sock); + + mld_receiver(); +}; + +#endif // MLD_RECEIVER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/mld_sender.hpp b/mcproxy/include/proxy/mld_sender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b1aa7521d773003210c8d78e014d043319aa4ea0 --- /dev/null +++ b/mcproxy/include/proxy/mld_sender.hpp @@ -0,0 +1,77 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_sender Sender + * @{ + */ + +#ifndef MLD_SENDER_HPP +#define MLD_SENDER_HPP + +#include "include/proxy/sender.hpp" + +/** + * @brief This fields will fill by the Linux kernel. + */ +#define MC_MASSAGES_AUTO_FILL 0 + +/** + * @brief Size of the router alert option. + */ +#define MC_MASSAGES_IPV6_ROUTER_ALERT_OPT_SIZE 0 //RFC 2711 + +/** + * @brief Hob-by-Hob Option Header padding size. + */ +typedef u_int16_t pad2 ; //padding + +/** + * @brief Generates MLD messages. + */ +class mld_sender: public sender{ +private: + enum msg_type { //for intern type handling + GENERAL_QUERY, MC_ADDR_SPECIFIC_QUERY + }; + + bool choose_if(int if_index); + int get_msg_min_size(); + bool add_hbh_opt_header(); + bool create_mc_query(msg_type type, unsigned char* buf,const addr_storage* g_addr=NULL); + +public: + /** + * @brief Create an mld_sender. + */ + mld_sender(); + + bool init(int addr_family, int version); + + bool send_general_query(int if_index); + bool send_group_specific_query(int if_index, const addr_storage& g_addr); + bool send_report(int if_index, const addr_storage& g_addr); + bool send_leave(int if_index, const addr_storage& g_addr); +}; + +#endif // MLD_SENDER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/proxy.hpp b/mcproxy/include/proxy/proxy.hpp new file mode 100644 index 0000000000000000000000000000000000000000..95f8fa64c200e05cb957ab94e4378fb2bba71fea --- /dev/null +++ b/mcproxy/include/proxy/proxy.hpp @@ -0,0 +1,235 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_proxy Proxy + * @brief The module Proxy reads the configuration file on startup. + * It then configures and starts all other modules, acquire the mrt-flag + * on a socket for manipulating the multicast routing tables of the Linux kernel. + * @{ + */ + +#ifndef PROXY_HPP +#define PROXY_HPP + +#include "include/utils/addr_storage.hpp" +#include "include/utils/mroute_socket.hpp" +#include "include/utils/if_prop.hpp" +#include "include/proxy/proxy_instance.hpp" +#include "include/proxy/receiver.hpp" + +#include <map> +#include <vector> +#include <string> +using namespace std; + +//-------------------------------------------------- +/** + * @brief data structure to the interface index with the current virtual interface index. + * @param first if_index + * @param second vif + */ +typedef map<int, int> vif_map; + +/** + * @brief Pair for #vif_map. + * @param first if_index + * @param second vif + */ +typedef pair<int, int> vif_pair; + +//-------------------------------------------------- + +/** + * @brief Downstream vector for #up_down_map. + * @param vector of the downstream interfaces + */ +typedef vector<int> down_vector; +/** + * @brief Downstream vector for #up_down_map. + * @param vector of the downstream interfaces + */ +typedef vector<int> down_vector; +/** + * @brief data structure to mangage the upstream/downstream instances. + * @param first index of the upstream interface + * @param second index vector of the downstream interfaces + */ +typedef map<int, down_vector > up_down_map; //map<upstream, downstreams> + +/** + * @brief Pair for #up_down_map. + * @param first index of the upstream interface + * @param second vector of the downstream interfaces + */ +typedef pair<int, down_vector > up_down_pair; + +//-------------------------------------------------- + +/** + * @brief Lookup map to find a proxyinstance for a spezific interface index + * @param first interface index + * @param second proxyinstance index based on arbitrary vector + */ +typedef map<int,int > interface_map; //map< interface, proxyinstance_index> + +/** + * @brief Pair for #interface_map + * @param first interface index + * @param second proxyinstance index based on arbitrary vector + */ +typedef pair<int,int> interface_pair; + +//-------------------------------------------------- +/** + * @brief Maximum length of a line in the config file. + */ +#define PROXY_CONFIG_LINE_LENGTH 200 + +/** + * @brief If s proxy instance in the timeout time dont react to an debug message it will be ignored. + */ +#define PROXY_DEBUG_MSG_TIMEOUT 3000 //msec + +/** + * @brief Path to change the rp filter flag. + */ +#define PROXY_RP_FILTER_PATH "/proc/sys/net/ipv4/conf/" + +/** + * @brief Default path to find the config file. + */ +#define PROXY_DEFAULT_CONIG_PATH "mcproxy.conf" + +/** + * @brief Instanced the multicast proxy + */ +class proxy{ +private: + //control data + static bool m_running; + bool m_is_single_instance; + int m_verbose_lvl; + bool m_print_status; + + bool m_rest_rp_filter; + vector<string> m_restore_rp_filter_vector; //save interfaces wiche musst set to true after before terminating + + string m_config_path; + int m_addr_family; //AF_INET or AF_INET6 + int m_version; //for AF_INET (1,2,3) to use IGMPv1/2/3, for AF_INET6 (1,2) to use MLDv1/2 + + //-- + vector<proxy_instance*> m_proxy_instances; + interface_map m_interface_map; + up_down_map m_up_down_map; + vif_map m_vif_map; + + if_prop m_if_prop; + + int get_free_vif_number(); + + vector<int> all_if_to_list(); + + //############## + //##-- Init --## + //############## + + bool prozess_commandline_args(int arg_count, char* args[]); + void help_output(); + bool get_rp_filter(string interface); + bool set_rp_filter(string interface, bool to); + bool restore_rp_filter(); + + bool load_config(string path); //load the config file and add the interfaces to state_table + + + //check the state_table for valid input, interfaces can only used on time ==> true = check ok, false = double interfaces + bool check_double_used_if(const vector<int>* new_interfaces); + bool init_vif_map(); + bool init_if_prop(); + bool check_and_set_flags(vector<int>& interface_list); //check up and running flag, set multicast and allMulti flag + bool start_proxy_instances(); + + + //bool init_routing_table(); //add all interfaces from state_table to ip_mr_vif (phyint or tunnel) , allocate memory for m_vif + static void signal_handler(int sig); + void close(); + + +public: + /** + * @brief Set default values of the class members and add signal handlers for the signal SIGINT and SIGTERM. + */ + proxy(); + + /** + * @brief Release all resources and restore reverse path flags if changed. + */ + ~proxy(); + + /** + * @brief Return readable state table information. + */ + string get_state_table(); + + /** + * @brief initialize the proxy + * @param arg_count Number of passed parameter. + * @param args Passed parameter + * + * Usage: mcproxy [-h] [-f] [-d] [-s] [-v [-v]] [-c <configfile>] + * + * -h + * Display this help screen. + * -f + * Reset the reverse path filter flag, to accept data from + * foreign Subnets. + * -d + * Run in debug mode. Output all log messages on thread[X] + * file. + * -s + * Print proxy status information. + * -v + * Be verbose. Give twice to see even more messages + * -c + * To specify the configuration file. + * + * @return Return true on success. + */ + bool init(int arg_count, char* args[]); + + /** + * @brief Start the proxy. + * @return Return true on success. + */ + bool start(); + + /** + * @brief Stop the proxy. + */ + void stop(); +}; + +#endif // PROXY_HPP +/** @}*/ + diff --git a/mcproxy/include/proxy/proxy_instance.hpp b/mcproxy/include/proxy/proxy_instance.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6365e6110ae448a69aa47cd4e785a0fab9fdc782 --- /dev/null +++ b/mcproxy/include/proxy/proxy_instance.hpp @@ -0,0 +1,295 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_proxy_instance Proxy Instance + * @brief A Proxy Instance represents a full multicast proxy. Each + * instance has access to the modules Receiver, Routing, Sender and Timer. + * @{ + */ + +#ifndef PROXY_INSTANCE_HPP +#define PROXY_INSTANCE_HPP + +#include "include/utils/addr_storage.hpp" +#include "include/proxy/message_queue.hpp" +#include "include/proxy/message_format.hpp" +#include "include/proxy/worker.hpp" +#include "include/proxy/routing.hpp" +#include "include/proxy/sender.hpp" +#include "include/proxy/igmp_sender.hpp" +#include "include/proxy/mld_sender.hpp" +#include "include/proxy/receiver.hpp" +#include "include/proxy/timing.hpp" +#include "include/proxy/check_source.hpp" + +#include <vector> +using namespace std; + +/** + * @brief Maximum size of the job queue. + */ +#define PROXY_INSTANCE_MSG_QUEUE_SIZE 1000 + +/** + * @brief Saved groupmemberships will be deleted if there robustness counter is equal this define. + */ +#define PROXY_INSTANCE_DEL_IMMEDIATELY 0 + +/** + * @brief Data structure to save multicast sources/groups and there states. + */ +struct src_state { + /** + * @brief Represents the possible states of a multicast source/group + */ + enum state { + INIT /** unused state to create this structure */, + RUNNING /** group is joined */, + RESPONSE_STATE /** leave message received, send Group Specific Query and wait for a new join message */, + WAIT_FOR_DEL /** last interval before delete this group */, + UNUSED_SRC /** multicast data packet received by the kernel, but not used by kernel routing table */, + CACHED_SRC /** multicast source forwarded by the Linux kernel */ + }; + + /** + * @brief Convert the current state to a string. + */ + std::string state_type_to_string(){ + HC_LOG_TRACE(""); + switch(flag){ + case INIT: return "INIT"; + case RUNNING: return "RUNNING"; + case RESPONSE_STATE: return "RESPONSE_STATE"; + case WAIT_FOR_DEL: return "WAIT_FOR_DEL"; + case UNUSED_SRC: return "UNUSED_SRC"; + case CACHED_SRC: return "CACHED_SRC"; + default: return "ERROR"; + } + } + + /** + * @brief Create a new default #src_state. + */ + src_state(): robustness_counter(0), flag(INIT) {} + + /** + * @brief Create a new initialized #src_state. + */ + src_state(int counter, state flag): robustness_counter(counter), flag(flag) {} + + /** + * @brief Save a counter that is linked to the current state. + */ + int robustness_counter; + + /** + * @brief Save the current state. + */ + state flag; +}; + +//-------------------------------------------------- +/** + * @brief Data structure to save the interface index with the current virtual interface index. + * @param first if_index + * @param second vif + */ +typedef map<int, int> vif_map; + +/** + * @brief Pair for #vif_map. + * @param first if_index + * @param second vif + */ +typedef pair<int, int> vif_pair; + +//-------------------------------------------------- +/** + * @brief Data structure to save sources and there states. + * @param first source address + * @param second states of the source + */ +typedef map<addr_storage, struct src_state> src_state_map; + +/** + * @brief Pair for #src_state_map. + * @param first source address + * @param second states of the source + */ +typedef pair<addr_storage, struct src_state> src_state_pair; + +//-------------------------------------------------- +/** + * @brief Data structure for the upstream interface to save group memberships and there states + * @param first group address + * @param second map of sources and there states + */ +typedef map<addr_storage, src_state_map> upstream_src_state_map; + +/** + * @brief Pair for #upstream_src_state_map + * @param first group address + * @param second map of sources and there states + */ +typedef pair<addr_storage, src_state_map> upstream_src_state_pair; + +//-------------------------------------------------- +/** + * @brief Data structure to save a number of sources with there states and group membership states. + * @param first data structure to save sources and there states + * @param second group membership state + */ +typedef pair<src_state_map, struct src_state> src_group_state_pair; + +//-------------------------------------------------- +/** + * @brief Data structure to save group memberships with there states and exsists sources with there states + * @param first group address + * @param second Data structure to save a number of sources with there states and group membership states. + */ +typedef map<addr_storage, src_group_state_pair > g_state_map; + +/** + * @brief Pair for #g_state_map + * @param first group address + * @param second data structure to save a number of sources with there states and group membership states. + */ +typedef pair<addr_storage, src_group_state_pair > g_state_pair; + +//-------------------------------------------------- + +/** + * @brief Data structure to save downstream interfaces and there multicast group information + * @param first interface index of the downstream interface + * @param second multicast group information + */ +typedef map< int, g_state_map > state_table_map; + +/** + * @brief Pair for #state_table_map + * @param first interface index of the downstream interface + * @param second multicast group information + */ +typedef pair< int, g_state_map > state_tabel_pair; + +/** + * @brief Represent a multicast Proxy + */ +class proxy_instance: public worker{ +private: + bool m_is_single_instance; + int m_table_number; + mroute_socket m_mrt_sock; + + //upstream inforamtion + int m_upstream; //if_index + upstream_src_state_map m_upstream_state; + + //downstream inforamtion + state_table_map m_state_table; + + + vif_map m_vif_map; //if_index to vif + + int m_addr_family; //AF_INET or AF_INET6 + int m_version; //for AF_INET (1,2,3) to use IGMPv1/2/3, for AF_INET6 (1,2) to use MLDv1/2 + + check_source m_check_source; + + routing m_routing; + sender* m_sender; + receiver* m_receiver; + timing* m_timing; + + //init + bool init_mrt_socket(); + bool init_receiver(); + bool init_sender(); + + + void worker_thread(); + + // registrate/unregistrate to reciever, router, and to the network + void registrate_if(int if_index); + void unregistrate_if(int if_index); + + //##-- igmp automat --## + //send general query to all downstream + bool send_gq_to_all(); + + //processed joins and leaves + void handle_igmp(struct receiver_msg* r); + + //processed clock events + void handle_clock(struct clock_msg* c); + + //create debug output + void handle_debug_msg(struct debug_msg* db); + + //add and del interfaces + void handle_config(struct config_msg* c); + + //need for aggregate states + bool is_group_joined(int without_if_index, const addr_storage& g_addr); + + //handel multicast routes + //need for CACHE_MISS, General Query + bool split_traffic(int if_index, const addr_storage& g_addr, const addr_storage& src_addr); + bool del_route(int if_index, const addr_storage& g_addr, const addr_storage& src_addr); + + //need for join, del group + void refresh_all_traffic(int if_index, const addr_storage& g_addr); + + //fill vif_list with downstream vifs who has the same g_addr + //without_if_index will be ignored + void add_all_group_vifs_to_list(std::list<int>* vif_list, int without_if_index, addr_storage g_addr); + + + void close(); +public: + /** + * @brief Set default values of the class members. + */ + proxy_instance(); + + /** + * @brief Release all resources. + */ + ~proxy_instance(); + + + /** + * @brief initialise the proxy + * @param addr_family AF_INET or AF_INET6 + * @param version used group membership version + * @param upstream_index interface index of the upstream + * @param upstream_vif virtual interface index of the upstream + * @param downstream_index interface index of the downstream + * @param downstram_vif virtual interface index of the downstream + * @param receiver* pointer to the modul @ref mod_receiver + */ + bool init(int addr_family, int version, int upstream_index, int upstream_vif, int downstream_index, int downstram_vif, bool single_instance); +}; + +#endif // PROXY_INSTANCE_HPP +/** @}*/ diff --git a/mcproxy/include/proxy/receiver.hpp b/mcproxy/include/proxy/receiver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7d6dc06b5d4c9a0ddaedb7c44ac3d381d3a50143 --- /dev/null +++ b/mcproxy/include/proxy/receiver.hpp @@ -0,0 +1,215 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_receiver Receiver + * @brief The module Receiver uses the socket with the mrt-flag to receive Membership Reports + * and Cache Miss messages. Cache Miss messages are sent from the Linux kernel in order to + * inform proxies about new multicast sources. + * @{ + */ + +#ifndef RECEIVER_HPP +#define RECEIVER_HPP + +#include "include/proxy/worker.hpp" +#include "include/utils/mroute_socket.hpp" +#include "include/utils/addr_storage.hpp" +#include "include/utils/if_prop.hpp" + +#include <map> +#include "boost/thread.hpp" +#include "boost/thread/mutex.hpp" + +class proxy_instance; + +/** + * @brief Receive timout set to have not a blocking receive funktion. + */ +#define RECEIVER_RECV_TIMEOUT 100 //msec + +//-------------------------------------------------- +// if_index, proxy_instance +/** + * @brief Data structure to save the interface index with the incidental Proxy Instance. + * @param first interface index + * @param second pointer to the incidental Proxy Instance + */ +typedef std::map<int, proxy_instance*> if_poxy_instance_map; + +/** + * @brief Pair for #if_poxy_instance_map. + * @param first interface index + * @param second pointer to the incidental Proxy Instance + */ +typedef std::pair<int, proxy_instance*> if_proxy_instance_pair; + +//-------------------------------------------------- +// vif number, if_index !!! reversed !!! +/** + * @brief Data structure to save the virtual interface index with the interface index with the current. + * @param first vif + * @param second if_index + * @attention This data structure is reversed to the over vif_maps!! + */ +typedef map<int, int> vif_map; + +/** + * @brief Pair for #vif_map. + * @param first vif + * @param second if_index + * @attention This data structure is reversed to the over vif_maps!! + */ +typedef pair<int, int> vif_pair; + +/** + * @brief Abstract basic receiver class. + */ +class receiver{ +private: + bool m_running; + boost::thread* m_worker_thread; + static void worker_thread(void* arg); + + bool init_if_prop(); + + boost::mutex m_data_lock; + vif_map m_vif_map; + + void close(); +protected: + /** + * @brief Save the interface index with the incidental Proxy Instance. + */ + if_poxy_instance_map m_if_proxy_map; + + /** + * @brief Collect interface properties. Used to generate multicast messages. + */ + if_prop m_if_property; + + /** + * @brief Abstracted multicast socket to receive multicast messages. + */ + mroute_socket* m_mrt_sock; + + /** + * @brief Used IP version (AF_INET or AF_INET6). + */ + int m_addr_family; + + /** + * @brief Used group membership version. + */ + int m_version; + + /** + * @brief Get the size for the control buffer for recvmsg(). + */ + virtual int get_ctrl_min_size()=0; + + /** + * @brief Get the size for the iov vector for recvmsg(). + */ + virtual int get_iov_min_size()=0; + + /** + * @brief Analyze the received packet and send a message to the relevant proxy instance. + * @param msg received message + * @param info_size received information size + */ + virtual void analyse_packet(struct msghdr* msg, int info_size)=0; + + //return prody instance pointer and on error NULL + /** + * @brief Get the proxy instance pointer to the interface index. Search in #m_if_proxy_map. + * @param if_index interface index + * @return pointer of the proxy instance or NULL if not found + */ + proxy_instance* get_proxy_instance(int if_index); + + //return on error 0 + /** + * @brief Get the interface index to a virtual interface index. Search in a private map #vif_map + * @param vif virutal interface index + * @return interface index or 0 if not found + */ + int get_if_index(int vif); +public: + /** + * @brief Create a receiver. + */ + receiver(); + + /** + * @brief Release all resources. + */ + ~receiver(); + + /** + * @brief Initialize the receiver. + * @param addr_family used IP version (AF_INET or AF_INET6) + * @param version used group membership version + * @param mrt_sock need the multicast routing socket with set mrt-flag + * @return Return true on success. + */ + virtual bool init(int addr_family, int version, mroute_socket* mrt_sock); + + /** + * @brief Register an interface at the receiver. + * @param if_index interface index of the registered interface + * @param vif virtual interface indxe of the inteface + * @param proxy_instance* who register the interface + */ + void registrate_interface(int if_index, int vif, proxy_instance* p); + + /** + * @brief Delete an registerd interface + * @param if_index interface index of the interface + * @param vif virtual interface index of the interface + */ + void del_interface(int if_index, int vif); + + /** + * @brief Check whether the receiver is running. + */ + bool is_running(); + + /** + * @brief Start the receiver. + */ + void start(); + + /** + * @brief Stop the receiver, but dont wait for stopped. + */ + void stop(); + + /** + * @brief Blocked until receiver stopped. + */ + void join(); +}; + + +#endif // RECEIVER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/routing.hpp b/mcproxy/include/proxy/routing.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6cef670b8173313e1387e72ef1da4ba669dd61bc --- /dev/null +++ b/mcproxy/include/proxy/routing.hpp @@ -0,0 +1,90 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_routing Routing + * @brief The module Routing set/delete virtual interfaces and multicast forwarding rules. + * @{ + */ + +#ifndef ROUTING_HPP +#define ROUTING_HPP + +#include "include/utils/mroute_socket.hpp" +#include "include/utils/if_prop.hpp" + +#include <map> +#include <list> + +/** + * @brief Set and delete virtual interfaces and forwarding rules in the Linux kernel. + */ +class routing{ +private: + bool m_is_single_instance; + int m_table_number; + int m_addr_family; //AF_INET or AF_INET6 + int m_version; //for AF_INET (1,2,3) to use IGMPv1/2/3, for AF_INET6 (1,2) to use MLDv1/2 + + mroute_socket* m_mrt_sock; + if_prop m_if_prop; //return interface properties + + //init + bool init_if_prop(); +public: + + /** + * @brief Add a virtual interface to the linux kernel table. + * @return Return true on success. + */ + bool add_vif(int if_index, int vif); + + /** + * @brief Delete a virtual interface from the linux kernel table. + * @return Return true on success. + */ + bool del_vif(int if_index, int vif); + + /** + * @brief Add a multicast route to the linux kernel table. + * @return Return true on success. + */ + bool add_route(int input_vif, const addr_storage& g_addr, const addr_storage& src_addr, const std::list<int>& output_vif); + + /** + * @brief Delete a multicast route from the linux kernel table. + * @return Return true on success. + */ + bool del_route(int vif, const addr_storage& g_addr, const addr_storage& src_addr); + + /** + * @brief Initialize the Routing module. + * @param addr_family AF_INET or AF_INET6 + * @param version used group membership version + * @return Return true on success. + */ + bool init(int addr_family, int version, mroute_socket* mrt_sock, bool single_instance, int table_number); + +}; + +#endif // ROUTING_HPP +/** @} */ diff --git a/mcproxy/include/proxy/sender.hpp b/mcproxy/include/proxy/sender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0ca51ecd144fba81fa4fd00f9943aa5b4dd9be2f --- /dev/null +++ b/mcproxy/include/proxy/sender.hpp @@ -0,0 +1,116 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_sender Sender + * @brief The module Sender generates and sends Membership Queries to the downstreams and Membership Reports to the upstreams. + * @{ + */ + +#ifndef SENDER_HPP +#define SENDER_HPP + +#include "include/utils/mroute_socket.hpp" +#include "include/utils/addr_storage.hpp" +#include "include/utils/if_prop.hpp" + +/** + * @brief Abstract basic sender class. + */ +class sender{ +private: +protected: + /** + * @brief Used IP version (AF_INET or AF_INET6). + */ + int m_addr_family; //AF_INET or AF_INET6 + + /** + * @brief Used group membership version. + */ + int m_version; //for AF_INET (1,2,3) to use IGMPv1/2/3, for AF_INET6 (1,2) to use MLDv1/2 + + /** + * @brief Abstracted multicast socket, that use raw-socket to send the messages. + */ + mroute_socket m_sock; + + /** + * @brief Collect interface properties. Used to generate multicast messages. + */ + if_prop m_if_prop; //return interface properties + + /** + * @brief initialize the interface properties class. + */ + bool init_if_prop(); +public: + + /** + * @brief Create a sender. + */ + sender(); + + /** + * @brief initialise the sender + * @param addr_family used IP version (AF_INET or AF_INET6) + * @param version used group membership version + * @return Return true on success. + */ + virtual bool init(int addr_family, int version); + + /** + * @brief Send a General Query to a specific interface. + * @param if_index used interface + * @return Return true on success. + */ + virtual bool send_general_query(int if_index)=0; + + /** + * @brief Send a Group Specific Query to a multicast group and a specific interface. + * @param if_index used interface + * @param g_addr used multicast group + * @return Return true on success. + */ + virtual bool send_group_specific_query(int if_index, const addr_storage& g_addr)=0; + + /** + * @brief Send a Membership Report to a multicast group and a specific interface. + * @param if_index used interface + * @param g_addr used multicast group + * @return Return true on success. + */ + virtual bool send_report(int if_index, const addr_storage& g_addr)=0; + + /** + * @brief Send a leave Message to a multicast group and a specific interface. + * @param if_index used interface + * @param g_addr used multicast group + * @return Return true on success. + */ + virtual bool send_leave(int if_index, const addr_storage& g_addr)=0; + +}; + + +#endif // SENDER_HPP +/** @} */ diff --git a/mcproxy/include/proxy/timing.hpp b/mcproxy/include/proxy/timing.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ab639b2cce1c30843fa614dfab06a702e4bb7971 --- /dev/null +++ b/mcproxy/include/proxy/timing.hpp @@ -0,0 +1,113 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @defgroup mod_timer Timer + * @brief The module Timer organizes the temporal behavior of the Proxy-Instances. + * @{ + */ + +#ifndef TIME_HPP +#define TIME_HPP + +#include "include/proxy/message_format.hpp" + +#include <list> +#include <boost/thread.hpp> + +/** + * @brief Poll interval, to look for an expires reminder. + */ +#define TIME_POLL_INTERVAL 500 //msec + +class proxy_instance; + +/** + * @brief Organizes reminder. + */ +class timing{ +private: + struct timehandling { + timehandling(struct timeval time, proxy_instance* pr_i, proxy_msg pr_msg); + struct timeval m_time; + proxy_instance* m_pr_i; + proxy_msg m_pr_msg; + }; + + bool m_running; + boost::thread* m_worker_thread; + static void worker_thread(timing* t); + + boost::mutex m_global_lock; + std::list<struct timehandling> m_time_list; + + //GOF singleton + timing(); + timing(const timing&); + timing& operator=(const timing&); + ~timing(); +public: + /** + * @brief Get an instance of the Routing module (GOF singleton). + */ + static timing* getInstance(); + + /** + * @brief Add a new reminder with an predefined time. + * @param msec predefined time in millisecond + * @param proxy_instance* pointer to the owner of the reminder + * @param pr_msg message of the reminder + * + */ + void add_time(int msec, proxy_instance* pr_i, proxy_msg& pr_msg); + + /** + * @brief Delete all reminder from a specific proxy instance. + * @param proxy_instance* pointer to the specific proxy instance + */ + void stop_all_time(proxy_instance* pr_i); + + /** + * @brief Start the module Timer. + */ + void start(); + + /** + * @brief Stop the module Timer, but dont wait for stopped. + */ + void stop(); + + /** + * @brief Blocked until module Timer stopped. + */ + void join(); + + /** + * @brief Test the functionality of the module Timer. + */ + static void test_timing(); +}; + + + +#endif // TIME_HPP +/** @} */ diff --git a/mcproxy/include/proxy/worker.hpp b/mcproxy/include/proxy/worker.hpp new file mode 100644 index 0000000000000000000000000000000000000000..571eac0c609011f47d9535b88ca986d17990d251 --- /dev/null +++ b/mcproxy/include/proxy/worker.hpp @@ -0,0 +1,94 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +/** + * @addtogroup mod_communication Communication + * @{ + */ + +#ifndef WORKER_HPP +#define WORKER_HPP + +#include "include/proxy/message_queue.hpp" +#include "include/proxy/message_format.hpp" +#include "boost/thread.hpp" + +/** + * @brief Wraps the job queue to a basic worker like an simple actor pattern. + */ +class worker{ +private: + worker(); + boost::thread* m_worker_thread; + + static void worker_thread_starter(worker* w); + + void close(); +protected: + + /** + * @brief Worker thread to process the jobs. + */ + virtual void worker_thread()=0; + + /** + * @brief The threads runs as long as m_running is true. + */ + bool m_running; + + /** + * @brief Job queue to process proxy_msg. + */ + message_queue<proxy_msg> m_job_queue; +public: + + /** + * @brief Create a worker with a maximum job queue size. + * @param max_msg maximum size of the job queue + */ + worker(int max_msg); + + ~worker(); + + /** + * @brief Add a message to the job queue. + */ + void add_msg(proxy_msg& msg); + + /** + * @brief Start the worker. + */ + void start(); + + /** + * @brief Check whether the receiver is running. + */ + bool is_running(); + + /** + * @brief Blocked until the worker thread stopped. + */ + void join(); +}; + +#endif // WORKER_HPP +/** @} */ diff --git a/mcproxy/include/utils/addr_storage.hpp b/mcproxy/include/utils/addr_storage.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3896c7717b47a4c183be026d5f80e9f2bc391745 --- /dev/null +++ b/mcproxy/include/utils/addr_storage.hpp @@ -0,0 +1,239 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#ifndef ADDR_STORAGE_HPP +#define ADDR_STORAGE_HPP + +#include <iostream> +#include <sys/socket.h> +#include <string> +#include <netinet/in.h> + +#include <iostream> +using namespace std; + +/** + * @brief Wrapper for ip an IP address storage. + */ +class addr_storage +{ +private: + struct sockaddr_storage m_addr; + inline void clean(); + inline int get_addr_len(int addr_family) const; +public: + /** + * @brief Create a zero addr_storage. + */ + addr_storage(); + + /** + * @brief Create a zero address specific storage. + */ + addr_storage(int addr_family); + + /** + * @brief Create an addr_storage based on a clear text ip. + */ + addr_storage(const std::string& addr); + + /** + * @brief Create an addr_storage based on the struct sockaddr_storage. + */ + addr_storage(const struct sockaddr_storage& addr); + + /** + * @brief Copy constructor + */ + addr_storage(const addr_storage& addr); + + /** + * @brief Create an addr_storage based on struct in_add. + */ + addr_storage(const struct in_addr& addr); + + /** + * @brief Create an addr_storage based on struct in6_addr. + */ + addr_storage(const struct in6_addr& addr); + + /** + * @brief Create an addr_storage based on struct sockaddr. + */ + addr_storage(const struct sockaddr& addr); + + /** + * @brief Create an addr_storage based on struct sockaddr_in. + */ + addr_storage(const struct sockaddr_in& addr); + + /** + * @brief Create an addr_storage based on struct sockaddr_in6. + */ + addr_storage(const struct sockaddr_in6& addr); + +//----------------------------------------------------------- + + /** + * @brief default copy operator + */ + addr_storage& operator=(const addr_storage& s); + + /** + * @brief copy operator struct sockaddr_storage to class addr_storage + */ + addr_storage& operator=(const struct sockaddr_storage& s); + + /** + * @brief copy operator string to class addr_storage + */ + addr_storage& operator=(const std::string& s); + + /** + * @brief copy operator struct in_addr to class addr_storage + */ + addr_storage& operator=(const struct in_addr& s); + + /** + * @brief copy operator struct in6_addr to class addr_storage + */ + addr_storage& operator=(const struct in6_addr& s); + + /** + * @brief copy operator struct sockaddr to class addr_storage + */ + addr_storage& operator=(const struct sockaddr& s); + + /** + * @brief copy operator struct sockaddr_in to class addr_storage + */ + addr_storage& operator=(const struct sockaddr_in& s); + + /** + * @brief copy operator struct sockaddr_in6 to class addr_storage + */ + addr_storage& operator=(const struct sockaddr_in6& s); + + //----------------------------------------------------------- + + /** + * @brief compare two addresses if one of this addresses unknown the function returns false + */ + bool operator==(const addr_storage& addr) const; + + /** + * @brief disjunction to operator== + */ + bool operator!=(addr_storage& addr) const; + + /** + * @brief lower then operator (only for IPv4 implemented) + */ + friend bool operator< (const addr_storage& addr1, const addr_storage& addr2); + + /** + * @brief mask an addr with a netmask + */ + addr_storage& mask(const addr_storage& s); + + //----------------------------------------------------------- + + /** + * @brief return current address family AF_INET or AF_INET6 or AF_UNSPEC + */ + int get_addr_family() const; + + /** + * @brief return current port or return 0 if no port exist + */ + int get_port() const; + + /** + * @brief return current port or return 0 if no port exist + */ + addr_storage& set_port(int port); + + /** + * @brief return current port or return 0 if no port exist + */ + addr_storage& set_port(const string& port); + + /** + * @brief return length of the address in byte or return 0 if no address family is available + */ + int get_addr_len() const; + + /** + * @brief return a sockaddr_storage struct + */ + const struct sockaddr_storage& get_sockaddr_storage() const; + + /** + * @brief return a in_addr struct + */ + const struct in_addr& get_in_addr() const; + + /** + * @brief return a in6_addr struct + */ + const struct in6_addr& get_in6_addr() const; + + /** + * @brief return a sockaddr struct + */ + const struct sockaddr& get_sockaddr() const; + + /** + * @brief return a sockaddr_in struct + */ + const struct sockaddr_in& get_sockaddr_in() const; + + /** + * @brief return a sockaddr_in6 struct + */ + const struct sockaddr_in6& get_sockaddr_in6() const; + + //----------------------------------------------------------- + + /** + * @brief return current address as string + */ + std::string to_string() const; + + /** + * @brief cout output operator + */ + friend std::ostream& operator <<(std::ostream& s, const addr_storage a); + + //----------------------------------------------------------- + + /** + * @brief simple test output + */ + static void test_addr_storage_old(); + static void test_addr_storage(); +}; + + +#endif // ADDR_STORAGE_HPP + diff --git a/mcproxy/include/utils/if_prop.hpp b/mcproxy/include/utils/if_prop.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d56fc1ee309b35a048adf7ada8e83c196e78847b --- /dev/null +++ b/mcproxy/include/utils/if_prop.hpp @@ -0,0 +1,114 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#ifndef IF_PROP_NEW_HPP +#define IF_PROP_NEW_HPP + +#include <list> +#include <map> +#include <ifaddrs.h> +using namespace std; + +//typedef pair<struct ifaddrs*, list<struct ifaddrs*> > ipv4_6_pair; + +struct ipv4_6_pair{ + + + const struct ifaddrs* ip4_addr; + list<const struct ifaddrs*> ip6_addr; + + ipv4_6_pair(const struct ifaddrs* ip4_addr, list<const struct ifaddrs*> ip6_addr){ + this->ip4_addr = ip4_addr; + this->ip6_addr = ip6_addr; + } + +}; + +//map<if_name, <ipv4 struct, ipv6 struct list> > +typedef map<string, ipv4_6_pair > if_prop_map; +typedef pair<string, ipv4_6_pair >if_prop_pair; + +/** + * @brief Prepare and organized the interface properties to a map data structure. + */ +class if_prop{ +private: + if_prop_map m_if_map; + struct ifaddrs* m_if_addrs; +public: + /** + * @brief Create the class if_prop. + */ + if_prop(); + + /** + * @brief Return the whole data structure. + */ + const if_prop_map * get_if_props() const; + + /** + * @brief Refresh all information of all interfaces. + * @return Return true on success. + */ + bool refresh_network_interfaces(); + + /** + * @brief Get the ipv4 interface properties for a specific interface name. + */ + const struct ifaddrs* get_ip4_if(const string &if_name) const; + + /** + * @brief Get the ipv6 interface properties for a specific interface name. + */ + const list<const struct ifaddrs* >* get_ip6_if(const string &if_name) const; + + /** + * @brief Print all available network interface information. + */ + void print_if_info() const; + + /** + * @brief Print interface information for a specific interface. + * @param if_p interface properties for a specific inerface. + */ + void print_if_addr(const struct ifaddrs* if_p) const; + + /** + * @brief Release all allocated resources. + */ + ~if_prop(); + + /** + * @brief Check for a valid data structure. + */ + bool is_getaddrs_valid() const{ + return m_if_addrs > 0; + } + + /** + * @brief Test the class if_prop. + */ + static void test_if_prop(); +}; + +#endif // IF_PROP_NEW_HPP diff --git a/mcproxy/include/utils/mc_socket.hpp b/mcproxy/include/utils/mc_socket.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5698c66a789f8bc62eb1d0268f484b416d7c491c --- /dev/null +++ b/mcproxy/include/utils/mc_socket.hpp @@ -0,0 +1,243 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#ifndef MCSOCKET_H_ +#define MCSOCKET_H_ + +#include "include/utils/addr_storage.hpp" +#include <time.h> +#include <string> +using namespace std; + +///@author Sebastian Woelke +///@brief socket for multicast applications + +/* + * ##--Multicast Addresses--## + * 224.0.0.0 - 224.255.255.255 ==> für Routingprotokolle reserviert + * 239.0.0.0 - 239.255.255.255 ==> für scoping reserviert + * 225.x.x.x bis 238.x.x.x ==> frei verfügbar + */ + +//IPv4 addresses that are reserved for IP multicasting (http://en.wikipedia.org/wiki/Multicast_address) +#define IPV4_ALL_HOST_ADDR "224.0.0.1" //The All Hosts multicast group that contains all systems on the same network segment +#define IPV4_ALL_IGMP_ROUTERS_ADDR "224.0.0.2" //The All Routers multicast group that contains all routers on the same network segment +#define IPV4_ALL_SPF_ROUTER_ADDR "224.0.0.5" //The Open Shortest Path First (OSPF) AllSPFRouters address. Used to send Hello packets to all OSPF routers on a network segment +#define IPV4_ALL_D_Routers_ADDR "224.0.0.6" //The OSPF AllDRouters address. Used to send OSPF routing information to OSPF designated routers on a network segment +#define IPV4_RIPV2_ADDR "224.0.0.9" //The RIP version 2 group address. Used to send routing information using the RIP protocol to all RIP v2-aware routers on a network segment +#define IPV4_EIGRP_ADDR "224.0.0.10" //EIGRP group address. Used to send EIGRP routing information to all EIGRP routers on a network segment +#define IPV4_PIMv2_ADDR "224.0.0.13" //PIM Version 2 (Protocol Independent Multicast) +#define IPV4_VRR_ADDR "224.0.0.18" //Virtual Router Redundancy Protocol +#define IPV4_IS_IS_OVER_IP_19_ADDR "224.0.0.19" //IS-IS over IP +#define IPV4_IS_IS_OVER_IP_20_ADDR "224.0.0.20" //IS-IS over IP +#define IPV4_IS_IS_OVER_IP_21_ADDR "224.0.0.21" //IS-IS over IP +#define IPV4_IGMPV3_ADDR "224.0.0.22" //IGMP Version 3 (Internet Group Management Protocol) +#define IPV4_HOT_STANDBY_ROUTERV2_ADDR "224.0.0.102" //Hot Standby Router Protocol Version 2 +#define IPV4_MCAST_DNS_ADDR "224.0.0.251" //Multicast DNS address +#define IPV4_LINK_LOCAL_MCAST_NAME_RES_ADDR "224.0.0.252" //Link-local Multicast Name Resolution address +#define IPV4_NTP_ADDR "224.0.1.1" //Network Time Protocol address +#define IPV4_CISCO_AUTO_RP_ANNOUNCE_ADDR "224.0.1.39" //Cisco Auto-RP-Announce address +#define IPV4_CISCO_AUTO_RP_DISCOVERY_ADDR "224.0.1.40" //Cisco Auto-RP-Discovery address +#define IPV4_H_323_GETEKEEPER_DISC_ADDR "224.0.1.41" //H.323 Gatekeeper discovery address + +//IPv6 addresses that are reserved for IP multicasting (http://www.iana.org/assignments/ipv6-multicast-addresses/) +#define IPV6_ALL_NODES_ADDR "ff02::1" //All nodes on the local network segment (equivalent to the IPv4 link-local broadcast address, 169.254.255.255) +#define IPV6_ALL_NODE_LOCAL_ROUTER "ff01::2" //RFC 4291 ==> All Routers Addresses +#define IPV6_ALL_LINK_LOCAL_ROUTER "ff02::2" //All routers on the link local network segment +#define IPV6_ALL_SITE_LOCAL_ROUTER "ff05::2" //All routers on the site local network segment [RFC4291] +#define IPV6_ALL_MLDv2_CAPABLE_ROUTERS "ff02::16" //All MLDv2-capable routers [RFC3810] +#define IPV6_ALL_PIM_ROUTERS "ff02::d" //All PIM Routers + +string ipAddrResolver(string ipAddr); + +typedef void (*free_fun) (struct addrinfo*); + +template< typename F, typename V> +struct save_free{ +private: + F m_fun; + V m_val; +public: + save_free(F fun, V val): m_fun(fun), m_val(val){ + } + + ~save_free(){ + (*m_fun)(m_val); + } +}; + +//Multicast Socket +/** + * @brief Wrapper for a multicast socket. + */ +class mc_socket { +protected: + /** + * @brief Used socket descriptor + */ + int m_sock; + + /** + * @brief Used IP version (AF_INET or AF_INET6). + */ + int m_addrFamily; + + /** + * @brief Save whether the socket is created not in this class. + */ + bool m_own_socket; + + /** + * @brief Mc_socket mustnt be copied because its contain an unique socket. + */ + mc_socket(const mc_socket ©); +public: + /** + * @brief Create a multicast socket. + */ + mc_socket(); + + /** + * @brief Close the internal datagram socket. + */ + virtual ~mc_socket(); + + /** + * @brief Create an IPv4 datagram socket. + */ + virtual bool create_udp_ipv4_socket(); + + /** + * @brief Create IPv6 datagram socket. + */ + virtual bool create_udp_ipv6_socket(); + + /** + * @brief Set an extern socket. + * @param socket socket descriptor + * @param addr_family used address family (AF_INET or AF_INET6) + * @return Return true on success. + */ + bool set_own_socket(int socket, int addr_family); + + /** + * @return Get the address family (AF_INET | AF_INET6). + */ + int get_addr_family(); + + /** + * @brief Bind IPv4 or IPv6 socket to a specific port. + * @return Return true on success. + */ + bool bind_udp_socket(int port); + + /** + * @brief Enable or disable multicast loopback. + * @return Return true on success. + */ + bool set_loop_back(bool enable); + + /** + * @brief Send a string to a specific ip address and to a specific port. + * @param addr destination address of packet in clear text + * @param port destination port + * @param data message to send + * @return Return true on success. + */ + bool send_packet(const char* addr, int port, string data); + + /** + * @brief Send data to a specific ip address and to a specific port. + * @param addr destination address of the packet in clear text + * @param port destination port + * @param data data to send + * @param data_size size of the data + * @return Return true on success. + */ + bool send_packet(const char* addr, int port, const unsigned char* data, unsigned int data_size); + + /** + * @brief Receive a datagram + * @param[out] buf read N bytes into buf from socket + * @param[in] sizeOfBuf size of buf + * @param[out] sizeOfInfo filled with the effective packet length less then sizeOfBuf + * @return Return true on success. + */ + bool receive_packet(unsigned char* buf, int sizeOfBuf, int &sizeOfInfo); + + /** + * @brief Receive a message with the kernel function recvmsg(). + * @param[out] msg received message + * @param[out] sizeOfInfo size of the received message + * @return Return true on success. + */ + bool receive_msg(struct msghdr* msg, int &sizeOfInfo); + + /** + * @brief Set a receive timeout. + * @param msec timeout in millisecond + * @return Return true on success. + */ + bool set_receive_timeout(long msec); + + /** + * @brief Choose a specific network interface + * @return Return true on success. + */ + bool choose_if(int if_index); + + /** + * @brief set the ttl + * @return Return true on success. + */ + bool set_ttl(int ttl); + + /** + * @brief Join a multicast group on a specific network interface. + * @param addr group to join in clear text + * @return Return true on success. + */ + bool join_group(const char* addr, int if_index); + + /** + * @brief Leave a multicast group on a specific network interface. + * @param addr group to join in clear text + * @return Return true on success. + */ + bool leave_group(const char* addr, int if_index); + + /** + * @brief Check for valid socket descriptor. + */ + bool is_udp_valid() { + return m_sock > 0; + } + + /** + * @brief Test the class mc_socket. + */ + static void test_join_leave_send(); + +}; + +#endif /* MCSOCKET_H_ */ diff --git a/mcproxy/include/utils/mc_timers_values.hpp b/mcproxy/include/utils/mc_timers_values.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1506d5a11fa9eded7a67aa6501520b15bea7fa1a --- /dev/null +++ b/mcproxy/include/utils/mc_timers_values.hpp @@ -0,0 +1,49 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#ifndef MC_TIMERS_VALUES_HPP +#define MC_TIMERS_VALUES_HPP + +//-- igmp and mld -- +#define MC_TV_ROBUSTNESS_VARIABLE 2//2 +#define MC_TV_QUERY_INTERVAL 30//125 //sec +#define MC_TV_QUERY_RESPONSE_INTERVAL 1//10 //sec +#define MC_TV_OTHER_QUERIER_PRESENT_INTERVAL (MC_TV_ROBUSTNESS_VARIABLE*MC_TV_QUERY_RESPONSE_INTERVAL) //sec +#define MC_TV_STARTUP_QUERY_INTERVAL (MC_TV_QUERY_INTERVAL/4) +#define MC_TV_STARTUP_QUERY_COUNT MC_TV_ROBUSTNESS_VARIABLE +#define MC_TV_UNSOLICITED_REPORT_INTERVAL 10 //sec + +//-- igmp -- +#define MC_TV_GROUP_MEMBERSHIP_INTERVAL (MC_TV_ROBUSTNESS_VARIABLE*MC_TV_QUERY_INTERVAL + MC_TV_QUERY_RESPONSE_INTERVAL) //sec +#define MC_TV_LAST_MEMBER_QUERY_INTEVAL 1 //sec +#define MC_TV_LAST_MEMBER_QUERY_COUNT MC_TV_ROBUSTNESS_VARIABLE +#define MC_TV_VERION_1_ROUTER_PRESNET_TIMEOUT 400 //sec +#define MC_TV_MAX_RESPONSE_TIME_UNIT 10 //1/10 sec + +//-- mld -- +#define MC_TV_MC_LISTENER_INTERVAL MC_TV_GROUP_MEMBERSHIP_INTERVAL +#define MC_TV_LAST_LISTENER_QUERY_INTERVAL MC_TV_LAST_MEMBER_QUERY_INTEVAL +#define MC_TV_LAST_LISTENER_QUERY_COUNT MC_TV_LAST_MEMBER_QUERY_COUNT +#define MC_TV_MAX_RESPONSE_DELAY_UNIT 1000 //1/1000 sec ==> 1 msec + +#endif // MC_TIMERS_VALUES_HPP diff --git a/mcproxy/include/utils/mroute_socket.hpp b/mcproxy/include/utils/mroute_socket.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d80d077f74400175a1b17ead40a286ddddd2482d --- /dev/null +++ b/mcproxy/include/utils/mroute_socket.hpp @@ -0,0 +1,247 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#ifndef MROUTE_SOCKET_HPP +#define MROUTE_SOCKET_HPP + +#include "include/utils/mc_socket.hpp" +#include <sys/types.h> + +#define MROUTE_RATE_LIMIT_ENDLESS 0 +#define MROUTE_TTL_THRESHOLD 1 +#define MROUTE_DEFAULT_TTL 1 + +#define ADD_SIGNED_NUM_U16(r,a) (r)+= (a); (r)+= ((r)>>16) + +/** + * @brief Wrapper for a multicast socket with additional functions to manipulate Linux kernel tables. + */ +class mroute_socket: public mc_socket +{ +private: + mroute_socket(const mroute_socket ©); + + //not used + bool create_udp_ipv4_socket(){ + return false; + } + + //not used + bool create_udp_ipv6_socket(){ + return false; + } + +public: + + /** + * @brief Create a mroute_socket. + */ + mroute_socket(); + + /** + * @brief Close raw socket. + */ + virtual ~mroute_socket(); + + /** + * @brief Create IPv4 raw socket. + * @return Return true on success. + */ + bool create_raw_ipv4_socket(); + + /** + * @brief Create IPv6 raw socket (RFC 3542 Section 3). + * @return Return true on success. + */ + bool create_raw_ipv6_socket(); + + /** + * @brief Create IPv6 raw socket (RFC 3542 Section 3). + * @return Return true on success. + */ + bool set_kernel_table(int table); + + /** + * @brief The IPv4 layer generates an IP header when + * sending a packet unless the IP_HDRINCL socket option + * is enabled on the socket. When it is enabled, the + * packet must contain an IP header. For receiving the + * IP header is always included in the packet. + * @return Return true on success. + */ + bool set_no_ip_hdr(); + + /** + * @brief Calculate an internet checksum needed for IPv4 IGMP header. + * @param buf header of the IGMP packet with a zero checksum field + * @param buf_size size of the IGMP packet + */ + u_int16_t calc_checksum(const unsigned char* buf, int buf_size); + + /** + * @brief Calculate the ICMPv6 header checksum by sending an ICMPv6 packet. + * Per default the ICMP6 checksum (RFC 3542 Section 3.1) will be calculate. + * @param enable if true the checsum will be calculate. + * @return Return true on success. + */ + bool set_default_icmp6_checksum_calc(bool enable); + + /** + * @brief Add an extension header to a sending packet. + * @param buf extension header + * @param buf_size size of the extension header + * @return Return true on success. + */ + bool add_extension_header(const unsigned char* buf, unsigned int buf_size); + + /** + * @brief Set to pass all icmpv6 packets to userpace. + * @return Return true on success. + */ + bool set_recv_icmpv6_msg(); + + /** + * @brief Set to pass the Hob-by-Hob header to userpace. + * @return Return true on success + */ + bool set_recv_hop_by_hop_msg(); + + /** + * @brief Set to pass the receive packet information to userpace. + * @return Return true on success + */ + bool set_recv_pkt_info(); + + /** + * @brief Enable or disable MRT flag to manipulate the multicast routing tables. + * - sysctl net.ipv4.conf.all.mc_forwarding will be set/reset + * @return Return true on success. + */ + bool set_mrt_flag(bool enable); + + /** + * @brief Adds the virtual interface to the mrouted API + * - sysctl net.ipv4.conf.eth0.mc_forwarding will be set + * - /proc/net$ cat ip_mr_vif displays the added interface + * + * @param vifNum musst the same unique number as delVIF (0 > uniqueNumber < MAXVIF ==32) + * @param ifName is the interface name e. g. "eth0" + * @param ipTunnelRemoteAddr if the interface is a tunnel interface the remote address has to set else it has to be NULL + * @return Return true on success. + */ + bool add_vif(int vifNum, const char* ifName, const char* ipTunnelRemoteAddr); + + /** + * @brief Bind the virtual interface to a spezific table as output and input interface + * @param vifNum is the virtual interface index + * @param table is the spezific table + * @return Return true on success. + */ + bool bind_vif_to_table(const char* ifName, int table); + + /** + * @brief unbind the virtual interface from a spezific table as output and input interface + * @param vifNum is the virtual interface index + * @param table is the spezific table + * @return Return true on success. + */ + bool unbind_vif_form_table(const char* ifName, int table); + + + /** + * @brief Delete the virtual interface from the multicast routing table. + * @param vifNum virtual index of the interface + * @return Return true on success. + */ + bool del_vif(int vifNum); + + /** + * @brief Adds a multicast route to the kernel. + * /proc/net$ cat ip_mr_cache display the route + * + * @param input_vifNum have to be the same value as in addVIF set + * @param source_addr from the receiving packet + * @param group_addr from the receiving packet + * @param output_vifNum forward to this virtual interface indexes + * @param output_vifNum_size size of the interface indexes + * @return Return true on success. + */ + bool add_mroute(int input_vifNum, const char* source_addr, const char* group_addr, unsigned int* output_vifNum, unsigned int output_vifNum_size); + + /** + * @brief Delete a multicast route. + * @param input_vifNum have to be the same value as in addVIF set + * @param source_addr from the receiving packet + * @param group_addr from the receiving packet + * @return Return true on success. + */ + bool del_mroute(int input_vifNum, const char* source_addr, const char* group_addr); + + /** + * @brief Get various statistics per interface. + * @param vif_index is the virtual interface index for an interface + * @param req_v4 musst point to a sioc_vif_req struct and will filled by this function when ipv4 is used + * @param req_v6 musst point to a sioc_mif_req6 struct and will filled by this function when ipv6 is used + * @return Return true on success. + */ + bool get_vif_stats(int vif_index, struct sioc_vif_req* req_v4, struct sioc_mif_req6* req_v6); + + /** + * @brief Get various statistics per multicast route. + * @param source_addr is the defined source address of the requested multicast route + * @param group_addr is the defined group address of the requested multicast route + * @param sgreq_v4 musst point to a sioc_sg_req struct and will filled by this function when ipv4 is used + * @param sgreq_v6 musst point to a sioc_sg_req6 struct and will filled by this function when ipv6 is used + * @return Return true on success. + */ + bool get_mroute_stats(const char* source_addr, const char* group_addr, struct sioc_sg_req* sgreq_v4, struct sioc_sg_req6* sgreq_v6); + + /** + * @brief simple test outputs + */ +#define MROUTE_SOCKET_SRC_ADDR_V4 "141.22.27.157" +#define MROUTE_SOCKET_G_ADDR_V4 "238.99.99.99" +#define MROUTE_SOCKET_SRC_ADDR_V6 "fe80::5e26:aff:fe23:8dc1" +#define MROUTE_SOCKET_G_ADDR_V6 "FF02:0:0:0:99:99:99:99" + +#define MROUTE_SOCKET_IF_NUM_ONE 0 +#define MROUTE_SOCKET_IF_NUM_TWO 1 +#define MROUTE_SOCKET_IF_NUM_THREE 2 +#define MROUTE_SOCKET_IF_STR_ONE "eth0" +#define MROUTE_SOCKET_IF_STR_TWO "wlan0" +#define MROUTE_SOCKET_IF_STR_THREE "tun0" + + void print_vif_stats(int vif_index); + void print_mroute_stats(const char* source_addr, const char* group_addr); + + static void print_struct_mf6cctl(struct mf6cctl* mc); + static void test_mcrouter_mrt_flag(); + + static void test_add_vifs(mroute_socket* m); + static void test_del_vifs(mroute_socket* m); + static void test_add_route(mroute_socket* m); + static void test_del_route(mroute_socket* m); + static void test_mcrouter_vifs_routes(int addrFamily); +}; + +#endif // MROUTE_SOCKET_HPP diff --git a/mcproxy/mainpage.dox b/mcproxy/mainpage.dox new file mode 100644 index 0000000000000000000000000000000000000000..22cb11376a7cc01236ed21c56b4e4b3a1be6cec9 --- /dev/null +++ b/mcproxy/mainpage.dox @@ -0,0 +1,88 @@ +/** + * \mainpage mcproxy + * + * \section Author + * Sebastian Wölke <Sebastian.Woelke@haw-hamburg.de> + * + * + * \section Introduction + * Mcproxy is an IGMP/MLD Proxy daemon for Linux. + * + * IGMP/MLD proxies offer the possibility to combine local + * multicast networks with a larger multicast infrastructure. In + * contrast to multicast routers, proxies are lightweight and do + * not require the support of a multicast routing protocols such as PIM or + * DVMRP. A common use case are local stub networks that interconnect with a + * remote multicast routing domain, possibly via a tunnel. Another usage + * example is in the Proxy Mobile IPv6 (PMIPv6 - RFC 5213) + * domains that want to provide transparent multicast services for + * mobile nodes. The mcproxy meets the requirements of the IGMP/MLD + * proxy standard (RFC 4605) and has additional functionalities. The + * multicast proxy can be instantiated multiple times and is dynamically + * configurable at runtime. + * + * \section Overview Overview + * + * \par + * The mcproxy is divided into the modules Receiver, Routing, Timer, + * Sender and an arbitrary number of Proxy-Instances. + * + * \image html overview.png + * + * \par + * The module @ref mod_proxy reads the configuration file on startup. It then configures + * and starts all other modules, acquire the mrt-flag on a socket for + * manipulating the multicast routing tables of the Linux kernel. + * + * \par + * A @ref mod_proxy_instance represents a full multicast proxy. Each instance + * has access to the modules Receiver, Routing, Sender and Timer. + * + * \par + * The module @ref mod_sender generates and sends Membership Queries to the + * downstreams and Membership Reports to the upstreams. + * + * \par + * The module @ref mod_receiver uses the socket with the mrt-flag to receive Membership + * Reports and Cache Miss messages. Cache Miss messages are sent from the + * Linux kernel in order to inform proxies about new multicast sources. + * + * \par + * The module @ref mod_routing sets and deletes virtual interfaces and multicast + * forwarding rules. + * + * \par + * The module @ref mod_timer organizes the temporal behavior of the Proxy-Instances. + * + * \subsection Communication Communication between the modules + * + * \image html interaction.png + * + * \par + * The modules communicate via synchronized message queues with the Proxy-Instances. + * + * \par + * Proxy-Instances register their interfaces at the module Receiver. + * If a Membership Report or a Cache Miss massage arrives at on of this + * regestrated interafaces, the module Receiver sends a message to the + * relevant Proxy-Instance. + * + * \par + * Proxy-Instances add reminders to the module Timer. A reminder contains a time + * and a message. If the predefined time expires for a reminder, the module Timer + * retun the reminder to the relevant Proxy-Instance. In this way, the temporal behavior + * of the Proxy-Instances is controlled. + * + * \par + * All other modules only waits for instructions from the Proxy-Instances. + * + * \subsection RFCs Related RFCs + * + * \par + * \li <a href="http://tools.ietf.org/html/rfc2236">RFC 2236</a> - IGMPv2 + * \li <a href="http://tools.ietf.org/html/rfc2710">RFC 2710</a> - MLDv1 + * \li <a href="http://tools.ietf.org/html/rfc4605">RFC 4605</a> - IGMP/MLD Proxying + * \li <a href="http://tools.ietf.org/html/rfc6224">RFC 6224</a> - Multicast Listener Support in PMIPv6 Domains + * + */ + diff --git a/mcproxy/mcproxy b/mcproxy/mcproxy new file mode 100755 index 0000000000000000000000000000000000000000..dfe9436eb6189a64c53336aee4df1008e712dab8 Binary files /dev/null and b/mcproxy/mcproxy differ diff --git a/mcproxy/mcproxy.conf b/mcproxy/mcproxy.conf new file mode 100644 index 0000000000000000000000000000000000000000..275a370e4eb07c4bac22d1cbeae9bec8049e75df --- /dev/null +++ b/mcproxy/mcproxy.conf @@ -0,0 +1,43 @@ +######################################################## +# +# Example configuration file for the mcproxy +# -------------------------------------------- +# +# The configuration file must define for every +# instance one upstream interface, and one or +# more downstream interfaces. +# +# upstream ==> downstream1 downstream2 ... downstreamN +# +# Only one protocol can be choosen!! Default is IGMPv2. +# +######################################################## + +##-- Protocol -- +#protocol MLDv1 #IPv6 +#protocol MLDv2 #IPv6, not implementet +#protocol IGMPv1 #IPv4, not implementet +protocol IGMPv2 #IPv4 +#protocol IGMPv3 #IPv4, not implementet + +##-- Instance 0 -- +#eth1 ==> eth0 +#tun0 ==> eth2 +#eth0 ==> tun2 +#tun0 ==> tun1 +#tun1 ==> tun0 +#tun2 ==> lo +lo ==> eth0 wlan0 +#eth2 ==> eth3 +#eth0 ==> lo + +##-- Instance 1 -- +#tun1 ==> eth2 tun3 tun4 + +##-- Instance 2 -- +#tun5 ==> eth3 tun6 tun7 tun8 + +#... + +##-- Instance N -- +#... diff --git a/mcproxy/mcproxy.pro b/mcproxy/mcproxy.pro new file mode 100644 index 0000000000000000000000000000000000000000..9cd7e4cf261b859bef6ad3ba3e079236478e6b2d --- /dev/null +++ b/mcproxy/mcproxy.pro @@ -0,0 +1,65 @@ +TARGET = mcproxy + +#CONFIG += release +CONFIG += debug + +CONFIG -= qt +QMAKE_CXXFLAGS += -ggdb +QMAKE_CXXFLAGS += -pedantic +QMAKE_CXXFLAGS += -ansi + +target.path = /usr/local/bin +INSTALLS += target + +doc.commands = doxygen ../doxygen/Doxyfile +QMAKE_EXTRA_TARGETS += doc + +SOURCES += src/main.cpp \ + src/hamcast_logging.cpp \ + #utils + src/utils/mc_socket.cpp \ + src/utils/addr_storage.cpp \ + src/utils/mroute_socket.cpp \ + src/utils/if_prop.cpp \ + #proxy + src/proxy/proxy.cpp \ + src/proxy/sender.cpp \ + src/proxy/receiver.cpp \ + src/proxy/mld_receiver.cpp \ + src/proxy/igmp_receiver.cpp \ + src/proxy/mld_sender.cpp \ + src/proxy/igmp_sender.cpp \ + src/proxy/proxy_instance.cpp \ + src/proxy/routing.cpp \ + src/proxy/worker.cpp \ + src/proxy/timing.cpp \ + src/proxy/check_if.cpp \ + src/proxy/check_source.cpp + +HEADERS += include/hamcast_logging.h \ + #utils + include/utils/mc_socket.hpp \ + include/utils/addr_storage.hpp \ + include/utils/mc_timers_values.hpp \ + include/utils/mroute_socket.hpp \ + include/utils/if_prop.hpp \ + #proxy + include/proxy/proxy.hpp \ + include/proxy/sender.hpp \ + include/proxy/receiver.hpp \ + include/proxy/mld_receiver.hpp \ + include/proxy/igmp_receiver.hpp \ + include/proxy/mld_sender.hpp \ + include/proxy/igmp_sender.hpp \ + include/proxy/proxy_instance.hpp \ + include/proxy/message_queue.hpp \ + include/proxy/message_format.hpp \ + include/proxy/routing.hpp \ + include/proxy/worker.hpp \ + include/proxy/timing.hpp \ + include/proxy/check_if.hpp \ + include/proxy/check_source.hpp + +LIBS += -L/usr/lib -lboost_thread \ + -lboost_date_time \ + -lboost_system diff --git a/mcproxy/mcproxy.pro.user b/mcproxy/mcproxy.pro.user new file mode 100644 index 0000000000000000000000000000000000000000..0644451af7e1470bc97a7766e2cf49b56b202a5e --- /dev/null +++ b/mcproxy/mcproxy.pro.user @@ -0,0 +1,157 @@ +<!DOCTYPE QtCreatorProject> +<qtcreator> + <data> + <variable>ProjectExplorer.Project.ActiveTarget</variable> + <value type="int">0</value> + </data> + <data> + <variable>ProjectExplorer.Project.EditorSettings</variable> + <valuemap type="QVariantMap"> + <value key="EditorConfiguration.AutoIndent" type="bool">true</value> + <value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value> + <value key="EditorConfiguration.Codec" type="QByteArray">System</value> + <value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value> + <value key="EditorConfiguration.IndentBraces" type="bool">false</value> + <value key="EditorConfiguration.IndentSize" type="int">4</value> + <value key="EditorConfiguration.MouseNavigation" type="bool">true</value> + <value key="EditorConfiguration.PaddingMode" type="int">1</value> + <value key="EditorConfiguration.ScrollWheelZooming" type="bool">true</value> + <value key="EditorConfiguration.SmartBackspace" type="bool">false</value> + <value key="EditorConfiguration.SpacesForTabs" type="bool">true</value> + <value key="EditorConfiguration.TabKeyBehavior" type="int">0</value> + <value key="EditorConfiguration.TabSize" type="int">8</value> + <value key="EditorConfiguration.UseGlobal" type="bool">true</value> + <value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value> + <value key="EditorConfiguration.addFinalNewLine" type="bool">true</value> + <value key="EditorConfiguration.cleanIndentation" type="bool">true</value> + <value key="EditorConfiguration.cleanWhitespace" type="bool">true</value> + <value key="EditorConfiguration.inEntireDocument" type="bool">false</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.Target.0</variable> + <valuemap type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value> + <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Bereinigen</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">4.7.4 Release</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/wolke/Dropbox/HAMcast/mcproxy/code/mcproxy/mcproxy</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">4</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">false</value> + </valuemap> + <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value> + <valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deployment</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Kein Deployment</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value> + </valuemap> + <value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value> + <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">mcproxy</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">mcproxy.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.TargetCount</variable> + <value type="int">1</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable> + <value type="QString">{6f6aec4b-1d57-4488-9852-8a87522e5ffc}</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.FileVersion</variable> + <value type="int">9</value> + </data> +</qtcreator> diff --git a/mcproxy/src/hamcast_logging.cpp b/mcproxy/src/hamcast_logging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98722de0524d981c3266b7018a0a7003166a97ca --- /dev/null +++ b/mcproxy/src/hamcast_logging.cpp @@ -0,0 +1,175 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Dominik Charousset <dominik.charousset@haw-hamburg.de> + */ + + +#include "include/hamcast_logging.h" +#include <fstream> +#include <boost/thread.hpp> +#include <boost/date_time.hpp> + +#include <boost/thread/pthread/shared_mutex.hpp> +#include <boost/thread/pthread/mutex.hpp> + + +namespace +{ + hc_log_fun_t m_log_fun = 0; + boost::shared_mutex m_log_fun_mtx; + + boost::mutex m_next_id_mtx; + boost::uint32_t m_next_id = 0; + + boost::uint32_t next_session_id() + { + boost::mutex::scoped_lock lock(m_next_id_mtx); + return m_next_id++; + } + + class logger + { + + bool m_enabled; + boost::uint32_t m_id; + std::fstream m_stream; + + public: + + logger(bool enabled = true) + : m_enabled(enabled), m_id(next_session_id()) + { + std::ostringstream oss; + oss << "thread" << m_id << ".log"; + std::string filename = oss.str(); + m_stream.open(filename.c_str(), std::fstream::out); + } + + inline void enable() { m_enabled = true; } + + inline void disable() { m_enabled = false; } + + void log(int lvl, const char* fun, const char* what) + { + using boost::get_system_time; + using boost::posix_time::to_iso_extended_string; + std::string time_stamp = to_iso_extended_string(get_system_time()); + std::ostringstream os; + os.width(28); + os << std::left << time_stamp; + os.width(7); + os << std::left; + switch (lvl) + { + case HC_LOG_TRACE_LVL: os << "TRACE"; break; + case HC_LOG_DEBUG_LVL: os << "DEBUG"; break; + case HC_LOG_INFO_LVL: os << "INFO"; break; + case HC_LOG_WARN_LVL: os << "WARN"; break; + case HC_LOG_ERROR_LVL: os << "ERROR"; break; + case HC_LOG_FATAL_LVL: os << "FATAL"; break; + default: break; + } + os.width(80); + os << std::left << fun; + os.width(0); + os << what; + os << "\n"; + std::string oss = os.str(); + m_stream << oss; + m_stream.flush(); + } + + ~logger() + { + m_stream.flush(); + m_stream.close(); + } + + }; + + boost::thread_specific_ptr<logger> m_logger; + + logger& thread_logger() + { + if (!(m_logger.get())) m_logger.reset(new logger); + return *(m_logger.get()); + } + + //hc_log_fun_t m_logger_fun = 0; + + void log_all_fun(int lvl, const char *fun_name, const char* line) + { + thread_logger().log(lvl, fun_name, line); + } + + void log_debug_fun(int lvl, const char* fun_name, const char* line) + { + if (lvl >= HC_LOG_DEBUG_LVL) log_all_fun(lvl, fun_name, line); + } + + void log_info_fun(int lvl, const char* fun_name, const char* line) + { + if (lvl >= HC_LOG_INFO_LVL) log_all_fun(lvl, fun_name, line); + } + + void log_warn_fun(int lvl, const char* fun_name, const char* line) + { + if (lvl >= HC_LOG_INFO_LVL) log_all_fun(lvl, fun_name, line); + } + + void log_error_fun(int lvl, const char* fun_name, const char* line) + { + if (lvl >= HC_LOG_ERROR_LVL) log_all_fun(lvl, fun_name, line); + } + + void log_fatal_fun(int lvl, const char* fun_name, const char* line) + { + if (lvl >= HC_LOG_FATAL_LVL) log_all_fun(lvl, fun_name, line); + } +} + +hc_log_fun_t hc_get_log_fun() +{ + boost::shared_lock<boost::shared_mutex> guard(m_log_fun_mtx); + return m_log_fun; +} + +void hc_set_log_fun(hc_log_fun_t function_ptr) +{ + boost::lock_guard<boost::shared_mutex> guard(m_log_fun_mtx); + m_log_fun = function_ptr; +} + +void hc_log(int loglvl, const char* func_name, const char *msg) +{ + boost::shared_lock<boost::shared_mutex> guard(m_log_fun_mtx); + if (m_log_fun) m_log_fun(loglvl, func_name, msg); +} + +void hc_set_default_log_fun(int log_lvl) +{ + switch (log_lvl) + { + case HC_LOG_DEBUG_LVL: hc_set_log_fun(log_debug_fun); break; + case HC_LOG_INFO_LVL: hc_set_log_fun(log_info_fun); break; + case HC_LOG_WARN_LVL: hc_set_log_fun(log_warn_fun); break; + case HC_LOG_ERROR_LVL: hc_set_log_fun(log_error_fun); break; + case HC_LOG_FATAL_LVL: hc_set_log_fun(log_fatal_fun); break; + default: hc_set_log_fun(log_all_fun); + } +} diff --git a/mcproxy/src/main.cpp b/mcproxy/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0602ba2b1136733ed47073b106a83961354d693b --- /dev/null +++ b/mcproxy/src/main.cpp @@ -0,0 +1,84 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +#include "include/hamcast_logging.h" +#include "include/utils/if_prop.hpp" +#include "include/utils/mc_socket.hpp" +#include "include/utils/mroute_socket.hpp" +#include "include/utils/addr_storage.hpp" +#include "include/proxy/proxy.hpp" +#include "include/proxy/timing.hpp" +#include "include/proxy/check_if.hpp" +#include "include/utils/if_prop.hpp" + + +#include <iostream> +using namespace std; + +void test_log(); +void test_mctables(); +void test_MC_TestTool(); +void test_mcproxy(int arg_count, char* args[]); +void test_test(); + +int main(int arg_count, char* args[]) { + hc_set_default_log_fun(HC_LOG_TRACE_LVL); + + //test_MC_Tables(); + //test_MC_TestTool(); + + test_mcproxy(arg_count,args); + + + //test_test(); + return 0; +} + +void test_log(){ + hc_set_default_log_fun(HC_LOG_TRACE_LVL); + HC_LOG_TRACE(""); + + HC_LOG_DEBUG("HC_LOG_DEBUG"); + HC_LOG_INFO("HC_LOG_INFO"); + HC_LOG_WARN("HC_LOG_WARN"); + HC_LOG_ERROR("HC_LOG_ERROR"); + HC_LOG_FATAL("HC_LOG_FATAL"); +} + +void test_mcproxy(int arg_count, char* args[]){ + hc_set_default_log_fun(HC_LOG_ERROR_LVL); + + proxy p; + if(p.init(arg_count, args)){ + cout << "mcproxy started" << endl; + cout << p.get_state_table() << endl; + p.start(); + p.stop(); + }else{ + cout << "mcproxy stopped! For more informations see log files." << endl; + } +} + +void test_test(){ + addr_storage::test_addr_storage(); + +} diff --git a/mcproxy/src/proxy/check_if.cpp b/mcproxy/src/proxy/check_if.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3984d8824e7a9c241d4748ea7bc37a664cc80221 --- /dev/null +++ b/mcproxy/src/proxy/check_if.cpp @@ -0,0 +1,181 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/check_if.hpp" +#include <net/if.h> +#include <unistd.h> +#include <iostream> + +using namespace std; + + +check_if::check_if() +{ + HC_LOG_TRACE(""); +} + +std::vector<int> check_if::init(vector<int>& check_lst, int addr_family){ + HC_LOG_TRACE(""); + + this->m_check_lst = check_lst; + this->m_addr_family = addr_family; + + vector<int> result; + m_if_property_a.refresh_network_interfaces(); + m_current_prop = &m_if_property_a; + + for(vector<int>::iterator i= m_check_lst.begin(); i != m_check_lst.end(); i++){ + char cstr[IF_NAMESIZE]; + string if_name(if_indextoname(*i,cstr)); + + const struct ifaddrs* prop; + if(m_addr_family == AF_INET){ + prop = m_current_prop->get_ip4_if(if_name); + }else if(m_addr_family == AF_INET6){ + const list<const struct ifaddrs*>* ipv6_if_list = m_current_prop->get_ip6_if(if_name); + prop = *(ipv6_if_list->begin()); + } + + if(!(prop->ifa_flags & IFF_RUNNING)){ //down + result.push_back(*i); + } + } + + return result; +} + +bool check_if::check(){ + HC_LOG_TRACE(""); + + m_swap_to_up.clear(); + m_swap_to_down.clear(); + + if_prop* if_property_old = m_current_prop; + + if(m_current_prop == &m_if_property_a){ + m_current_prop = &m_if_property_b; + }else if(m_current_prop == &m_if_property_b){ + m_current_prop = &m_if_property_a; + }else{ + HC_LOG_ERROR("unknown pointer"); + return false; + } + + m_current_prop->refresh_network_interfaces(); + + for(vector<int>::iterator i= m_check_lst.begin(); i != m_check_lst.end(); i++){ + char cstr[IF_NAMESIZE]; + string if_name(if_indextoname(*i,cstr)); + + const struct ifaddrs* prop_new = m_current_prop->get_ip4_if(if_name); + const struct ifaddrs* prop_old = if_property_old->get_ip4_if(if_name); + + if(m_addr_family == AF_INET){ + prop_new = m_current_prop->get_ip4_if(if_name); + prop_old = if_property_old->get_ip4_if(if_name); + }else if(m_addr_family == AF_INET6){ + const list<const struct ifaddrs*>* ipv6_if_list_new = m_current_prop->get_ip6_if(if_name); + const list<const struct ifaddrs*>* ipv6_if_list_old = if_property_old->get_ip6_if(if_name); + + prop_new = *(ipv6_if_list_new->begin()); + prop_old = *(ipv6_if_list_old->begin()); + } + + if(((prop_new->ifa_flags ^ prop_old->ifa_flags) & IFF_RUNNING)){ //IFF_RUNNING changed + if(prop_new->ifa_flags & IFF_RUNNING){ //up + m_swap_to_up.push_back(*i); + }else{ //down + m_swap_to_down.push_back(*i); + } + } + } + + return true; +} + +std::vector<int> check_if::swap_to_up(){ + HC_LOG_TRACE(""); + return m_swap_to_up; + +} + +std::vector<int> check_if::swap_to_down(){ + HC_LOG_TRACE(""); + return m_swap_to_down; +} + +void check_if::test_check_if(){ + HC_LOG_TRACE(""); + + check_if c; + if_prop prop; + vector<int> if_list_tmp; + char cstr[IF_NAMESIZE]; + int sleeptime= 0; + + //fill if_list_tmp + prop.refresh_network_interfaces(); + const if_prop_map* if_prop_map_p = prop.get_if_props(); + cout << "available interfaces under test:" << endl; + for(if_prop_map::const_iterator i= if_prop_map_p->begin(); i != if_prop_map_p->end(); i++){ + cout << i->first <<" "; + if_list_tmp.push_back(if_nametoindex(i->first.c_str())); + } + cout << endl; + + //init status + if_list_tmp = c.init(if_list_tmp, AF_INET); + cout << "this interfaces are down:" << endl; + for(vector<int>::iterator i= if_list_tmp.begin(); i != if_list_tmp.end(); i++){ + cout << if_indextoname(*i,cstr) << " "; + } + cout << endl; + + while(sleeptime< 1000){ + usleep(1000000); + cout << "sleeptime: " << sleeptime << endl; + c.check(); + if_list_tmp = c.swap_to_down(); + if(if_list_tmp.size() >0){ + cout << "this interfaces switch to down: " << endl; + for(vector<int>::iterator i= if_list_tmp.begin(); i < if_list_tmp.end(); i++){ + cout << if_indextoname(*i,cstr) << " "; + } + cout << endl; + } + + if_list_tmp = c.swap_to_up(); + if(if_list_tmp.size() >0){ + cout << "this interfaces switch to up: " << endl; + for(vector<int>::iterator i= if_list_tmp.begin(); i < if_list_tmp.end(); i++){ + cout << if_indextoname(*i,cstr) << " "; + } + cout << endl; + } + + sleeptime++; + } + + +} diff --git a/mcproxy/src/proxy/check_source.cpp b/mcproxy/src/proxy/check_source.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f99d92ef99f8a7e58616d9c84565eb731cd4d1df --- /dev/null +++ b/mcproxy/src/proxy/check_source.cpp @@ -0,0 +1,119 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +#include "include/hamcast_logging.h" +#include "include/utils/addr_storage.hpp" +#include "include/proxy/check_source.hpp" +#include <linux/mroute.h> +#include <linux/mroute6.h> + +bool check_source::init(int addr_family, mroute_socket* sock ){ + HC_LOG_TRACE(""); + + this->m_addr_family = addr_family; + m_sock = sock; + + m_current_check = &m_check_src_a; + + return true; +} + +bool check_source::check(){ + HC_LOG_TRACE(""); + + if(m_current_check == &m_check_src_a){ + m_current_check = &m_check_src_b; + }else{ + m_current_check = &m_check_src_a; + } + + m_current_check->clear(); + + return true; +} + +bool check_source::is_src_unused(int vif, addr_storage src_addr, addr_storage g_addr){ + HC_LOG_TRACE(""); + + // old table | new talbe | unused? + // entry | entry | + //------------------------------------ + // empty | empty | true ==> Error + //------------------------------------ + // empty | exist | false ==> save to current table + //------------------------------------ + // exist | empty | true ==> Error + //------------------------------------ + // exist | exist | IF( old entry != new entry) ==> false and save ELSE true and save + + pkt_cnt_map* old_check= (m_current_check == &m_check_src_a)? &m_check_src_b : &m_check_src_a; + + int current_pkt_cnt = -1; + int old_pkt_cnt = -1; + + //extract mroute information + //--kernel + if(m_addr_family == AF_INET){ + struct sioc_sg_req tmp_stat; + if(m_sock->get_mroute_stats(src_addr.to_string().c_str(), g_addr.to_string().c_str(), &tmp_stat, NULL)){ + current_pkt_cnt = tmp_stat.pktcnt; + HC_LOG_DEBUG(" src_addr: " << src_addr << " g_addr: " << g_addr << " vif: " << vif); + HC_LOG_DEBUG(" -packets[" << tmp_stat.bytecnt << " bytes]:" << tmp_stat.pktcnt); + HC_LOG_DEBUG(" -wrong packets:" << tmp_stat.wrong_if); + }else{ + return true; + } + }else if(m_addr_family == AF_INET6){ + struct sioc_sg_req6 tmp_stat; + if(m_sock->get_mroute_stats(src_addr.to_string().c_str(), g_addr.to_string().c_str(), NULL, &tmp_stat)){ + current_pkt_cnt = tmp_stat.pktcnt; + HC_LOG_DEBUG(" src_addr: " << src_addr << " g_addr: " << g_addr << " vif: " << vif); + HC_LOG_DEBUG(" -packets[" << tmp_stat.bytecnt << " bytes]:" << tmp_stat.pktcnt); + HC_LOG_DEBUG(" -wrong packets:" << tmp_stat.wrong_if); + }else{ + return true; + } + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return true; + } + + //evaluate and save mroute information + src_grp_pair current_sg_pair(src_addr,g_addr); + pkt_cnt_map::iterator iter_pkt_cnt = old_check->find(current_sg_pair); + + if(iter_pkt_cnt == old_check->end()){ + m_current_check->insert(pkt_cnt_pair(current_sg_pair,current_pkt_cnt)); + return false; + }else{ + old_pkt_cnt = iter_pkt_cnt->second; + } + + if(current_pkt_cnt == old_pkt_cnt){ + m_current_check->insert(pkt_cnt_pair(current_sg_pair,current_pkt_cnt)); + return true; + }else{ + m_current_check->insert(pkt_cnt_pair(current_sg_pair,current_pkt_cnt)); + return false; + } + +} diff --git a/mcproxy/src/proxy/igmp_receiver.cpp b/mcproxy/src/proxy/igmp_receiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..629c9ae64d6879ad1c00dc39daa611fda30965cb --- /dev/null +++ b/mcproxy/src/proxy/igmp_receiver.cpp @@ -0,0 +1,178 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +#include "include/hamcast_logging.h" +#include "include/proxy/igmp_receiver.hpp" +#include "include/proxy/proxy_instance.hpp" + +#include <net/if.h> +#include <linux/mroute.h> +#include <netinet/igmp.h> +#include <netinet/ip.h> + + + +igmp_receiver::igmp_receiver(){ + HC_LOG_TRACE(""); +} + +int igmp_receiver::get_iov_min_size(){ + HC_LOG_TRACE(""); + int size_ip = sizeof(struct ip) + sizeof(struct igmp) + IGMP_RECEIVER_IPV4_ROUTER_ALERT_OPT_SIZE; + int size_kernel = sizeof(struct igmpmsg); + return (size_ip < size_kernel)? size_kernel : size_ip; +} + +int igmp_receiver::get_ctrl_min_size(){ + HC_LOG_TRACE(""); + //useless + return 0; +} + +void igmp_receiver::analyse_packet(struct msghdr* msg, int info_size){ + HC_LOG_TRACE(""); + + struct ip* ip_hdr = (struct ip*)msg->msg_iov->iov_base; + struct igmp* igmp_hdr = (struct igmp*) ((char*)msg->msg_iov->iov_base + ip_hdr->ip_hl*4); + + int if_index = 0; + addr_storage g_addr; + addr_storage src_addr; + proxy_instance* pr_i; + + //test_output::printPacket_IPv4_Infos(buf, msg_size); + HC_LOG_DEBUG("received packet XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + + /* packets sent up from kernel to daemon have ip->ip_p = 0 */ + if(ip_hdr->ip_p == IGMP_RECEIVER_KERNEL_MSG){ + HC_LOG_DEBUG("kernel msg"); + struct igmpmsg *igmpctl; + igmpctl = (struct igmpmsg *) msg->msg_iov->iov_base; + + switch (igmpctl->im_msgtype) { + case IGMPMSG_NOCACHE: { + src_addr = igmpctl->im_src; + HC_LOG_DEBUG("\tsrc: " << src_addr); + + g_addr = igmpctl->im_dst; + HC_LOG_DEBUG("\tgroup: " << g_addr); + + HC_LOG_DEBUG("\tvif: " << (int)igmpctl->im_vif); + if((if_index = get_if_index(igmpctl->im_vif)) == 0) return; + HC_LOG_DEBUG("\tif_index: " << if_index); + + if((pr_i = get_proxy_instance(if_index)) == NULL) return; + + proxy_msg m; + m.type = proxy_msg::RECEIVER_MSG; + m.msg = new struct receiver_msg(receiver_msg::CACHE_MISS, if_index, src_addr, g_addr); + pr_i->add_msg(m); + break; + } + default: + HC_LOG_WARN("unknown kernel message"); + } + }else if(ip_hdr->ip_p == IPPROTO_IGMP && ntohs(ip_hdr->ip_len)==get_iov_min_size()){ + //test_output::printPaket_IPv4_IgmpInfos(buf); + if(igmp_hdr->igmp_type == IGMP_V2_MEMBERSHIP_REPORT){ + HC_LOG_DEBUG("\tjoin"); + + src_addr = ip_hdr->ip_src; + HC_LOG_DEBUG("\tsrc: " << src_addr); + + g_addr = igmp_hdr->igmp_group; + HC_LOG_DEBUG("\tgroup: " << g_addr); + + if((if_index = this->map_ip2if_index(src_addr)) == 0) return; + HC_LOG_DEBUG("\tif_index: " << if_index); + + if((pr_i= this->get_proxy_instance(if_index))== NULL) return; + + proxy_msg m; + m.type = proxy_msg::RECEIVER_MSG; + m.msg = new struct receiver_msg(receiver_msg::JOIN, if_index, g_addr); + pr_i->add_msg(m); + }else if(igmp_hdr->igmp_type == IGMP_V2_LEAVE_GROUP){ + HC_LOG_DEBUG("\tleave"); + + src_addr = ip_hdr->ip_src; + HC_LOG_DEBUG("\tsrc: " << src_addr); + + g_addr = igmp_hdr->igmp_group; + HC_LOG_DEBUG("\tgroup: " << g_addr); + + if((if_index = this->map_ip2if_index(src_addr))== 0) return ; + HC_LOG_DEBUG("\tif_index: " << if_index); + + if((pr_i=this->get_proxy_instance(if_index)) ==NULL) return; + + proxy_msg m; + m.type = proxy_msg::RECEIVER_MSG; + m.msg = new struct receiver_msg(receiver_msg::LEAVE, if_index, g_addr); + pr_i->add_msg(m); + }else{ + HC_LOG_DEBUG("unknown IGMP-packet"); + HC_LOG_DEBUG("type: " << igmp_hdr->igmp_type); + } + }else{ + HC_LOG_DEBUG("unknown IP-packet: " << ip_hdr->ip_p); + } +} + +int igmp_receiver::map_ip2if_index(const addr_storage& src_addr){ + HC_LOG_TRACE(""); + + char cstr[IF_NAMESIZE]; + addr_storage tmp_mask; + + addr_storage own_addr; + const struct ifaddrs* item; + + addr_storage comp_addr; + + if(src_addr.get_addr_family() == AF_INET){ + if_poxy_instance_map::iterator it; + for(it= m_if_proxy_map.begin(); it != m_if_proxy_map.end(); it++){ + //maks own ip + string if_name(if_indextoname(it->first, cstr)); + + item = m_if_property.get_ip4_if(if_name); + if(item == NULL) return 0; + + own_addr = *(item->ifa_addr); + tmp_mask = *(item->ifa_netmask); + + comp_addr = own_addr.mask(tmp_mask); + + if(comp_addr == tmp_mask.mask(src_addr)){ + return it->first; + } + + } + }else{ + HC_LOG_ERROR("cannot map IPv6 addr to interface index:" << src_addr); + return 0; + } + + return 0; //no interface found +} + diff --git a/mcproxy/src/proxy/igmp_sender.cpp b/mcproxy/src/proxy/igmp_sender.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f817c9c9d02178b0256ebf52b20240d2d57dd2a --- /dev/null +++ b/mcproxy/src/proxy/igmp_sender.cpp @@ -0,0 +1,132 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/igmp_sender.hpp" +#include "include/utils/mc_timers_values.hpp" + +#include <netinet/igmp.h> +#include <netinet/ip.h> +#include <net/if.h> + +igmp_sender::igmp_sender(){ + HC_LOG_TRACE(""); + +} + +bool igmp_sender::init(int addr_family, int version){ + HC_LOG_TRACE(""); + + if(addr_family == AF_INET){ + if(!sender::init(addr_family,version)) return false; + }else{ + return false; + } + + return true; +} + +bool igmp_sender::send_general_query(int if_index){ + HC_LOG_TRACE(""); + + int size = get_msg_min_size(); + if(size <0) return false; + unsigned char buf[size]; + + if(!m_sock.choose_if(if_index)) return false; + if(!create_mc_query(GENERAL_QUERY, buf)) return false; + + return m_sock.send_packet(IPV4_ALL_HOST_ADDR,0,buf,sizeof(buf)); +} + +bool igmp_sender::send_group_specific_query(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + int size = get_msg_min_size(); + if(size <0) return false; + unsigned char buf[size]; + + if(!m_sock.choose_if(if_index)) return false; + if(!create_mc_query(GROUP_SPECIFIC_QUERY, buf, &g_addr)) return false; + + return m_sock.send_packet(g_addr.to_string().c_str(),0,buf,sizeof(buf)); +} + +bool igmp_sender::send_report(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + return m_sock.join_group(g_addr.to_string().c_str(),if_index); +} + +bool igmp_sender::send_leave(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + return m_sock.leave_group(g_addr.to_string().c_str(),if_index); +} + +int igmp_sender::get_msg_min_size(){ + HC_LOG_TRACE(""); + + if(m_version == 2){ + return sizeof(struct igmp); + }else{ + HC_LOG_ERROR("IPv4 version: " << m_version << " not supported"); + return -1; + } +} + + +bool igmp_sender::create_mc_query(msg_type type, unsigned char* buf,const addr_storage* g_addr){ + HC_LOG_TRACE(""); + + if(m_version == 2){ + struct igmp* igmp_Hdr = (struct igmp*)(buf); + + igmp_Hdr->igmp_type = IGMP_MEMBERSHIP_QUERY; + igmp_Hdr->igmp_cksum = 0; + + if(type==GENERAL_QUERY){ + igmp_Hdr->igmp_code = MC_TV_QUERY_RESPONSE_INTERVAL*MC_TV_MAX_RESPONSE_TIME_UNIT; + igmp_Hdr->igmp_group = addr_storage(m_addr_family).get_in_addr(); //0.0.0.0 + }else if(type== GROUP_SPECIFIC_QUERY){ + if(!g_addr){ + HC_LOG_ERROR("g_addr is NULL"); + return false; + } + + igmp_Hdr->igmp_code = MC_TV_LAST_MEMBER_QUERY_INTEVAL*MC_TV_MAX_RESPONSE_TIME_UNIT; + igmp_Hdr->igmp_group = g_addr->get_in_addr(); + }else{ + HC_LOG_ERROR("wrong type: " << type); + return false; + } + + igmp_Hdr->igmp_cksum = m_sock.calc_checksum((unsigned char*)igmp_Hdr,sizeof(struct igmp)); + + return true; + }else{ + HC_LOG_ERROR("wrong verson: "<< m_version); + return false; + } +} + diff --git a/mcproxy/src/proxy/mld_receiver.cpp b/mcproxy/src/proxy/mld_receiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55ef91d14e3454005866f27d97eb9ad30768ec60 --- /dev/null +++ b/mcproxy/src/proxy/mld_receiver.cpp @@ -0,0 +1,123 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/mld_receiver.hpp" +#include "include/proxy/proxy_instance.hpp" + +#include <linux/mroute6.h> +#include <netinet/ip6.h> +#include <netinet/icmp6.h> +#include <sys/socket.h> + +//DEBUG +#include <net/if.h> + +mld_receiver::mld_receiver(){ + HC_LOG_TRACE(""); +} + + +bool mld_receiver::init(int addr_family, int version, mroute_socket* mrt_sock){ + bool rc = this->receiver::init(addr_family,version,mrt_sock); + if(!rc) return false; + if(!m_mrt_sock->set_recv_icmpv6_msg()) return false; + if(!m_mrt_sock->set_recv_pkt_info()) return false; + + return true; +} + + +int mld_receiver::get_iov_min_size(){ + HC_LOG_TRACE(""); + int size_ip = sizeof(struct mld_hdr); + int size_kernel = sizeof(struct mrt6msg); + return (size_ip < size_kernel)? size_kernel : size_ip; +} + +int mld_receiver::get_ctrl_min_size(){ + HC_LOG_TRACE(""); + + return sizeof(struct cmsghdr) +sizeof(struct in6_pktinfo); + //return 400; +} + +void mld_receiver::analyse_packet(struct msghdr* msg, int info_size){ + HC_LOG_TRACE(""); + + + struct mld_hdr* hdr = (struct mld_hdr*)msg->msg_iov->iov_base; + proxy_instance* pr_i; + addr_storage g_addr; + + if(hdr->mld_type == MLD_RECEIVER_KERNEL_MSG){ //kernel + struct mrt6msg* mldctl = (struct mrt6msg*)msg->msg_iov->iov_base; + + switch (mldctl->im6_msgtype) { + case MRT6MSG_NOCACHE: { + addr_storage src_addr(mldctl->im6_src); + g_addr = mldctl->im6_dst; + + int if_index; + if((if_index = get_if_index(mldctl->im6_mif)) == 0) return; + + if((pr_i = get_proxy_instance(if_index)) == NULL) return; + + proxy_msg m; + m.type = proxy_msg::RECEIVER_MSG; + m.msg = new struct receiver_msg(receiver_msg::CACHE_MISS, if_index, src_addr, g_addr); + pr_i->add_msg(m); + break; + } + default: + HC_LOG_WARN("unknown kernel message"); + } + }else if(hdr->mld_type == MLD_LISTENER_REPORT || hdr->mld_type == MLD_LISTENER_REDUCTION){ //join + struct in6_pktinfo* packet_info = NULL; + + for (struct cmsghdr* cmsgptr = CMSG_FIRSTHDR(msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(msg, cmsgptr)) { + if (cmsgptr->cmsg_len > 0 &&cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO ) { + packet_info = (struct in6_pktinfo*)CMSG_DATA(cmsgptr); + } + } + if(packet_info == NULL) return; + + if((pr_i = this->get_proxy_instance(packet_info->ipi6_ifindex))== NULL) return; //?is ifindex registratet + g_addr = hdr->mld_addr; + + proxy_msg m; + m.type = proxy_msg::RECEIVER_MSG; + + if(hdr->mld_type == MLD_LISTENER_REPORT){ + m.msg = new struct receiver_msg(receiver_msg::JOIN, packet_info->ipi6_ifindex, g_addr); + }else if(hdr->mld_type == MLD_LISTENER_REDUCTION){ + m.msg = new struct receiver_msg(receiver_msg::LEAVE, packet_info->ipi6_ifindex, g_addr); + }else{ + HC_LOG_ERROR("wrong mld type"); + } + + pr_i->add_msg(m); + }else{ + HC_LOG_DEBUG("unknown MLD-packet: " << (int)(hdr->mld_type)); + } +} diff --git a/mcproxy/src/proxy/mld_sender.cpp b/mcproxy/src/proxy/mld_sender.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d93ddf8043146b00ccef5753e847d6554450b66 --- /dev/null +++ b/mcproxy/src/proxy/mld_sender.cpp @@ -0,0 +1,156 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + +#include "include/hamcast_logging.h" +#include "include/proxy/mld_sender.hpp" +#include "include/utils/mc_timers_values.hpp" + +#include <net/if.h> +#include <netinet/icmp6.h> +#include <netinet/ip6.h> + +mld_sender::mld_sender(){ + HC_LOG_TRACE(""); + +} + +bool mld_sender::init(int addr_family, int version){ + HC_LOG_TRACE(""); + + if(addr_family == AF_INET6){ + if(!sender::init(addr_family,version)) return false; + if(!m_sock.set_default_icmp6_checksum_calc(true)) return false; + if(!add_hbh_opt_header()) return false; + }else{ + return false; + } + + return true; +} + +bool mld_sender::send_general_query(int if_index){ + HC_LOG_TRACE(""); + + int size = get_msg_min_size(); + if(size <0) return false; + + if(!m_sock.choose_if(if_index)) return false; + + unsigned char buf[size]; + if(!create_mc_query(GENERAL_QUERY, buf)) return false; + + return m_sock.send_packet(IPV6_ALL_NODES_ADDR,0,buf,sizeof(buf)); +} + +bool mld_sender::send_group_specific_query(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + int size = get_msg_min_size(); + if(size <0) return false; + + if(!m_sock.choose_if(if_index)) return false; + + unsigned char buf[size]; + if(!create_mc_query(MC_ADDR_SPECIFIC_QUERY, buf, &g_addr)) return false; + + return m_sock.send_packet(g_addr.to_string().c_str(),0,buf,sizeof(buf)); +} + +int mld_sender::get_msg_min_size(){ + HC_LOG_TRACE(""); + + if(m_version == 1){ + return sizeof(struct mld_hdr); + }else{ + HC_LOG_ERROR("IPv6 version: " << m_version << " not supported"); + return -1; + } +} + +bool mld_sender::send_report(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + return m_sock.join_group(g_addr.to_string().c_str(),if_index); +} + +bool mld_sender::send_leave(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + return m_sock.leave_group(g_addr.to_string().c_str(),if_index); +} + +bool mld_sender::create_mc_query(msg_type type, unsigned char* buf, const addr_storage* g_addr){ + HC_LOG_TRACE(""); + + if(m_version == 1){ + struct mld_hdr* mld_Hdr = (struct mld_hdr*)buf; + + mld_Hdr->mld_type = MLD_LISTENER_QUERY; + mld_Hdr->mld_code = 0; + mld_Hdr->mld_cksum = MC_MASSAGES_AUTO_FILL; + mld_Hdr->mld_reserved = 0; + + if(type==GENERAL_QUERY){ + mld_Hdr->mld_maxdelay = htons(MC_TV_QUERY_RESPONSE_INTERVAL * MC_TV_MAX_RESPONSE_DELAY_UNIT); + mld_Hdr->mld_addr = addr_storage(m_addr_family).get_in6_addr(); //0.0.0.0 + }else if(type== MC_ADDR_SPECIFIC_QUERY){ + if(!g_addr){ + HC_LOG_ERROR("g_addr is NULL"); + return false; + } + + mld_Hdr->mld_maxdelay = htons(MC_TV_LAST_LISTENER_QUERY_INTERVAL * MC_TV_MAX_RESPONSE_DELAY_UNIT); + mld_Hdr->mld_addr = g_addr->get_in6_addr(); + }else{ + HC_LOG_ERROR("wrong type: " << type); + return false; + } + + return true; + }else{ + HC_LOG_ERROR("wrong verson: "<< m_version); + return false; + } +} + +bool mld_sender::add_hbh_opt_header(){ + HC_LOG_TRACE(""); + + unsigned char extbuf[sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)+ sizeof(pad2)]; + + struct ip6_hbh* hbh_Hdr = (struct ip6_hbh*)extbuf; + struct ip6_opt_router* opt_Hdr = (struct ip6_opt_router*)(extbuf + sizeof(struct ip6_hbh)); + pad2* pad_Hdr = (pad2*)(extbuf + sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)); + + hbh_Hdr->ip6h_nxt = IPPROTO_ICMPV6; + hbh_Hdr->ip6h_len = MC_MASSAGES_IPV6_ROUTER_ALERT_OPT_SIZE; //=> 8 Bytes + + opt_Hdr->ip6or_type = IP6OPT_ROUTER_ALERT; + opt_Hdr->ip6or_len = sizeof(opt_Hdr->ip6or_value); + *(u_int16_t*)&opt_Hdr->ip6or_value[0] = IP6_ALERT_MLD; + + *pad_Hdr = IP6OPT_PADN; + + if(!m_sock.add_extension_header((unsigned char*)hbh_Hdr,sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)+ sizeof(pad2))) return false; + + return true; +} diff --git a/mcproxy/src/proxy/proxy.cpp b/mcproxy/src/proxy/proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a3626be7fc0c76a09c063bec712e6189d2a6855 --- /dev/null +++ b/mcproxy/src/proxy/proxy.cpp @@ -0,0 +1,805 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/proxy.hpp" +#include "include/proxy/routing.hpp" +#include "include/proxy/igmp_receiver.hpp" +#include "include/proxy/mld_receiver.hpp" +#include "include/proxy/timing.hpp" +#include "include/proxy/check_if.hpp" + +#include <linux/mroute.h> +#include <linux/mroute6.h> +#include <sstream> +#include <net/if.h> +#include <fstream> +#include <string> +#include <iostream> +#include <signal.h> + +#include <unistd.h> + +using namespace std; + +bool proxy::m_running= false; + +proxy::proxy(): + m_is_single_instance(true),m_verbose_lvl(0),m_print_status(false), m_rest_rp_filter(false), m_config_path(PROXY_DEFAULT_CONIG_PATH) ,m_addr_family(AF_INET), m_version(2) +{ + HC_LOG_TRACE(""); + + signal(SIGINT,proxy::signal_handler); + signal(SIGTERM,proxy::signal_handler); +} + +proxy::~proxy(){ + HC_LOG_TRACE(""); + + close(); +} + +bool proxy::load_config(string path){ + HC_LOG_TRACE(""); + + ifstream file; + //IF_NAMESIZE + //net/if.h, line 74 + //item ifreq* + char cstr[PROXY_CONFIG_LINE_LENGTH]; + int state=0; //0= look für upstream, 1= look for "==>" 2= look for the first downstream 3= look for additional downstreams + int linecount=0; + + file.open(path.c_str()); + if(!file){ + HC_LOG_ERROR("can't open file: " << path); + return false; + }else{ + file.getline(cstr,sizeof(cstr)); + linecount++; + while(!file.eof()){ + stringstream strline; + string comp_str; + strline << cstr; + + int tmp_upstream_if=-1; + int tmp_downstream_if=-1; + down_vector tmp_down_vector; + + state =0; + if(!strline.eof()){ + do{ + strline >> comp_str; + if(!comp_str.empty() && comp_str.at(0) != '#'){ + + if(comp_str.compare("protocol") == 0) { + if(!strline.eof()){ + strline >> comp_str; + if(comp_str.compare("IGMPv1") == 0){ + m_addr_family=AF_INET; + m_version=1; + }else if(comp_str.compare("IGMPv2") == 0){ + m_addr_family=AF_INET; + m_version=2; + }else if(comp_str.compare("IGMPv3") == 0){ + m_addr_family=AF_INET; + m_version=3; + }else if(comp_str.compare("MLDv1") == 0){ + m_addr_family=AF_INET6; + m_version=1; + }else if(comp_str.compare("MLDv2") == 0){ + m_addr_family=AF_INET6; + m_version=2; + }else{ + HC_LOG_ERROR("unknown protocol: " << comp_str << " <line " << linecount << ">"); + return false; + } + }else{ + HC_LOG_ERROR("unknown protocol " << " <line " << linecount << ">"); + return false; + } + + if(!strline.eof()){ + strline >> comp_str; + if(comp_str.at(0) == '#'){ + while(!strline.eof()){ + strline >> comp_str; + } + }else{ + HC_LOG_ERROR("to much arguments" << " <line " << linecount << ">"); + return false; + } + } + }else if(state==0){ + tmp_upstream_if=if_nametoindex(comp_str.c_str()); + + if(tmp_upstream_if >0){ + state=1; + }else{ + HC_LOG_ERROR("upstream interface not found: " << comp_str << " <line " << linecount << ">"); + return false; + } + + }else if(state==1){ + if(comp_str.compare("==>") == 0){ + state = 2; + }else{ + HC_LOG_ERROR("syntax error: " << comp_str << " expected: " << " ==>" << " <line " << linecount << ">"); + return false; + } + }else if(state==2 || state ==3){ + tmp_downstream_if=if_nametoindex(comp_str.c_str()); + if(tmp_downstream_if >0){ + state =3; + tmp_down_vector.push_back(tmp_downstream_if); + }else{ + HC_LOG_ERROR("downstream interface not found: " << comp_str << " <line " << linecount << ">"); + return false; + } + }else{ + HC_LOG_ERROR("wrong state: " << state); + return false; + } + + + }else{ + break; + } + + }while(!strline.eof()); + } + + if(state == 3){ + m_up_down_map.insert(up_down_pair(tmp_upstream_if,tmp_down_vector)); + }else if (state == 2){ + HC_LOG_ERROR("line incomplete: " << cstr << " in line " << linecount << ">"); + return false; + } + file.getline(cstr,sizeof(cstr)); + } + } + + if(m_up_down_map.size() > 1){ + m_is_single_instance = false; + }else{ + m_is_single_instance = true; + } + + HC_LOG_DEBUG("m_addr_family: " << m_addr_family << "; m_version: " << m_version << "; m_is_single_instance: " << m_is_single_instance << ";"); + return true; +} + +vector<int> proxy::all_if_to_list(){ + HC_LOG_TRACE(""); + + vector<int> interface_list; + + up_down_map::iterator it_up_down; + + for ( it_up_down=m_up_down_map.begin() ; it_up_down != m_up_down_map.end(); it_up_down++ ){ + interface_list.push_back(it_up_down->first); + + down_vector tmp_down_vector =it_up_down->second; + for(unsigned int i=0; i< tmp_down_vector.size();i++){ + interface_list.push_back(tmp_down_vector[i]); + } + } + + return interface_list; +} + +int proxy::get_free_vif_number(){ + HC_LOG_TRACE(""); + + int vifs_elements; + + if(m_addr_family == AF_INET){ + vifs_elements = MAXVIFS; + }else if(m_addr_family == AF_INET6){ + vifs_elements = MAXMIFS; + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return -1; + } + int vifs[vifs_elements]; //index interpreted as vifnumber, contains interpreted as interface index + + //clean the vif memory + memset(vifs,0, sizeof(vifs)); + + //fill vif list + vif_map::iterator iter; + for(iter=m_vif_map.begin(); iter!=m_vif_map.end(); iter++){ + if(iter->second >= vifs_elements){ + HC_LOG_ERROR("wrong vif index"); + return -1; + } + vifs[iter->second] = iter->first; + } + + for(int i=0;i < vifs_elements;i++){ + if(vifs[i] ==0 ){ + return i; + } + } + + HC_LOG_ERROR("no free vif number"); + return -1; +} + +bool proxy::init_vif_map(){ + HC_LOG_TRACE(""); + + vector<int> interface_list = all_if_to_list(); + + int free_vif; + + for(unsigned int i=0; i< interface_list.size(); i++){ + free_vif = get_free_vif_number(); + if(free_vif <0){ + HC_LOG_ERROR("no free vif"); + return false; + } + + m_vif_map.insert(vif_pair(interface_list[i],free_vif)); + + } + + return true; +} + +bool proxy::check_double_used_if(const vector<int>* new_interfaces){ + HC_LOG_TRACE(""); + + vector<int> interface_list = all_if_to_list(); + + //add new if_list to interface_list + if(new_interfaces != NULL){ + for(unsigned int i=0; i< new_interfaces->size();i++){ + interface_list.push_back((*new_interfaces)[i]); + } + } + + while(!interface_list.empty()){ + int tmp_if = interface_list.back(); + interface_list.pop_back(); + for(unsigned int i=0; i< interface_list.size(); i++){ + if(interface_list[i] == tmp_if){ + return false; + } + } + } + + + return true; +} + +string proxy::get_state_table(){ + HC_LOG_TRACE(""); + + up_down_map::iterator it_up_down; + stringstream str; + char cstr[IF_NAMESIZE]; + + str << "protocol: " << endl; + + if(m_addr_family == AF_INET){ + switch(m_version){ + case 1: str << "\tIGMPv1" << endl; break; + case 2: str << "\tIGMPv2" << endl; break; + case 3: str << "\tIGMPv3" << endl; break; + default: str << "\tIPv4 but unknown addr family" << endl; + } + }else if(m_addr_family == AF_INET6){ + switch(m_version){ + case 1: str << "\tMLDv1" << endl; break; + case 2: str << "\tMLDv2" << endl; break; + default: str << "\tIPv6 but unknown addr family" << endl; + } + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + str << "\tunknown IP version" << endl; + } + + str << endl; + + if(m_up_down_map.empty()){ + return "state table is empty"; + } + + for ( it_up_down=m_up_down_map.begin() ; it_up_down != m_up_down_map.end(); it_up_down++ ){ + str << if_indextoname(it_up_down->first, cstr) << " (#" << it_up_down->first << ")" << " ==>" << endl; + + down_vector tmp_down_vector =it_up_down->second; + for(unsigned int i=0; i< tmp_down_vector.size();i++){ + str << "\t" << if_indextoname(tmp_down_vector[i], cstr) << " (#" << tmp_down_vector[i] << ")" << endl; + } + } + return str.str(); +} + +bool proxy::init(int arg_count, char* args[]){ + HC_LOG_TRACE(""); + + if(!prozess_commandline_args(arg_count, args)) return false; + + //admin test + // Check root privilegis + if (geteuid() != 0) { //no root privilegis + HC_LOG_ERROR("The mcproxy has to be started with root privileges!"); + cout << "The mcproxy has to be started with root privileges!" << endl; + return false; + } + + if(!load_config(m_config_path)) return false; + + if(!check_double_used_if(NULL)){ + HC_LOG_ERROR("found double used interface"); + return false; + } + + if(!init_vif_map()) return false; + + if(!init_if_prop()) return false; + + vector<int> if_list=all_if_to_list(); + if(!check_and_set_flags(if_list)) return false; + + //start timing + timing* tim = timing::getInstance(); + tim->start(); + + if(!start_proxy_instances()) return false; + + return true; +} + +void proxy::help_output(){ + HC_LOG_TRACE(""); + cout <<"Usage: mcproxy [-h] [-r] [-d] [-s] [-v [-v]] [-c <configfile>]" << endl; + cout << endl; + cout << "\t-h" << endl; + cout << "\t\tDisplay this help screen." << endl; + + cout << "\t-r" << endl; + cout << "\t\tReset the reverse path filter flag, to accept data from" << endl; + cout << "\t\tforeign Subnets." << endl; + + cout << "\t-d" << endl; + cout << "\t\tRun in debug mode. Output all log messages on thread[X]" << endl; + cout << "\t\tfile." << endl; + + cout << "\t-s" << endl; + cout << "\t\tPrint proxy status information." << endl; + + cout << "\t-v" << endl; + cout << "\t\tBe verbose. Give twice to see even more messages" << endl; + + cout << "\t-c" << endl; + cout << "\t\tTo specify the configuration file." << endl; + +} + +bool proxy::prozess_commandline_args(int arg_count, char* args[]){ + HC_LOG_TRACE(""); + + bool logging = false; + + if(arg_count == 1){ + + }else{ + for (int c; (c = getopt(arg_count, args, "hrdsvc")) != -1;) { + switch (c) { + case 'h': + help_output(); + return false; + break; + case 'r': + m_rest_rp_filter = true; + break; + case 'd': + logging = true; + break; + case 's': + m_print_status = true; + break; + case 'v': + m_verbose_lvl++; + break; + case 'c': + if(args[optind][0] != '-'){ + m_config_path = string(args[optind]); + }else{ + HC_LOG_ERROR("no config path defined"); + cout << "no config path defined" << endl; + return false; + } + break; + default: + HC_LOG_ERROR("Unknown argument! See help (-h) for more information."); + cout << "See help (-h) for more information." << endl; + return false; + break; + } + } + } + + + if(!logging){ + hc_set_default_log_fun(HC_LOG_ERROR_LVL); //no fatal logs defined + }else{ + if(m_verbose_lvl ==0){ + hc_set_default_log_fun(HC_LOG_DEBUG_LVL); + }else if(m_verbose_lvl>=1){ + hc_set_default_log_fun(HC_LOG_TRACE_LVL); + }else{ + HC_LOG_ERROR("Unknown verbose level: " << m_verbose_lvl); + return false; + } + } + + return true; + +} + +bool proxy::start_proxy_instances(){ + HC_LOG_TRACE(""); + + proxy_msg msg; + up_down_map::iterator it_up_down; + vif_map::iterator it_vif; + int upstream_vif; + int downstream_vif; + + + for ( it_up_down=m_up_down_map.begin() ; it_up_down != m_up_down_map.end(); it_up_down++ ){ + down_vector tmp_down_vector =it_up_down->second; + + proxy_instance* p= new proxy_instance(); + m_proxy_instances.push_back(p); + + if((it_vif = m_vif_map.find(it_up_down->first)) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << it_up_down->first); + return false; + } + upstream_vif = it_vif->second; + + if((it_vif = m_vif_map.find(tmp_down_vector[0])) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << tmp_down_vector[0]); + return false; + } + downstream_vif = it_vif->second; + + //start proxy instance + if(!p->init(m_addr_family,m_version,it_up_down->first, upstream_vif, tmp_down_vector[0], downstream_vif, m_is_single_instance)){ + return false; + } + + p->start(); + + + //add upstream and first downstream + m_interface_map.insert(interface_pair(it_up_down->first,m_proxy_instances.size()-1)); + m_interface_map.insert(interface_pair(tmp_down_vector[0],m_proxy_instances.size()-1)); + + //add downstream + for(unsigned int i=1; i <tmp_down_vector.size();i++){ + msg.type = proxy_msg::CONFIG_MSG; + + if((it_vif = m_vif_map.find(tmp_down_vector[i])) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << tmp_down_vector[0]); + return false; + } + downstream_vif = it_vif->second; + msg.msg = new config_msg(config_msg::ADD_DOWNSTREAM, tmp_down_vector[i], downstream_vif); + p->add_msg(msg); + m_interface_map.insert(interface_pair(tmp_down_vector[i],m_proxy_instances.size()-1)); + } + } + + return true; +} + +bool proxy::init_if_prop(){ + HC_LOG_TRACE(""); + + if(!m_if_prop.refresh_network_interfaces()) return false; + + return true; +} + +bool proxy::check_and_set_flags(vector<int>& interface_list){ + HC_LOG_TRACE(""); + + char cstr[IF_NAMESIZE]; + const if_prop_map* prop_map = m_if_prop.get_if_props(); + + //##debug + //m_if_prop.print_if_info(); + + if_prop_map::const_iterator iter; + const struct ifaddrs* ifaddr; + + for(unsigned int i=0; i< interface_list.size(); i++){ + string if_name(if_indextoname(interface_list[i],cstr)); + + iter = prop_map->find(if_name); + + if(iter == prop_map->end()){ + HC_LOG_ERROR("interface " << if_name << " not found"); + return false; + } + + if(m_addr_family == AF_INET){ + if(iter->second.ip4_addr != NULL){ + ifaddr = iter->second.ip4_addr; + }else{ + HC_LOG_ERROR("interface " << if_name << " don't support ipv4"); + return false; + } + }else if(m_addr_family == AF_INET6){ + const list<const struct ifaddrs*>* ipv6_if_list = &(iter->second.ip6_addr); + if(ipv6_if_list->size() != 0){ + ifaddr = *(ipv6_if_list->begin()); + }else{ + HC_LOG_ERROR("interface " << if_name << " don't support ipv6"); + return false; + } + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + if(!(ifaddr->ifa_flags & IFF_UP)){ + HC_LOG_ERROR("wrong interface status: interface " << if_name << " is not up"); + return false; + } + + //reset rp_filter for every used interface + if(m_rest_rp_filter){ + if(get_rp_filter(if_name)){ + if(set_rp_filter(if_name, false)){ + m_restore_rp_filter_vector.push_back(if_name); + }else{ + return false; + } + } + } + } + + //reset global rp_filter + if(m_rest_rp_filter){ + string global_if = "all"; + if(get_rp_filter(global_if)){ + if(set_rp_filter(global_if, false)){ + m_restore_rp_filter_vector.push_back(global_if); + }else{ + return false; + } + } + } + + return true; +} + +bool proxy::restore_rp_filter(){ + HC_LOG_TRACE(""); + bool state = true; + + for(vector<string>::iterator iter= m_restore_rp_filter_vector.begin(); iter!= m_restore_rp_filter_vector.end(); iter++){ + if(!set_rp_filter(*iter,true)){ + state = false; + } + } + + return state; +} + +bool proxy::get_rp_filter(string interface){ + HC_LOG_TRACE(""); + stringstream path; + bool state; + path << PROXY_RP_FILTER_PATH << interface << "/rp_filter"; + + ifstream is(path.str().c_str(), ios::binary|ios::in); + if(!is){ + HC_LOG_ERROR("failed to open file:" << path); + return false; + }else{ + state = is.get(); + } + is.close(); + + return state; +} + +bool proxy::set_rp_filter(string interface, bool to){ + HC_LOG_TRACE(""); + stringstream path; + path << PROXY_RP_FILTER_PATH << interface << "/rp_filter"; + + ofstream os(path.str().c_str(), ios::binary|ios::out); + if(!os){ + HC_LOG_ERROR("failed to open file:" << path << " and set rp_filter to " << to); + return false; + }else{ + if(to){ + os.put('1'); + }else{ + os.put('0'); + } + } + os.flush(); + os.close(); + return true; +} + +bool proxy::start(){ + HC_LOG_TRACE(""); + + vif_map::iterator it_vif; + interface_map::iterator it_proxy_numb; + proxy_msg msg; + + //check_if init + check_if check_interface; + vector<int> if_list_tmp; + up_down_map::iterator it_up_down; + + for(it_up_down=m_up_down_map.begin() ; it_up_down != m_up_down_map.end(); it_up_down++){ + down_vector tmp_down_vector =it_up_down->second; + for(unsigned int i=0; i< tmp_down_vector.size();i++){ + if_list_tmp.push_back(tmp_down_vector[i]); + } + } + + //init status + //del all down interfaces + if_list_tmp = check_interface.init(if_list_tmp, m_addr_family); + for(vector<int>::iterator i= if_list_tmp.begin(); i != if_list_tmp.end(); i++){ + if((it_vif = m_vif_map.find(*i)) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << *i); + return false; + } + + if((it_proxy_numb = m_interface_map.find(*i)) == m_interface_map.end()){ + HC_LOG_ERROR("failed to find proxy instance form if_index: " << *i); + return false; + } + + msg.msg = new config_msg(config_msg::DEL_DOWNSTREAM,*i, it_vif->second); + m_proxy_instances[it_proxy_numb->second]->add_msg(msg); + } + + + //################################# + int alive_time=0; + proxy::m_running = true; + while(proxy::m_running){ + + usleep(4000000); + alive_time +=1; + + if(m_print_status){ + debug_msg::lod lod; + if(m_verbose_lvl==0){ + lod =debug_msg::NORMAL; + }else if(m_verbose_lvl==1){ + lod = debug_msg::MORE; + }else if(m_verbose_lvl>=2){ + lod = debug_msg::MORE_MORE; + } + + cout << "alvie time: " << alive_time << endl; + + msg.type = proxy_msg::DEBUG_MSG; + msg.msg = new debug_msg(lod, m_proxy_instances.size(),PROXY_DEBUG_MSG_TIMEOUT); + + for(unsigned int i=0; i< m_proxy_instances.size(); i++){ + m_proxy_instances[i]->add_msg(msg); + } + + debug_msg* dm = (debug_msg*)msg.msg.get(); + dm->join_debug_msg(); + cout << dm->get_debug_msg() << endl; + } + + check_interface.check(); + //calc swap_to_down interfaces + if_list_tmp = check_interface.swap_to_down(); + for(vector<int>::iterator i= if_list_tmp.begin(); i < if_list_tmp.end(); i++){ + if((it_vif = m_vif_map.find(*i)) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << *i); + return false; + } + + if((it_proxy_numb = m_interface_map.find(*i)) == m_interface_map.end()){ + HC_LOG_ERROR("failed to find proxy instance form if_index: " << *i); + return false; + } + + msg.type = proxy_msg::CONFIG_MSG; + msg.msg = new config_msg(config_msg::DEL_DOWNSTREAM,*i, it_vif->second); + m_proxy_instances[it_proxy_numb->second]->add_msg(msg); + } + + //calc swap_to_up interfaces + if_list_tmp = check_interface.swap_to_up(); + for(vector<int>::iterator i= if_list_tmp.begin(); i < if_list_tmp.end(); i++){ + if((it_vif = m_vif_map.find(*i)) == m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif form if_index: " << *i); + return false; + } + + if((it_proxy_numb = m_interface_map.find(*i)) == m_interface_map.end()){ + HC_LOG_ERROR("failed to find proxy instance form if_index: " << *i); + return false; + } + + msg.type = proxy_msg::CONFIG_MSG; + msg.msg = new config_msg(config_msg::ADD_DOWNSTREAM,*i, it_vif->second); + m_proxy_instances[it_proxy_numb->second]->add_msg(msg); + } + } + + + + return true; +} + +void proxy::signal_handler(int sig){ + HC_LOG_TRACE(""); + + //HC_LOG_DEBUG("Signale: " << sys_siglist[sig] << " received"); + proxy::m_running = false; +} + + +void proxy::stop(){ + HC_LOG_TRACE(""); + + proxy_msg m; + m.type = proxy_msg::EXIT_CMD; + + HC_LOG_DEBUG("kill worker thread proxy_instance"); + for(unsigned int i=0; i< m_proxy_instances.size(); i++){ + m_proxy_instances[i]->add_msg(m); + } + + for(unsigned int i=0; i< m_proxy_instances.size(); i++){ + HC_LOG_DEBUG("join worker thread proxy_instance."); + m_proxy_instances[i]->join(); + HC_LOG_DEBUG("joined."); + delete m_proxy_instances[i]; + } + + timing* tim= timing::getInstance(); + tim->stop(); + tim->join(); + +} + +void proxy::close(){ + HC_LOG_TRACE(""); + + restore_rp_filter(); +} diff --git a/mcproxy/src/proxy/proxy_instance.cpp b/mcproxy/src/proxy/proxy_instance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e7b9e68a734000326b90047641034bd1dcbdffb --- /dev/null +++ b/mcproxy/src/proxy/proxy_instance.cpp @@ -0,0 +1,1132 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/proxy_instance.hpp" +#include "include/utils/mc_timers_values.hpp" +#include "include/proxy/igmp_receiver.hpp" +#include "include/proxy/mld_receiver.hpp" + +#include <net/if.h> +#include <sstream> + +proxy_instance::proxy_instance(): + worker(PROXY_INSTANCE_MSG_QUEUE_SIZE), m_is_single_instance(true), m_table_number(-1), m_upstream(0), m_addr_family(-1), m_version(-1) +{ + HC_LOG_TRACE(""); + +} + +proxy_instance::~proxy_instance(){ + HC_LOG_TRACE(""); + close(); +} + +bool proxy_instance::init(int addr_family, int version, int upstream_index, int upstream_vif, int downstream_index, int downstram_vif, bool single_instance){ + HC_LOG_TRACE(""); + + m_is_single_instance = single_instance; + m_addr_family = addr_family; + m_version = version; + + m_upstream = upstream_index; + m_table_number = upstream_index; + m_vif_map.insert(vif_pair(upstream_index,upstream_vif)); + + m_state_table.insert(state_tabel_pair(downstream_index, g_state_map())); + m_vif_map.insert(vif_pair(downstream_index, downstram_vif)); + + if(!init_mrt_socket()) return false; + + m_check_source.init(m_addr_family, &m_mrt_sock); + + if(!init_receiver()) return false; + + if(!init_sender()) return false; + + m_routing.init(m_addr_family,m_version, &m_mrt_sock, m_is_single_instance, m_table_number); + + m_timing = timing::getInstance(); + + return true; +} + +bool proxy_instance::init_receiver(){ + HC_LOG_TRACE(""); + + if(m_addr_family == AF_INET){ + m_receiver = new igmp_receiver(); + }else if(m_addr_family == AF_INET6){ + m_receiver = new mld_receiver(); + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + if(!m_receiver->init(m_addr_family,m_version, &m_mrt_sock)) return false; + m_receiver->start(); + + return true; +} + +bool proxy_instance::init_mrt_socket(){ + HC_LOG_TRACE(""); + + if(m_addr_family == AF_INET){ + m_mrt_sock.create_raw_ipv4_socket(); + }else if(m_addr_family == AF_INET6){ + m_mrt_sock.create_raw_ipv6_socket(); + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + if(!m_is_single_instance){ + if(!m_mrt_sock.set_kernel_table(m_upstream)){ + return false; + }else{ + HC_LOG_DEBUG("proxy instance: " << m_upstream); + } + } + + if(!m_mrt_sock.set_mrt_flag(true)) return false; + + return true; +} + +bool proxy_instance::init_sender(){ + HC_LOG_TRACE(""); + + if(m_addr_family == AF_INET){ + m_sender = new igmp_sender; + }else if(m_addr_family == AF_INET6){ + m_sender = new mld_sender; + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + if(!m_sender->init(m_addr_family,m_version)) return false; + + return true; +} + +void proxy_instance::worker_thread(){ + HC_LOG_TRACE(""); + + proxy_msg m; + state_table_map::iterator it_state_table; + + //##-- add all interfaces --## + //upsteam + registrate_if(m_upstream); + //downsteams (only one) + for ( it_state_table=m_state_table.begin() ; it_state_table != m_state_table.end(); it_state_table++ ){ + registrate_if(it_state_table->first); + } + + //##-- general query --## + //nach registrate_if ausgelagert + //send_gq_to_all(); + + //##-- initiate GQ timer --## + m.type = proxy_msg::CLOCK_MSG; + m.msg = new struct clock_msg(clock_msg::SEND_GQ_TO_ALL); + m_timing->add_time(MC_TV_QUERY_INTERVAL*1000 /*msec*/,this,m); + + //##-- thread working loop --## + while(m_running){ + m = m_job_queue.dequeue(); + HC_LOG_DEBUG("received new job. type: " << m.msg_type_to_string()); + switch(m.type){ + case proxy_msg::TEST_MSG: { + struct test_msg* t= (struct test_msg*) m.msg.get(); + t->test(); + break; + } + case proxy_msg::RECEIVER_MSG: { + struct receiver_msg* t= (struct receiver_msg*) m.msg.get(); + handle_igmp(t); + break; + } + case proxy_msg::CLOCK_MSG: { + struct clock_msg* t = (struct clock_msg*) m.msg.get(); + handle_clock(t); + break; + } + case proxy_msg::CONFIG_MSG: { + struct config_msg* t = (struct config_msg*) m.msg.get(); + handle_config(t); + break; + } + case proxy_msg::DEBUG_MSG: { + struct debug_msg* t = (struct debug_msg*) m.msg.get(); + handle_debug_msg(t); + break; + } + + case proxy_msg::EXIT_CMD: m_running = false; break; + default: HC_LOG_ERROR("unknown message format"); + } + } + + //##-- timing --## + //remove all running times + m_timing->stop_all_time(this); + + //##-- del all interfaces --## + //upsteam + unregistrate_if(m_upstream); + //downsteams + for ( it_state_table=m_state_table.begin() ; it_state_table != m_state_table.end(); it_state_table++ ){ + unregistrate_if(it_state_table->first); + } + + HC_LOG_DEBUG("worker thread proxy_instance end"); +} + +void proxy_instance::handle_igmp(struct receiver_msg* r){ + HC_LOG_TRACE(""); + + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_state_map::iterator iter_src; + src_group_state_pair* sgs_pair; + proxy_msg msg; + + switch(r->type){ + case receiver_msg::JOIN: { + //upstream joins are uninteresting + if(r->if_index == m_upstream) return; + + iter_table =m_state_table.find(r->if_index); + if(iter_table == m_state_table.end()) return; + + iter_state = iter_table->second.find(r->g_addr); + + if(iter_state == iter_table->second.end()){ //add group + struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::RUNNING); + iter_table->second.insert(g_state_pair(r->g_addr,src_group_state_pair(src_state_map(), tmp_state))); + + //--refresh upstream + if(!is_group_joined(r->if_index,r->g_addr)){ + if(!m_sender->send_report(m_upstream, r->g_addr)){ + HC_LOG_ERROR("failed to join on upstream group: " << r->g_addr); + return; + } + } + + //--refresh routing + refresh_all_traffic(r->if_index, r->g_addr); + + }else{ //refresh group + sgs_pair = &iter_state->second; + sgs_pair->second.robustness_counter = MC_TV_ROBUSTNESS_VARIABLE; + sgs_pair->second.flag = src_state::RUNNING; + } + + break; + } + case receiver_msg::LEAVE:{ + //cout << "leave an if: " << r->if_index << " für gruppe:" << r->g_addr << " empfangen" << endl; + //upstream leaves are uninteresting + if(r->if_index == m_upstream) return; + + iter_table =m_state_table.find(r->if_index); + if(iter_table == m_state_table.end()) return; + + iter_state = iter_table->second.find(r->g_addr); + if(iter_state == iter_table->second.end()) return; + sgs_pair = &iter_state->second; + + sgs_pair->second.flag = src_state::RESPONSE_STATE; + + msg.type = proxy_msg::CLOCK_MSG; + msg.msg = new struct clock_msg(clock_msg::SEND_GSQ, iter_table->first, iter_state->first); + + if(m_addr_family == AF_INET){ + sgs_pair->second.robustness_counter = MC_TV_LAST_MEMBER_QUERY_COUNT; + + m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); + }else if(m_addr_family== AF_INET6){ + sgs_pair->second.robustness_counter = MC_TV_LAST_LISTENER_QUERY_COUNT; + + m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return; + } + + break; + } + case receiver_msg::CACHE_MISS: { + if(r->if_index == m_upstream){ + upstream_src_state_map::iterator it_gss = m_upstream_state.find(r->g_addr); + if(it_gss == m_upstream_state.end()){ //new group found + struct src_state tmp_src_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); + src_state_map tmp_src_state_map; + tmp_src_state_map.insert(src_state_pair(r->src_addr,tmp_src_state)); + m_upstream_state.insert(upstream_src_state_pair(r->g_addr,tmp_src_state_map)); + }else{ // insert in existing group + iter_src = it_gss->second.find(r->src_addr); + if(iter_src == it_gss->second.end()){ //new src addr + struct src_state tmp_src_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); + it_gss->second.insert(src_state_pair(r->src_addr,tmp_src_state)); + }else{ //src exist + HC_LOG_DEBUG("kernel msg with src: " << r->src_addr << " received, this source address exist for if_index: " << r->if_index << " and group:" << r->g_addr << " because it's normaly not joined on a downstream interface"); + return; + } + } + + //refresh routing + if(split_traffic(r->if_index, r->g_addr, r->src_addr)){ + // versetzt nach split traffic + // upstream_src_state_map::iterator it_gss = m_upstream_state.find(r->g_addr); + // if(it_gss == m_upstream_state.end()){ + // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find upstream g_addr:" << r->g_addr); + // return; + // } + // iter_src = it_gss->second.find(r->src_addr); + // if(iter_src == it_gss->second.end()){ + // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << r->g_addr << " the source:" << r->src_addr); + // return; + // } + // iter_src->second.flag = src_state::CACHED_SRC; + } + + }else{ //downstream cache miss + iter_table =m_state_table.find(r->if_index); + if(iter_table == m_state_table.end()) return; + + iter_state = iter_table->second.find(r->g_addr); + if(iter_state == iter_table->second.end()) { //new group found + struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); + struct src_state tmp_state_group; + src_state_map tmp_src_state_map; + tmp_src_state_map.insert(src_state_pair(r->src_addr,tmp_state)); + iter_table->second.insert(g_state_pair(r->g_addr, src_group_state_pair(tmp_src_state_map, tmp_state_group))); + }else{ //insert in existing group + sgs_pair = &iter_state->second; + + iter_src = sgs_pair->first.find(r->src_addr); + if(iter_src == sgs_pair->first.end()){ //new src found, add to list + struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); + sgs_pair->first.insert(src_state_pair(r->src_addr,tmp_state)); + }else{ //error old src found + HC_LOG_ERROR("kernel msg with src: " << r->src_addr << " received, this source address exist for if_index: " << r->if_index << " and group:" << r->g_addr); + return; + } + } + + //refresh routing + if(split_traffic(r->if_index, r->g_addr, r->src_addr)){ + // versetzt nach split traffic + // iter_state = iter_table->second.find(r->g_addr); + // if(iter_state == iter_table->second.end()) { + // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find downstream g_addr:" << r->g_addr); + // return; + // } + // sgs_pair = &iter_state->second; + // iter_src = sgs_pair->first.find(r->src_addr); + // if(iter_state == iter_table->second.end()) { + // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << r->g_addr << " the source:" << r->src_addr); + // return; + // } + // iter_src->second.flag = src_state::CACHED_SRC; + } + + } + break; + } + default: HC_LOG_ERROR("unknown receiver messge format"); + } +} + +void proxy_instance::handle_clock(struct clock_msg* c){ + HC_LOG_TRACE(""); + + proxy_msg msg; + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_state_map::iterator iter_src; + src_group_state_pair* sgs_pair = NULL; + + + switch(c->type){ + case clock_msg::SEND_GQ_TO_ALL: { + //send GQ + send_gq_to_all(); + + m_check_source.check(); //reloade routing table + + //##-- dekrement all counter of all groups on all downstream interfaces in RUNNING state --## + //##-- and dekrement all counter of all groups source addresses --## + vector<addr_storage> tmp_erase_group_vector; //if group not joined and all sources are deleted + for(iter_table= m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ + + for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ + sgs_pair = &iter_state->second; + + //-- process groups in RUNNING state -- + if( sgs_pair->second.flag == src_state::RUNNING){ + //if counter == 0 delete this group after query response + if(--sgs_pair->second.robustness_counter == 0){ + sgs_pair->second.flag= src_state::WAIT_FOR_DEL; + sgs_pair->second.robustness_counter = PROXY_INSTANCE_DEL_IMMEDIATELY; + + msg.type = proxy_msg::CLOCK_MSG; + msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); + m_timing->add_time(MC_TV_QUERY_RESPONSE_INTERVAL*1000 /*msec*/,this,msg); + } + } + + + //-- process sources in FOREIGN_SRC state -downstream- -- + vector<addr_storage> tmp_erase_source_vector; + for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ + if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ + //del unused sources + vif_map::iterator it_vif_map; + if((it_vif_map = m_vif_map.find(iter_table->first)) == m_vif_map.end()){ + HC_LOG_ERROR("cant find vif to if_index:" << iter_table->first); + } + + if(m_check_source.is_src_unused(it_vif_map->second, iter_src->first, iter_state->first)){ + iter_src->second.robustness_counter--; + }else{ + iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; + } + + if(iter_src->second.robustness_counter == 0){ + //save invalid sources + tmp_erase_source_vector.push_back(iter_src->first); + + //refresh routing + if(iter_src->second.flag == src_state::CACHED_SRC){ + del_route(iter_table->first, iter_state->first, iter_src->first); + } + + } + }else{ + HC_LOG_ERROR("downstream source is in unknown state: " << iter_src->second.state_type_to_string()); + } + } + //erase invalid sources + for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ + if((iter_src = sgs_pair->first.find(tmp_erase_source_vector[i]))!= sgs_pair->first.end()){ + sgs_pair->first.erase(iter_src); + }else{ + HC_LOG_ERROR("cant find invalid downstream soruce: " << tmp_erase_source_vector[i]); + } + } + + //if group has no sources and is not joined (flag=INIT) remove the group + if(sgs_pair->first.size() == 0){ + if(sgs_pair->second.flag == src_state::INIT){ + tmp_erase_group_vector.push_back(iter_state->first); + } + } + + + } + //erase unused groups + for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ + if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ + iter_table->second.erase(iter_state); + + }else{ + HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); + } + } + tmp_erase_group_vector.clear(); + + } + + + + //-- process sources in FOREIGN_SRC state -upstream- -- + upstream_src_state_map::iterator tmp_it_up_ss_map; + src_state_map* tmp_ss_map; + tmp_erase_group_vector.clear(); //unused groups + for(tmp_it_up_ss_map = m_upstream_state.begin(); tmp_it_up_ss_map != m_upstream_state.end(); tmp_it_up_ss_map++){ + + tmp_ss_map = &tmp_it_up_ss_map->second; + vector<addr_storage> tmp_erase_source_vector; + for(iter_src = tmp_ss_map->begin(); iter_src != tmp_ss_map->end(); iter_src++){ + // if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ + + // //del old sources + // if(--iter_src->second.robustness_counter == 0){ + // //save invalid sources + // tmp_erase_source_vector.push_back(iter_src->first); + + // //refresh routing + // if(iter_src->second.flag == src_state::CACHED_SRC){ + // del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); + // } + + // } + // }else{ + // HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); + // } + + if(iter_src->second.flag == src_state::UNUSED_SRC){ + + //del old sources + if(--iter_src->second.robustness_counter == 0){ + //save invalid sources + tmp_erase_source_vector.push_back(iter_src->first); + } + }else if(iter_src->second.flag == src_state::CACHED_SRC){ + + if(m_check_source.is_src_unused(m_upstream, iter_src->first, tmp_it_up_ss_map->first)){ + if(--iter_src->second.robustness_counter == 0){ + //save invalid sources + tmp_erase_source_vector.push_back(iter_src->first); + + del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); + } + + }else{ + iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; + } + + + }else{ + HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); + } + + + } + //erase invalid sources + for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ + if((iter_src = tmp_ss_map->find(tmp_erase_source_vector[i])) != tmp_ss_map->end()){ + tmp_ss_map->erase(iter_src); + }else{ + HC_LOG_ERROR("cant find invalid upstream soruce: " << tmp_erase_source_vector[i]); + } + } + + //if group has no sources remove the group + if(tmp_it_up_ss_map->second.size() == 0){ + tmp_erase_group_vector.push_back(tmp_it_up_ss_map->first); + } + + } + //erase unused groups + for(unsigned int i=0; i < tmp_erase_group_vector.size(); i++){ + tmp_it_up_ss_map = m_upstream_state.find(tmp_erase_group_vector[i]); + if(tmp_it_up_ss_map != m_upstream_state.end()){ + m_upstream_state.erase(tmp_it_up_ss_map); + }else{ + HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); + } + } + + //initiate new GQ + msg.type = proxy_msg::CLOCK_MSG; + msg.msg = new struct clock_msg(clock_msg::SEND_GQ_TO_ALL); + m_timing->add_time(MC_TV_QUERY_INTERVAL*1000 /*msec*/,this,msg); + break; + } + case clock_msg::SEND_GSQ: { + iter_table =m_state_table.find(c->if_index); + if(iter_table == m_state_table.end()) return; + + iter_state = iter_table->second.find(c->g_addr); + if(iter_state == iter_table->second.end()) return; + + sgs_pair = &iter_state->second; + if(sgs_pair->second.flag == src_state::RESPONSE_STATE){ + m_sender->send_group_specific_query(c->if_index,c->g_addr); + + if(--sgs_pair->second.robustness_counter == PROXY_INSTANCE_DEL_IMMEDIATELY){ + sgs_pair->second.flag = src_state::WAIT_FOR_DEL; + + msg.type = proxy_msg::CLOCK_MSG; + msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); + if(m_addr_family == AF_INET){ + m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); + }else if(m_addr_family == AF_INET6){ + m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return; + } + }else{ + msg.type = proxy_msg::CLOCK_MSG; + msg.msg = new struct clock_msg(clock_msg::SEND_GSQ, iter_table->first, iter_state->first); + + if(m_addr_family == AF_INET){ + m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); + }else if(m_addr_family== AF_INET6){ + m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return; + } + } + } + break; + } + case clock_msg::DEL_GROUP:{ + iter_table =m_state_table.find(c->if_index); + if(iter_table == m_state_table.end()) return; + + iter_state = iter_table->second.find(c->g_addr); + if(iter_state == iter_table->second.end()) return; + + sgs_pair = &iter_state->second; + if(sgs_pair->second.flag == src_state::WAIT_FOR_DEL){ + HC_LOG_DEBUG("DEL_GROUP if_index: " << c->if_index << " group: " << c->g_addr); + + //refresh upstream + if(!is_group_joined(c->if_index,c->g_addr)){ + if(!m_sender->send_leave(m_upstream, c->g_addr)){ + HC_LOG_ERROR("failed to leave on upstream group: " << c->g_addr); + } + } + + //del only if no FOREIGN_SRC available + if(sgs_pair->first.size() == 0){ + iter_table->second.erase(iter_state); + }else{ //set groupstate to INIT + sgs_pair->second.flag = src_state::INIT; + } + + //refresh routing + //cout << "in del group: refresh_all_traffic()..." << endl; + refresh_all_traffic(c->if_index, c->g_addr); + } + + break; + } + case clock_msg::SEND_GQ: break; //start up Query Interval vor new interfaces + default: HC_LOG_ERROR("unknown clock message foramt"); + } +} + +void proxy_instance::handle_config(struct config_msg* c){ + HC_LOG_TRACE(""); + + switch(c->type){ + case config_msg::ADD_DOWNSTREAM: { + + //if interface exist + if(m_state_table.find(c->if_index) != m_state_table.end()){ + HC_LOG_ERROR("failed to add downstream, interface " << c->if_index << " allready exist"); + } + + m_state_table.insert(state_tabel_pair(c->if_index,g_state_map())); + m_vif_map.insert(vif_pair(c->if_index,c->vif)); + registrate_if(c->if_index); + break; + } + case config_msg::DEL_DOWNSTREAM: { + //if interface exist + if(m_state_table.find(c->if_index) == m_state_table.end()){ + HC_LOG_ERROR("failed to del downstream, interface " << c->if_index << " not exist"); + } + + unregistrate_if(c->if_index); + + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_group_state_pair* sgs_pair = NULL; + src_state_map::iterator iter_src; + + iter_table =m_state_table.find(c->if_index); + if(iter_table == m_state_table.end()) { + HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); + return; + } + + vector<addr_storage> tmp_erase_group_vector; + for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ + sgs_pair = &iter_state->second; + + //remove all own sources (routes) + for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ + if(iter_src->second.flag == src_state::CACHED_SRC){ + del_route(iter_table->first, iter_state->first, iter_src->first); + } + } + + //save all groups for remove + tmp_erase_group_vector.push_back(iter_state->first); + + //refresh upstream + if(!is_group_joined(c->if_index,iter_state->first)){ + if(!m_sender->send_leave(m_upstream, iter_state->first)){ + HC_LOG_ERROR("failed to leave on upstream group: " << iter_state->first); + } + } + } + + //erase all groups + for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ + if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ + iter_table->second.erase(iter_state); + + //calculate the joined group roles + refresh_all_traffic(c->if_index, tmp_erase_group_vector[i]); + }else{ + HC_LOG_ERROR("cant find downstream group: " << tmp_erase_group_vector[i]);} + + } + + //clean state table + m_state_table.erase(iter_table); + + //clean vif map + vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); + if(it_vif_map == m_vif_map.end()) { + HC_LOG_ERROR("faild to del downstream: cant find vif to if_index: " << c->if_index); + return; + } + m_vif_map.erase(it_vif_map); + + //HC_LOG_ERROR("del downstream not implementeted"); + break; + } + case config_msg::SET_UPSTREAM: { + + //remove current upstream + unregistrate_if(c->if_index); + + vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); + if(it_vif_map == m_vif_map.end()) { + HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); + return; + } + m_vif_map.erase(it_vif_map); + + //ToDo + //refresh routes????????????????????????????????? + HC_LOG_ERROR("set upstream not implementeted"); + + + //set new upstream + m_upstream = c->if_index; + m_vif_map.insert(vif_pair(c->if_index,c->vif)); + registrate_if(c->if_index); + + break; + } + default: HC_LOG_ERROR("unknown config message format"); + } +} + +void proxy_instance::handle_debug_msg(struct debug_msg* db){ + HC_LOG_TRACE(""); + std::stringstream str; + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_state_map::iterator iter_src_state; + vif_map::iterator iter_vif; + + upstream_src_state_map::iterator iter_up_src_state; + + + char cstr[IF_NAMESIZE]; + string if_name(if_indextoname(m_upstream,cstr)); + + if((iter_vif = m_vif_map.find(m_upstream))== m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif to upstream if_index:" << m_upstream); + return; + } + str << "##-- instance upstream " << if_name << " [vif=" << iter_vif->second<< "] --##" << endl; + + if(db->get_level_of_detail() > debug_msg::LESS){ + + if(db->get_level_of_detail() > debug_msg::NORMAL){ + //upstream output + str << "\tgroup addr" << endl; + + int tmp_g_counter=0; + for(iter_up_src_state= m_upstream_state.begin(); iter_up_src_state !=m_upstream_state.end(); iter_up_src_state++){ + src_state_map* tmp_src_state_map = &iter_up_src_state->second; + str << "\t[" << tmp_g_counter++ << "] " <<iter_up_src_state->first << "\t" << endl; + + int tmp_s_counter=0; + if(db->get_level_of_detail() > debug_msg::MORE){ + if(tmp_src_state_map->size()>0 ){ + str << "\t\tsrc addr | robustness_counter | flag" << endl; + for(iter_src_state = tmp_src_state_map->begin(); iter_src_state != tmp_src_state_map->end(); iter_src_state++){ + str << "\t\t[" << tmp_s_counter++ << "] " << iter_src_state->first << "\t" << iter_src_state->second.robustness_counter << "\t" << iter_src_state->second.state_type_to_string() << endl; + } + } + } + } + str << endl; + + } + + //downstream output + for(iter_table= m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ + if_name = if_indextoname(iter_table->first,cstr); + + if((iter_vif = m_vif_map.find(iter_table->first))== m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif to downstream if_index:" << iter_table->first); + return; + } + + str << "\t-- downstream " << if_name << " [vif=" << iter_vif->second << "] --" << endl; + + if(db->get_level_of_detail() > debug_msg::NORMAL){ + + str << "\t\tgroup addr | robustness_counter | flag" << endl; + + int tmp_g_counter=0; + for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ + src_group_state_pair* tmp_gsp = &iter_state->second; + str << "\t\t[" << tmp_g_counter++ << "] " <<iter_state->first << "\t" << tmp_gsp->second.robustness_counter << "\t" << tmp_gsp->second.state_type_to_string() << endl; + + int tmp_s_counter=0; + if(db->get_level_of_detail() > debug_msg::MORE){ + if(tmp_gsp->first.size()>0 ){ + str << "\t\t\tsrc addr | robustness_counter | flag" << endl; + for(iter_src_state = tmp_gsp->first.begin(); iter_src_state != tmp_gsp->first.end(); iter_src_state++){ + str << "\t\t\t[" << tmp_s_counter++ << "] " << iter_src_state->first << "\t" << iter_src_state->second.robustness_counter << "\t" << iter_src_state->second.state_type_to_string() << endl; + } + } + } + } + str << endl; + + } + } + } + + db->add_debug_msg(str.str()); +} + +bool proxy_instance::send_gq_to_all(){ + HC_LOG_TRACE(""); + HC_LOG_DEBUG("send general query to all"); + bool correct= true; + + state_table_map::iterator it_state_table; + for(it_state_table= m_state_table.begin(); it_state_table != m_state_table.end(); it_state_table++){ + if(!m_sender->send_general_query(it_state_table->first)){ + HC_LOG_ERROR("failed to send general to if_index: " << it_state_table->first); + correct = false; + } + } + + return correct; +} + +bool proxy_instance::split_traffic(int if_index, const addr_storage& g_addr, const addr_storage& src_addr){ + HC_LOG_TRACE(""); + proxy_msg msg; + std::list<int> vif_list; + + vif_map::iterator it_vif_map = m_vif_map.find(if_index); + if(it_vif_map == m_vif_map.end()){ + HC_LOG_ERROR("cant find vif to if_index:" << if_index); + return false; + } + int vif = it_vif_map->second; + //cout << "vif vom source interface: " << vif << endl; + + //find all downstream interaces who join this group and if if_index is not a upstream add upstream vif + add_all_group_vifs_to_list(&vif_list, if_index, g_addr); + //cout << "split_traffic: haben wieviele vifs gefunden: " << vif_list.size() << endl; + if(vif_list.size() == 0) return false; //if nobody join this group ignore + + m_routing.add_route(vif, g_addr, src_addr, vif_list); + + //set source to flag CACHED_SRC + if(if_index == m_upstream){ //upstream source + upstream_src_state_map::iterator it_gss = m_upstream_state.find(g_addr); + if(it_gss == m_upstream_state.end()){ + HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find upstream g_addr:" << g_addr); + return false; + } + src_state_map::iterator iter_src = it_gss->second.find(src_addr); + if(iter_src == it_gss->second.end()){ + HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << g_addr << " the source:" << src_addr); + return false; + } + iter_src->second.flag = src_state::CACHED_SRC; + }else{ //downstream source + state_table_map::iterator iter_table =m_state_table.find(if_index); + if(iter_table == m_state_table.end()) return false; + + g_state_map::iterator iter_state = iter_table->second.find(g_addr); + if(iter_state == iter_table->second.end()) { + HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find downstream g_addr:" << g_addr); + return false; + } + src_group_state_pair* sgs_pair = &iter_state->second; + src_state_map::iterator iter_src = sgs_pair->first.find(src_addr); + if(iter_state == iter_table->second.end()) { + HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << g_addr << " the source:" << src_addr); + return false; + } + iter_src->second.flag = src_state::CACHED_SRC; + } + + return true; +} + +bool proxy_instance::del_route(int if_index, const addr_storage& g_addr, const addr_storage& src_addr){ + HC_LOG_TRACE(""); + + vif_map::iterator it_vif_map = m_vif_map.find(if_index); + if(it_vif_map == m_vif_map.end()){ + HC_LOG_ERROR("cant find vif to if_index:" << if_index); + return false; + } + int vif = it_vif_map->second; + + m_routing.del_route(vif, g_addr, src_addr); + + return true; +} + +void proxy_instance::refresh_all_traffic(int if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + upstream_src_state_map::iterator iter_uss; + src_state_map::iterator iter_src; + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_group_state_pair* sgs_pair = 0; + + if(if_index == m_upstream){ + HC_LOG_ERROR("the if_index:" << if_index << " mussnt be the upstream, upstream have no joined groups"); + } + + //process upstream + iter_uss = m_upstream_state.find(g_addr); + if(iter_uss != m_upstream_state.end()){ //g_addr found + for(iter_src = iter_uss->second.begin(); iter_src != iter_uss->second.end(); iter_src++){ + if(!split_traffic(m_upstream, g_addr, iter_src->first)){ + //have to check old upstream source because the have no default stream so they dont refresh themselve like downstreams + iter_src->second.flag = src_state::UNUSED_SRC; + del_route(if_index,g_addr,iter_src->first); + } + } + } + + //process downstream + for(iter_table = m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ + if(if_index != iter_table->first){ + + iter_state = iter_table->second.find(g_addr); + + if(iter_state != iter_table->second.end()){ + sgs_pair = &iter_state->second; + + for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ + split_traffic(iter_table->first, g_addr, iter_src->first); + } + } + + } + } +} + +void proxy_instance::add_all_group_vifs_to_list(std::list<int>* vif_list, int without_if_index, addr_storage g_addr){ + + vif_map::iterator it_vif_map; + + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_group_state_pair* sgs_pair = 0; + + //all downstream traffic musst be forward to upstream + if(without_if_index != m_upstream){ + it_vif_map = m_vif_map.find(m_upstream); + if(it_vif_map == m_vif_map.end()){ + HC_LOG_ERROR("cant find vif to if_index:" << m_upstream); + return; + } + vif_list->push_back(it_vif_map->second); + //cout << "add_all_group_vifs_to_list: upstream gefunden und gesetzt. if_index: " << m_upstream << " vif: " << it_vif_map->second << endl; + } + + //all downstream and upstream traffic musste be forward to the downstream who joined the same group + for(iter_table = m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ + if(without_if_index != iter_table->first){ + + iter_state = iter_table->second.find(g_addr); + + if(iter_state != iter_table->second.end()){ + sgs_pair = &iter_state->second; + + //if the groupe is in use + if(sgs_pair->second.flag == src_state::RUNNING || sgs_pair->second.flag == src_state::RESPONSE_STATE || sgs_pair->second.flag == src_state::WAIT_FOR_DEL){ + it_vif_map = m_vif_map.find(iter_table->first); + if(it_vif_map == m_vif_map.end()){ + HC_LOG_ERROR("cant find vif to if_index:" << iter_table->first); + return; + } + vif_list->push_back(it_vif_map->second); + } + } + + } + } +} + +void proxy_instance::registrate_if(int if_index){ + HC_LOG_TRACE(""); + + vif_map::iterator it_vif_map; + if((it_vif_map = m_vif_map.find(if_index))== m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif from if_index:" << if_index); + return; + } + int vif = it_vif_map->second; + + //##-- routing --## + m_routing.add_vif( if_index, vif); + + //##-- receiver --## + m_receiver->registrate_interface(if_index, vif, this); + + if(if_index != m_upstream){ + + //##-- sender --## + //join all_router_addr at all downstreams + if(m_addr_family == AF_INET){ + addr_storage mc_router_addr(IPV4_ALL_IGMP_ROUTERS_ADDR); + if(!m_sender->send_report(if_index, mc_router_addr)){ + HC_LOG_ERROR("failed to join: ==> " << IPV4_ALL_IGMP_ROUTERS_ADDR); + } + }else if(m_addr_family == AF_INET6){ + addr_storage mc_router_addr(IPV6_ALL_LINK_LOCAL_ROUTER); + if(!m_sender->send_report(if_index, mc_router_addr )){ + HC_LOG_ERROR("failed to join: ==> " << mc_router_addr); + } + + mc_router_addr= IPV6_ALL_SITE_LOCAL_ROUTER; + if(!m_sender->send_report(if_index, mc_router_addr )){ + HC_LOG_ERROR("failed to join: ==> " << mc_router_addr); + } + + HC_LOG_WARN("untesteted"); + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return; + } + + //send the first GQ + if(!m_sender->send_general_query(if_index)){ + HC_LOG_ERROR("failed to send general to if_index: " << if_index); + return; + } + } +} + +void proxy_instance::unregistrate_if(int if_index){ + HC_LOG_TRACE(""); + + vif_map::iterator it_vif_map; + if((it_vif_map = m_vif_map.find(if_index))== m_vif_map.end()){ + HC_LOG_ERROR("failed to find vif from if_index:" << if_index); + return; + } + int vif = it_vif_map->second; + + //##-- routing --## + m_routing.del_vif(if_index, vif); + + //##-- receiver --## + m_receiver->del_interface(if_index, vif); + + //##-- timing --## + //remove all running times + //m_timing->stop_all_time(this); + + if(if_index != m_upstream){ + + //##-- sender --## + //leave all router addr at all downstreams + if(m_addr_family == AF_INET){ + addr_storage mc_router_addr(IPV4_ALL_IGMP_ROUTERS_ADDR); + if(!m_sender->send_leave(if_index, mc_router_addr )){ + HC_LOG_ERROR("failed to leave: ==> " << mc_router_addr); + } + }else if(m_addr_family == AF_INET6){ + addr_storage mc_router_addr(IPV6_ALL_LINK_LOCAL_ROUTER); + if(!m_sender->send_leave(if_index, mc_router_addr )){ + HC_LOG_ERROR("failed to leave: ==> " << mc_router_addr); + } + + mc_router_addr=IPV6_ALL_SITE_LOCAL_ROUTER; + if(!m_sender->send_leave(if_index, mc_router_addr )){ + HC_LOG_ERROR("failed to leave: ==> " << mc_router_addr); + } + + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return; + } + + + } + +} + +bool proxy_instance::is_group_joined(int without_if_index, const addr_storage& g_addr){ + HC_LOG_TRACE(""); + + state_table_map::iterator iter_table; + g_state_map::iterator iter_state; + src_group_state_pair* sgs_pair = 0; + + //process downstream + for(iter_table = m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ + if(without_if_index != iter_table->first){ + + iter_state = iter_table->second.find(g_addr); + + if(iter_state != iter_table->second.end()){ + sgs_pair = &iter_state->second; + if(sgs_pair->second.flag != src_state::INIT){ + return true; + } + } + + } + } + + return false; +} + +void proxy_instance::close(){ + HC_LOG_TRACE(""); + + delete m_sender; + + m_receiver->stop(); + m_receiver->join(); + delete m_receiver; + + + +} diff --git a/mcproxy/src/proxy/receiver.cpp b/mcproxy/src/proxy/receiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74a956602a98d65e2db09dd47fca89c6ea2764a0 --- /dev/null +++ b/mcproxy/src/proxy/receiver.cpp @@ -0,0 +1,178 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/receiver.hpp" + +#include <iostream> +using namespace std; + +receiver::receiver(): + m_running(false), m_worker_thread(0) +{ + HC_LOG_TRACE(""); +} + +receiver::~receiver(){ + HC_LOG_TRACE(""); + close(); +} + +void receiver::close(){ + HC_LOG_TRACE(""); + delete m_worker_thread; +} + +bool receiver::init_if_prop(){ + HC_LOG_TRACE(""); + + //if(!m_if_prop.init_IfInfo()) return false; + //if(!m_if_prop.refresh_network_interfaces()) return false; + m_if_property.refresh_network_interfaces(); + + return true; +} + +bool receiver::init(int addr_family, int version, mroute_socket* mrt_sock){ + HC_LOG_TRACE(""); + + m_addr_family = addr_family; + m_version = version; + m_mrt_sock = mrt_sock; + + if(!init_if_prop()) return false; + if(!m_mrt_sock->set_receive_timeout(RECEIVER_RECV_TIMEOUT)) return false; + //if(!m_mrt_sock->setLoopBack(true)) return false; + + return true; +} + +proxy_instance* receiver::get_proxy_instance(int if_index){ + HC_LOG_TRACE(""); + if_poxy_instance_map::iterator it= m_if_proxy_map.find(if_index); + if(it != m_if_proxy_map.end()){ + return it->second; + }else{ + return NULL; + } +} + +void receiver::registrate_interface(int if_index, int vif, proxy_instance* p){ + HC_LOG_TRACE(""); + + boost::lock_guard<boost::mutex> lock(m_data_lock); + m_if_proxy_map.insert(if_proxy_instance_pair(if_index,p)); + + m_vif_map.insert(vif_pair(vif,if_index)); +} + +void receiver::del_interface(int if_index,int vif){ + HC_LOG_TRACE(""); + + boost::lock_guard<boost::mutex> lock(m_data_lock); + m_if_proxy_map.erase(if_index); + m_vif_map.erase(vif); +} + +int receiver::get_if_index(int vif){ + HC_LOG_TRACE(""); + + vif_map::iterator it= m_vif_map.find(vif); + if(it != m_vif_map.end()){ + return it->second; + }else{ + return 0; + } +} + +void receiver::worker_thread(void* arg){ + HC_LOG_TRACE(""); + + receiver* r= (receiver*) arg; + int info_size = 0; + + //######################## + //create msg + //iov + unsigned char iov_buf[r->get_iov_min_size()]; + struct iovec iov; + iov.iov_base = iov_buf; + iov.iov_len = sizeof(iov_buf); + + //control + unsigned char ctrl[r->get_ctrl_min_size()]; + + //create msghdr + struct msghdr msg; + msg.msg_name = NULL; + msg.msg_namelen = 0; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = ctrl; + msg.msg_controllen = sizeof(ctrl); + + msg.msg_flags = 0; + //######################## + + while(r->m_running){ + if(!r->m_mrt_sock->receive_msg(&msg,info_size)){ + HC_LOG_ERROR("received failed"); + sleep(1); + continue; + } + if(info_size == 0) { + continue; //on timeout + } + r->m_data_lock.lock(); + r->analyse_packet(&msg,info_size); + r->m_data_lock.unlock(); + } +} + +bool receiver::is_running(){ + HC_LOG_TRACE(""); + return m_running; +} + +void receiver::start(){ + HC_LOG_TRACE(""); + + m_running = true; + m_worker_thread = new boost::thread(receiver::worker_thread, this); +} + +void receiver::stop(){ + HC_LOG_TRACE(""); + + m_running= false; +} + +void receiver::join(){ + HC_LOG_TRACE(""); + + if(m_worker_thread){ + m_worker_thread->join(); + } +} diff --git a/mcproxy/src/proxy/routing.cpp b/mcproxy/src/proxy/routing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f38e2367fbec0e9c1a85ecab9b412719849cd9f --- /dev/null +++ b/mcproxy/src/proxy/routing.cpp @@ -0,0 +1,158 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/routing.hpp" +#include "include/utils/addr_storage.hpp" + +#include <net/if.h> +#include <linux/mroute.h> +#include <linux/mroute6.h> +#include <iostream> + +bool routing::init(int addr_family, int version, mroute_socket* mrt_sock, bool single_instance, int table_number){ + HC_LOG_TRACE(""); + + m_is_single_instance = single_instance; + m_table_number = table_number; + m_addr_family = addr_family; + m_version = version; + m_mrt_sock = mrt_sock; + + if(!init_if_prop()) return false; + + return false; +} + +bool routing::init_if_prop(){ + HC_LOG_TRACE(""); + + if(!m_if_prop.refresh_network_interfaces()) return false; + + return true; +} + +bool routing::add_vif(int if_index, int vif){ + HC_LOG_TRACE(""); + + char cstr[IF_NAMESIZE]; + const struct ifaddrs* item=NULL; + string if_name(if_indextoname(if_index,cstr)); + + if(m_addr_family == AF_INET){ + if((item = m_if_prop.get_ip4_if(if_name))== NULL){ + HC_LOG_ERROR("interface not found: " << if_name); + return false; + } + }else if(m_addr_family == AF_INET6){ + if((item = m_if_prop.get_ip6_if(if_name)->front()) == NULL){ + HC_LOG_ERROR("interface not found: " << if_name); + return false; + } + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + if((item->ifa_flags & IFF_POINTOPOINT) && (item->ifa_dstaddr != NULL)) { //tunnel + + addr_storage p2p_addr(*(item->ifa_dstaddr)); + + if(!m_mrt_sock->add_vif(vif,if_name.c_str(),p2p_addr.to_string().c_str())){ + return false; + } + + }else{ //phyint + if(!m_mrt_sock->add_vif(vif,if_name.c_str(), NULL)){ + return false; + } + + } + + if(!m_is_single_instance){ + if(!m_mrt_sock->bind_vif_to_table(if_name.c_str(),m_table_number)){ + return false; + } + } + + HC_LOG_DEBUG("added interface: " << if_name << " to vif_table with vif number:" << vif); + return true; +} + +bool routing::add_route(int input_vif, const addr_storage& g_addr, const addr_storage& src_addr, const std::list<int>& output_vif){ + HC_LOG_TRACE(""); + + if(m_addr_family == AF_INET){ + if(output_vif.size() > MAXVIFS) return false; + }else if(m_addr_family == AF_INET6){ + if(output_vif.size() > MAXMIFS) return false; + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + list<int>::const_iterator iter_out; + unsigned int out_vif[output_vif.size()]; + + int i=0; + for(iter_out = output_vif.begin(); iter_out != output_vif.end(); iter_out++){ + out_vif[i++] = *iter_out; + } + + if(!m_mrt_sock->add_mroute(input_vif, src_addr.to_string().c_str(), g_addr.to_string().c_str(), out_vif, output_vif.size())){ + return false; + } + + return true; +} + +bool routing::del_route(int vif, const addr_storage& g_addr, const addr_storage& src_addr){ + HC_LOG_TRACE(""); + + if(!m_mrt_sock->del_mroute(vif, src_addr.to_string().c_str(), g_addr.to_string().c_str())){ + return false; + } + + return true; +} + +bool routing::del_vif(int if_index, int vif){ + HC_LOG_TRACE(""); + + if(!m_mrt_sock->del_vif(vif)){ + return false; + } + + if(!m_is_single_instance){ + char cstr[IF_NAMESIZE]; + if_indextoname(if_index,cstr); + + if(!m_mrt_sock->unbind_vif_form_table(cstr,m_table_number)){ + return false; + } + } + + HC_LOG_DEBUG("removed interface with vif number: " << vif) ; + return true; +} + diff --git a/mcproxy/src/proxy/sender.cpp b/mcproxy/src/proxy/sender.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af4ae27c4b3fe9876569152d8af43e26833f6807 --- /dev/null +++ b/mcproxy/src/proxy/sender.cpp @@ -0,0 +1,60 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/sender.hpp" + +sender::sender(){ + HC_LOG_TRACE(""); +} + +bool sender::init(int addr_family, int version){ + HC_LOG_TRACE(""); + + m_addr_family = addr_family; + m_version = version; + + if(m_addr_family == AF_INET){ + if(!m_sock.create_raw_ipv4_socket()) return false; + }else if(m_addr_family == AF_INET6){ + if(!m_sock.create_raw_ipv6_socket()) return false; + }else{ + HC_LOG_ERROR("wrong addr_family: " << m_addr_family); + return false; + } + + if(!m_sock.set_loop_back(false)) return false; + + if(!init_if_prop()) return false; + + return true; +} + +bool sender::init_if_prop(){ + HC_LOG_TRACE(""); + + if(!m_if_prop.refresh_network_interfaces()) return false; + + return true; +} + diff --git a/mcproxy/src/proxy/timing.cpp b/mcproxy/src/proxy/timing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ab96164f72117663e5ff84900dcda7615d7a3ba --- /dev/null +++ b/mcproxy/src/proxy/timing.cpp @@ -0,0 +1,153 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/timing.hpp" +#include "include/proxy/proxy_instance.hpp" +#include <sys/time.h> +#include <iostream> + +timing::timing(): + m_running(false), m_worker_thread(0) +{ + HC_LOG_TRACE(""); + +} + +timing::~timing(){ + HC_LOG_TRACE(""); + delete m_worker_thread; +} + +timing::timehandling::timehandling(struct timeval time, proxy_instance* pr_i, proxy_msg pr_msg){ + HC_LOG_TRACE(""); + m_time = time; + m_pr_i = pr_i; + m_pr_msg = pr_msg; +} + +void timing::worker_thread(timing* t){ + HC_LOG_TRACE(""); + + while(t->m_running){ + usleep(TIME_POLL_INTERVAL); + + struct timeval current_timeval; + gettimeofday(¤t_timeval, NULL); + + t->m_global_lock.lock(); + + list<struct timehandling>::iterator iter; + for(iter= t->m_time_list.begin(); iter != t->m_time_list.end(); iter++){ + if(current_timeval.tv_sec > iter->m_time.tv_sec){ + iter->m_pr_i->add_msg(iter->m_pr_msg); + iter = t->m_time_list.erase(iter); + }else if(current_timeval.tv_sec == iter->m_time.tv_sec){ + if(current_timeval.tv_usec >= iter->m_time.tv_usec){ + iter->m_pr_i->add_msg(iter->m_pr_msg); + iter = t->m_time_list.erase(iter); + } + } + } + + t->m_global_lock.unlock(); + + } +} + +timing* timing::getInstance(){ + HC_LOG_TRACE(""); + + static timing instance; + return &instance; +} + +void timing::add_time(int msec, proxy_instance* m_pr_i, proxy_msg& pr_msg){ + HC_LOG_TRACE(""); + + struct timeval t; + gettimeofday(&t, NULL); + t.tv_sec += msec/1000; + t.tv_usec += 1000 * (msec % 1000);; + + struct timehandling th(t, m_pr_i, pr_msg); + + m_global_lock.lock(); + m_time_list.push_back(th); + m_global_lock.unlock(); + +} + +void timing::stop_all_time(proxy_instance* pr_i){ + HC_LOG_TRACE(""); + + m_global_lock.lock(); + + list<struct timehandling>::iterator iter; + for(iter= m_time_list.begin(); iter != m_time_list.end(); iter++){ + if(iter->m_pr_i == pr_i){ + iter = m_time_list.erase(iter); + } + } + + m_global_lock.unlock(); +} + +void timing::start(){ + HC_LOG_TRACE(""); + + m_running = true; + m_worker_thread = new boost::thread(timing::worker_thread, this); +} + +void timing::stop(){ + HC_LOG_TRACE(""); + + m_running= false; +} + +void timing::join(){ + HC_LOG_TRACE(""); + + if(m_worker_thread){ + m_worker_thread->join(); + } +} + +void timing::test_timing(){ + HC_LOG_TRACE(""); + + timing* t = timing::getInstance(); + proxy_msg p_msg; + p_msg.msg = new struct test_msg(4); + + t->start(); + t->add_time(10000,NULL,p_msg); + /*t->add_time(2000,NULL,p_msg); + t->add_time(3000,NULL,p_msg); + t->add_time(4000,NULL,p_msg); + t->add_time(10000,NULL,p_msg);*/ + sleep(2); + t->stop(); + t->join(); +} diff --git a/mcproxy/src/proxy/worker.cpp b/mcproxy/src/proxy/worker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2edbcc6c3936c12b555e1694f6b4e61e0ad28a09 --- /dev/null +++ b/mcproxy/src/proxy/worker.cpp @@ -0,0 +1,76 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/proxy/worker.hpp" + +worker::worker(int max_msg): + m_worker_thread(0), m_running(false), m_job_queue(max_msg) + +{ + HC_LOG_TRACE(""); +} + +worker::~worker(){ + close(); +} + + +void worker::start(){ + HC_LOG_TRACE(""); + + m_running = true; + m_worker_thread = new boost::thread(worker::worker_thread_starter, this); +} + +void worker::worker_thread_starter(worker* w){ + HC_LOG_TRACE(""); + + w->worker_thread(); +} + +void worker::close(){ + HC_LOG_TRACE(""); + join(); + delete m_worker_thread; +} + +void worker::add_msg(proxy_msg& msg){ + HC_LOG_TRACE(""); + + HC_LOG_DEBUG("message type:" << msg.msg_type_to_string()); + m_job_queue.enqueue(msg); +} + +bool worker::is_running(){ + HC_LOG_TRACE(""); + return m_running; +} + +void worker::join(){ + HC_LOG_TRACE(""); + + if(m_worker_thread){ + m_worker_thread->join(); + } +} diff --git a/mcproxy/src/utils/addr_storage.cpp b/mcproxy/src/utils/addr_storage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7324f094cd0fe071dcbe548a3d62d17dc3afc05e --- /dev/null +++ b/mcproxy/src/utils/addr_storage.cpp @@ -0,0 +1,640 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/utils/addr_storage.hpp" + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <cstring> +#include <string> +#include <stdlib.h> + +void addr_storage::clean(){ + HC_LOG_TRACE(""); + + //memset(&m_addr,0, sizeof(m_addr)); + ((struct sockaddr_in6*)&m_addr)->sin6_family = AF_UNSPEC; + ((struct sockaddr_in6*)&m_addr)->sin6_port = 0; + ((struct sockaddr_in6*)&m_addr)->sin6_flowinfo = 0; + ((struct sockaddr_in6*)&m_addr)->sin6_scope_id = 0; +} + +int addr_storage::get_addr_len(int addr_family) const{ + HC_LOG_TRACE(""); + + switch(addr_family){ + case AF_INET: return sizeof(struct sockaddr_in); + case AF_INET6: return sizeof(struct sockaddr_in6); + default: + HC_LOG_ERROR("Unknown address family"); + return 0; + } +} + +addr_storage::addr_storage(){ + HC_LOG_TRACE(""); + + clean(); +} + +addr_storage::addr_storage(int addr_family){ + HC_LOG_TRACE(""); + + memset(&m_addr,0, sizeof(m_addr)); + m_addr.ss_family = addr_family; +} + +addr_storage::addr_storage(const std::string& addr) +{ + HC_LOG_TRACE(""); + *this = addr; +} + +addr_storage::addr_storage(const struct sockaddr_storage& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const addr_storage& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const struct in_addr& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const struct in6_addr& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const struct sockaddr& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const struct sockaddr_in6& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +addr_storage::addr_storage(const struct sockaddr_in& addr){ + HC_LOG_TRACE(""); + + *this = addr; +} + +std::ostream& operator <<(std::ostream& s, const addr_storage a){ + HC_LOG_TRACE(""); + + s << a.to_string(); + return s; +} + +addr_storage& addr_storage::operator=(const addr_storage& s){ + HC_LOG_TRACE(""); + + if(this != &s){ + this->m_addr = s.m_addr; + } + + return *this; +} + +addr_storage& addr_storage::operator=(const struct sockaddr_storage& s){ + HC_LOG_TRACE(""); + + this->m_addr = s; + return *this; +} + +addr_storage& addr_storage::operator=(const std::string& s){ + HC_LOG_TRACE(""); + + clean(); + + if(s.find_first_of(':')==std::string::npos){ //==> IPv4 + m_addr.ss_family=AF_INET; + if(inet_pton(m_addr.ss_family, s.c_str(), (void*)&(((struct sockaddr_in*)(&m_addr))->sin_addr))<1){ + HC_LOG_ERROR("failed to convert string to sockaddr_storage:" << s); + } + }else{ //==> IPv6 + m_addr.ss_family=AF_INET6; + if(inet_pton(m_addr.ss_family, s.c_str(), (void*)&(((struct sockaddr_in6*)(&m_addr))->sin6_addr))<1){ + HC_LOG_ERROR("failed to convert string to sockaddr_storage:" << s); + } + } + + return *this; +} + +addr_storage& addr_storage::operator=(const struct in_addr& s){ + HC_LOG_TRACE(""); + + clean(); + + m_addr.ss_family = AF_INET; + ((sockaddr_in*)(&m_addr))->sin_addr = s; + return *this; +} + +addr_storage& addr_storage::operator=(const struct in6_addr& s){ + HC_LOG_TRACE(""); + + clean(); + + m_addr.ss_family = AF_INET6; + ((sockaddr_in6*)(&m_addr))->sin6_addr = s; + return *this; +} + +addr_storage& addr_storage::operator=(const struct sockaddr& s){ + HC_LOG_TRACE(""); + + clean(); + memcpy(&m_addr,&s,get_addr_len(s.sa_family)); + + return *this; +} + +addr_storage& addr_storage::operator=(const struct sockaddr_in& s){ + HC_LOG_TRACE(""); + + clean(); + + *this = *(const struct sockaddr*)&s; + return *this; +} + +addr_storage& addr_storage::operator=(const struct sockaddr_in6& s){ + HC_LOG_TRACE(""); + + clean(); + + *this = *(const struct sockaddr_in*)&s; + return *this; +} + +bool addr_storage::operator==(const addr_storage& addr) const{ + HC_LOG_TRACE(""); + + std::string a, b; + a = this->to_string(); + b = addr.to_string(); + + if(a.empty()){ + return false; + }else if(a.compare(b) == 0){ + return true; + }else{ + return false; + } +} + +bool addr_storage::operator!=(addr_storage& addr) const{ + HC_LOG_TRACE(""); + + return !(*this == addr); +} + + +bool operator< (const addr_storage& addr1, const addr_storage& addr2){ + HC_LOG_TRACE(""); + + if(addr1.m_addr.ss_family == AF_INET && addr2.m_addr.ss_family == AF_INET){ + return ntohl(((sockaddr_in*)(&addr1))->sin_addr.s_addr) < ntohl(((sockaddr_in*)(&addr2))->sin_addr.s_addr); + }else if(addr1.m_addr.ss_family == AF_INET6 && addr2.m_addr.ss_family == AF_INET6){ + const uint8_t* a1 = ((const sockaddr_in6*)&addr1.m_addr)->sin6_addr.s6_addr; + const uint8_t* a2 = ((const sockaddr_in6*)&addr2.m_addr)->sin6_addr.s6_addr; + + for(unsigned int i=0; i < sizeof(struct in6_addr)/sizeof(uint8_t); i++){ + if(a1[i]> a2[i]){ + return false; + }else if(a1[i]<a2[i]){ + return true; + } + } + return false; + }else{ + HC_LOG_ERROR("incompatible ip versions"); + return false; + } +} + +int addr_storage::get_addr_family() const{ + HC_LOG_TRACE(""); + + return this->m_addr.ss_family; +} + +int addr_storage::get_port() const{ + HC_LOG_TRACE(""); + + return ((sockaddr_in*)&m_addr)->sin_port; +} + +addr_storage& addr_storage::set_port(int port){ + HC_LOG_TRACE(""); + + ((sockaddr_in*)&m_addr)->sin_port = port; + return *this; +} + +addr_storage& addr_storage::set_port(const string& port){ + HC_LOG_TRACE(""); + + set_port(atoi(port.c_str())); + return *this; +} + +int addr_storage::get_addr_len() const{ + HC_LOG_TRACE(""); + + return get_addr_len(get_addr_family()); +} + +const struct sockaddr_storage& addr_storage::get_sockaddr_storage() const{ + HC_LOG_TRACE(""); + + return m_addr; +} + +const struct in_addr& addr_storage::get_in_addr() const{ + HC_LOG_TRACE(""); + + return ((const struct sockaddr_in*)(&m_addr))->sin_addr; +} + +const struct in6_addr& addr_storage::get_in6_addr() const{ + HC_LOG_TRACE(""); + + return ((const struct sockaddr_in6*)(&m_addr))->sin6_addr; +} + +const struct sockaddr& addr_storage::get_sockaddr() const{ + HC_LOG_TRACE(""); + + return *((const struct sockaddr*)&m_addr); +} + +const struct sockaddr_in& addr_storage::get_sockaddr_in() const{ + HC_LOG_TRACE(""); + + return *((const struct sockaddr_in*)(&m_addr)); +} + +const struct sockaddr_in6& addr_storage::get_sockaddr_in6() const{ + HC_LOG_TRACE(""); + + return *((const struct sockaddr_in6*)(&m_addr)); +} + + +std::string addr_storage::to_string() const{ + HC_LOG_TRACE(""); + + int af = m_addr.ss_family; + if(af == AF_INET){ + char addressBuffer[INET_ADDRSTRLEN]; + + if(inet_ntop(af,(const void*)&(((const struct sockaddr_in*)(&m_addr))->sin_addr),addressBuffer, sizeof(addressBuffer)) == NULL){ + HC_LOG_ERROR("failed to convert sockaddr_storage"); + return std::string(); + }else{ + return std::string(addressBuffer); + } + }else if(af == AF_INET6){ + char addressBuffer[INET6_ADDRSTRLEN]; + if(inet_ntop(af,(const void*)&(((const struct sockaddr_in6*)(&m_addr))->sin6_addr),addressBuffer, sizeof(addressBuffer)) == NULL){ + HC_LOG_ERROR("failed to convert sockaddr_storage"); + return std::string(); + }else{ + return std::string(addressBuffer); + } + + }else{ + HC_LOG_ERROR("wrong address family"); + return std::string(); + } + +} + +addr_storage& addr_storage::mask(const addr_storage& s){ + HC_LOG_TRACE(""); + + if(this->m_addr.ss_family == AF_INET && s.m_addr.ss_family == AF_INET){ + ((sockaddr_in*)(&m_addr))->sin_addr.s_addr &= ((sockaddr_in*)(&s))->sin_addr.s_addr; + return *this; + }else { + HC_LOG_ERROR("incompatible ip versions"); + } + + return *this; +} + +void addr_storage::test_addr_storage_old(){ + HC_LOG_TRACE(""); + + using namespace std; + std::string addr4 = "251.0.0.224"; + std::string addr6 = "ff02:231:abc::1"; + + struct sockaddr_storage sockaddr4; + struct sockaddr_storage sockaddr6; + struct in_addr in_addr4; + struct in6_addr in_addr6; + struct in6_addr in_addr6tmp; + + addr_storage s4; + addr_storage s6; + addr_storage s4_tmp; + addr_storage s6_tmp; + addr_storage s4_1; + addr_storage s6_1; + + + + cout << "-- string in addr_storage, cout stream, sockaddr_storage to string --" << endl; + s4 = addr4; + s6 = addr6; + + cout <<"addr4: str<" << addr4 << "> addr_storage<" << s4 << "> ==>" << (addr4.compare(s4.to_string())==0? "OK!" : "FAILED!") << endl; + cout << "addr6: str<" << addr6 << "> addr_storage<" << s6 << "> ==>" << (addr6.compare(s6.to_string())==0? "OK!" : "FAILED!") << endl; + + cout << "-- sockaddr_storage to addr_storage --" << endl; + sockaddr4 = s4.get_sockaddr_storage(); + sockaddr6 = s6.get_sockaddr_storage(); + s4_1 = sockaddr4; + s6_1 = sockaddr6; + cout << "addr4: str<" << addr4 << "> addr_storage<" << s4_1 << "> ==>" << (addr4.compare(s4_1.to_string())==0? "OK!" : "FAILED!") << endl; + cout << "addr6: str<" << addr6 << "> addr_storage<" << s6_1 << "> ==>" << (addr6.compare(s6_1.to_string())==0? "OK!" : "FAILED!") << endl; + + cout << "-- equivalent addresses --" << endl; + s4_tmp = "Hallo ich bin bob"; + s6_tmp = "ich: auch"; + + cout << "s4_tmp: str<" << s4_tmp << "> == s6_tmp<" << s6_tmp << "> ==>" << ((s4_tmp != s6_tmp)? "OK!" : "FAILED!") << endl; + cout << "s6_1: str<" << s6_1 << "> s6_1<" << s6_1 << "> ==>" << (s6_1 == s6_1? "OK!" : "FAILED!") << endl; + + + cout << "-- struct in_addr and in6_addr --" << endl; + in_addr4 = s4.get_in_addr(); + in_addr6 = s6.get_in6_addr(); + + if(!inet_pton(AF_INET6, addr6.c_str(),(void*)&in_addr6tmp)>0){ + cout << "Error convert " << addr6 <<" to in6_addr FAILED! " << endl; + } + + cout << "addr_storage to struct in_addr ==>" << (in_addr4.s_addr == inet_addr(addr4.c_str())? "OK!": "FAILED!") << endl; + cout << "addr_storage to struct in6_addr ==>" << (IN6_ARE_ADDR_EQUAL(&in_addr6,&in_addr6tmp)? "OK!": "FAILED!") << endl; + cout << "struct in_addr to addr_storage ==>" << ((addr_storage(in_addr4).to_string().compare(addr4)==0)? "OK!": "FAILED!") <<endl; + cout << "struct in6_addr to addr_storage ==>" << ((addr_storage(in_addr6).to_string().compare(addr6)==0)? "OK!": "FAILED!") <<endl; + + cout << "-- ipv4 mask --" << endl; + s6_tmp = "141.22.26.0"; + s4 = "141.22.26.249"; + s6 = "255.255.254.0"; + s4_tmp = s4; + s4_tmp.mask(s6); + cout << s4 << " mask with " << s6 << " ==> " << s4_tmp << " ==>" << (s4_tmp == s6_tmp? "OK!" : "FAILED!") << endl; + s4 = "141.22.27.155"; + s6 = "255.255.254.0"; + s4_tmp = s4; + s4_tmp.mask(s6); + cout << s4 << " mask with " << s6 << " ==> " << s4_tmp << " ==>" << (s4_tmp == s6_tmp? "OK!" : "FAILED!")<< endl; + s4 = "141.22.27.142"; + s6 = "255.255.254.0"; + s4_tmp = s4; + s4_tmp.mask(s6); + cout << s4 << " mask with " << s6 << " ==> " << s4_tmp << " ==>" << (s4_tmp == s6_tmp? "OK!" : "FAILED!")<< endl; + + cout << "-- less then --" << endl; + s4 = "141.22.26.249"; + s6 = "255.255.254.0"; + cout << s4 << " is less then " << s6 << ": " << (s4<s6? "true ==>OK!" : "false ==>FAILED!") << endl; + cout << s6 << " is less then " << s4 << ": " << (s6<s4? "true ==>FAILED!" : "false ==>OK!") << endl; + s4 = "fe80::5e26:aff:fe23:8dc0"; + s6 = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; + cout << s4 << " is less then " << s6 << ": " << (s4<s6? "true ==>OK!" : "false ==>FAILED!") << endl; + cout << s6 << " is less then " << s4 << ": " << (s6<s4? "true ==>FAILED!" : "false ==>OK!") << endl; + s4 = "0:0:0:0:ffff:ffff:ffff:ffff"; + s6 = "ffff:ffff:ffff:ffff::0"; + cout << s4 << " is less then " << s6 << ": " << (s4<s6? "true ==>OK!" : "false ==>FAILED!") << endl; + cout << s6 << " is less then " << s4 << ": " << (s6<s4? "true ==>FAILED!" : "false ==>OK!") << endl; + +} + +void addr_storage::test_addr_storage(){ + HC_LOG_TRACE(""); + + //string + //sockaddr_storage + //in_addr + //in6_addr + //sockaddr + //sockaddr_in + //sockaddr_in6 + + const string s4("1.2.3.4"); + const string s6("1:2:3::4"); + const addr_storage a4(s4); + const addr_storage a6(s6); + + cout << "const string s4(\"1.2.3.4\");" << endl; + cout << "const string s6(\"1:2:3::4\");" << endl; + cout << "const addr_storage a4(s4);" << endl; + cout << "const addr_storage a6(s6);" << endl; + cout << "-------------------------------" << endl; + + cout << "a4.to_string().compare(s4) ==> "; + if(a4.to_string().compare(s4)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6.to_string().compare(s6) ==> "; + if(a6.to_string().compare(s6)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a4.get_sockaddr_storage()).to_string().compare(s4) ==> "; + if(addr_storage(a4.get_sockaddr_storage()).to_string().compare(s4) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a6.get_sockaddr_storage()).to_string().compare(s6) ==> "; + if(addr_storage(a6.get_sockaddr_storage()).to_string().compare(s6) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a4.get_sockaddr()).to_string().compare(s4) ==> "; + if(addr_storage(a4.get_sockaddr()).to_string().compare(s4) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a6.get_sockaddr()).to_string().compare(s6) ==> "; + if(addr_storage(a4.get_sockaddr()).to_string().compare(s4) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a4.get_sockaddr_in()).to_string().compare(s4) ==> "; + if(addr_storage(a4.get_sockaddr_in()).to_string().compare(s4) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "addr_storage(a6.get_sockaddr_in6()).to_string().compare(s6) ==> "; + if(addr_storage(a6.get_sockaddr_in6()).to_string().compare(s6) == 0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "-------------------------------" << endl; + cout << "addr_storage a4a(s4);" << endl; + cout << "addr_storage a6a(s6);" << endl; + cout << "const int port = 123;" << endl; + + addr_storage a4a(s4); + addr_storage a6a(s6); + const int port = 123; + + cout << "a4a.set_port(port).get_port() == port ==> "; + if(a4a.set_port(port).get_port() == port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6a.set_port(port).get_port() == port ==> "; + if(a6a.set_port(port).get_port() == port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a4a.to_string().compare(s4) ==> "; + if(a4a.to_string().compare(s4)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6.to_string().compare(s6) ==> "; + if(a6a.to_string().compare(s6)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "-------------------------------" << endl; + cout << "const int bad_port = 0xFFFFFF;" << endl; + const int bad_port = 0xFFFFFF; + + + cout << "a4a.set_port(bad_port).get_port() != bad_port ==> "; + if(a4a.set_port(bad_port).get_port() != bad_port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6a.set_port(port).get_port() != port ==> "; + if(a6a.set_port(bad_port).get_port() != bad_port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a4a.to_string().compare(s4) ==> "; + if(a4a.to_string().compare(s4)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6a.to_string().compare(s6) ==> "; + if(a6a.to_string().compare(s6)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "-------------------------------" << endl; + cout << "const string sport = \"123\";" << endl; + a4a = s4; + a6a = s6; + + const string sport = "123"; + + cout << "a4a.set_port(port).get_port() == port ==> "; + if(a4a.set_port(port).get_port() == port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6a.set_port(port).get_port() == port ==> "; + if(a6a.set_port(port).get_port() == port){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a4a.to_string().compare(s4) ==> "; + if(a4a.to_string().compare(s4)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + + cout << "a6.to_string().compare(s6) ==> "; + if(a6a.to_string().compare(s6)==0){ + cout << "OK!" << endl; + }else{ + cout << "FAILED!" << endl; + } + +} + diff --git a/mcproxy/src/utils/if_prop.cpp b/mcproxy/src/utils/if_prop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62814dfe401118f0309e890ab8100905c366e860 --- /dev/null +++ b/mcproxy/src/utils/if_prop.cpp @@ -0,0 +1,230 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/utils/if_prop.hpp" +#include "include/utils/addr_storage.hpp" + +#include <cstring> +#include <errno.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <unistd.h> +#include <iostream> + +//using namespace std; + +if_prop::if_prop(): + m_if_addrs(0) +{ + HC_LOG_TRACE(""); +} + +bool if_prop::refresh_network_interfaces(){ + HC_LOG_TRACE(""); + + //clean + if(is_getaddrs_valid()){ + freeifaddrs(m_if_addrs); + } + + m_if_map.clear(); + + //create + if(getifaddrs(&m_if_addrs) < 0){ + HC_LOG_ERROR("getifaddrs failed! Error: " << strerror(errno) ); + return false; + } + + struct ifaddrs* ifEntry=NULL; + for(ifEntry=m_if_addrs; ifEntry!=NULL; ifEntry=ifEntry->ifa_next) { + if(ifEntry->ifa_addr->sa_data == NULL) { + continue; + } + + + if(ifEntry->ifa_addr->sa_family==AF_INET) { + if_prop_map::iterator iter = m_if_map.find(ifEntry->ifa_name); + if(iter != m_if_map.end()){ //existing interface + if(iter->second.ip4_addr != NULL){ + HC_LOG_WARN("more than one ipv4 address for one interface configurated! used:" << addr_storage(*(iter->second.ip4_addr->ifa_addr)) << "; don't used:" << addr_storage(*(ifEntry->ifa_addr)) << ";"); + //return false; + }else{ + iter->second.ip4_addr = ifEntry; + } + }else{ //new interface + m_if_map.insert(if_prop_pair(ifEntry->ifa_name, ipv4_6_pair(ifEntry,list<const struct ifaddrs*>()))); + } + } else if(ifEntry->ifa_addr->sa_family==AF_INET6) { + if_prop_map::iterator iter = m_if_map.find(ifEntry->ifa_name); + if(iter != m_if_map.end()){ //existing interface + list<const struct ifaddrs*>* l = &iter->second.ip6_addr; + l->push_back(ifEntry); + }else{ //new interface + list<const struct ifaddrs*> l; + l.push_back(ifEntry); + m_if_map.insert(if_prop_pair(ifEntry->ifa_name, ipv4_6_pair(NULL,l))); + } + } else { + //It isn't IPv4 or IPv6 + continue; + } + + } + return true; +} + +const if_prop_map* if_prop::get_if_props() const{ + HC_LOG_TRACE(""); + + if (!is_getaddrs_valid()) { + HC_LOG_ERROR("data invalid"); + return NULL; + } + + return &m_if_map; +} + +const struct ifaddrs* if_prop::get_ip4_if(const string &if_name) const{ + HC_LOG_TRACE(""); + + if (!is_getaddrs_valid()) { + HC_LOG_ERROR("data invalid"); + return NULL; + } + + if_prop_map::const_iterator if_prop_iter = m_if_map.find(if_name); + if(if_prop_iter == m_if_map.end()) return NULL; + + return if_prop_iter->second.ip4_addr; +} + +const list<const struct ifaddrs*>* if_prop::get_ip6_if(const string &if_name) const{ + HC_LOG_TRACE(""); + + if (!is_getaddrs_valid()) { + HC_LOG_ERROR("data invalid"); + return NULL; + } + + if_prop_map::const_iterator if_prop_iter = m_if_map.find(if_name); + if(if_prop_iter == m_if_map.end()) return NULL; + + return &(if_prop_iter->second.ip6_addr); +} + +void if_prop::print_if_addr(const struct ifaddrs* if_p) const{ + cout << "\tif name: " << if_p->ifa_name << endl; + cout << "\t- addr: " << addr_storage(*if_p->ifa_addr) << endl; + cout << "\t- netmask: " << addr_storage(*if_p->ifa_netmask) << endl; + + cout << "\t- flags:"; + if(if_p->ifa_flags & IFF_UP) cout << "IFF_UP "; + if(if_p->ifa_flags & IFF_RUNNING) cout << "IFF_RUNNING "; + if(if_p->ifa_flags & IFF_LOOPBACK) cout << "IFF_LOOPBACK "; + if(if_p->ifa_flags & IFF_BROADCAST) cout << "IFF_BROADCAST "; + if(if_p->ifa_flags & IFF_ALLMULTI) cout << "IFF_ALLMULTI "; + if(if_p->ifa_flags & IFF_MULTICAST) cout << "IFF_MULTICAST "; + if(if_p->ifa_flags & IFF_PROMISC) cout << "IFF_PROMISCIFF_PROMISC "; + if(if_p->ifa_flags & IFF_POINTOPOINT) cout << "IFF_POINTOPOINT "; + + cout << endl; + + if(if_p->ifa_flags & IFF_POINTOPOINT){ + if(if_p->ifa_dstaddr != NULL){ + cout << "\t- dstaddr: " << addr_storage(*if_p->ifa_dstaddr) << endl; + } + }else if(if_p->ifa_addr->sa_family == AF_INET){ //broadcast addr + cout << "\t- broadaddr: " << addr_storage(*if_p->ifa_broadaddr) << endl; + } +} + +void if_prop::print_if_info() const{ + HC_LOG_TRACE(""); + + if (!is_getaddrs_valid()) { + HC_LOG_ERROR("data invalid"); + return; + } + + const if_prop_map* prop = get_if_props(); + if(prop == NULL){ + HC_LOG_ERROR("data struct not found"); + return; + } + + const struct ifaddrs* if_p; + const list<const struct ifaddrs*>* if_p_list; + + cout << "##-- IPv4 [count:" << prop->size() << "]--##" << endl; + for(if_prop_map::const_iterator iter = prop->begin(); iter != prop->end(); iter++){ + if_p = get_ip4_if(iter->first); + if(if_p == NULL){ + HC_LOG_ERROR("interface name not found: " << iter->first); + continue; + } + + print_if_addr(if_p); + } + + cout << "##-- IPv6 [count:" << prop->size() << "]--##" << endl; + for(if_prop_map::const_iterator iter = prop->begin(); iter != prop->end(); iter++){ + if_p_list = get_ip6_if(iter->first); + + if(if_p_list == NULL){ + HC_LOG_ERROR("interface name not found: " << iter->first); + continue; + } + + for(list<const struct ifaddrs*>::const_iterator itera = if_p_list->begin(); itera != if_p_list->end(); itera++){ + print_if_addr(*itera); + } + } +} + +if_prop::~if_prop(){ + HC_LOG_TRACE(""); + + if(is_getaddrs_valid()){ + freeifaddrs(m_if_addrs); + } +} + +void if_prop::test_if_prop(){ + HC_LOG_TRACE(""); + + if_prop p; + cout << "##-- refresh --##" << endl; + if(!p.refresh_network_interfaces()){ + cout << "refresh faild" << endl; + return; + } + p.print_if_info(); + cout << "##-- refresh --##" << endl; + sleep(1); + if(!p.refresh_network_interfaces()){ + cout << "refresh faild" << endl; + return; + } + p.print_if_info(); +} diff --git a/mcproxy/src/utils/mc_socket.cpp b/mcproxy/src/utils/mc_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2963e2bccdfd65f8aadedf2f8d905454581e7606 --- /dev/null +++ b/mcproxy/src/utils/mc_socket.cpp @@ -0,0 +1,639 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/utils/mc_socket.hpp" + +#include <boost/lexical_cast.hpp> +#include <netpacket/packet.h> +#include <cstring> //memset +#include <iostream> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/socket.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <net/if.h> + + +using namespace std; + +string ipAddrResolver(string ipAddr){ + string str[][2]={ + {IPV4_IGMPV3_ADDR, "IPV4_IGMPV3_ADDR"}, + {IPV4_ALL_HOST_ADDR,"IPV4_ALL_HOST_ADDR"}, + {IPV4_ALL_IGMP_ROUTERS_ADDR, "IPV4_ALL_ROUTERS_ADDR"}, + {IPV4_PIMv2_ADDR,"IPV4_PIMv2_ADDR"}, + {IPV4_MCAST_DNS_ADDR, "IPV4_MCAST_DNS_ADDR"}, + {IPV6_ALL_MLDv2_CAPABLE_ROUTERS, "IPV6_ALL_MLDv2_CAPABLE_ROUTERS"}, + {IPV6_ALL_NODES_ADDR,"IPV6_ALL_NODES_ADDR"}, + {IPV6_ALL_LINK_LOCAL_ROUTER, "IPV6_ALL_LINK_LOCAL_ROUTER"}, + {IPV6_ALL_SITE_LOCAL_ROUTER,"IPV6_ALL_SITE_LOCAL_ROUTER"}, + {IPV6_ALL_PIM_ROUTERS, "IPV6_ALL_PIM_ROUTERS"} + }; + + unsigned int nCount = 9; + + for(unsigned int i=0; i< nCount; i++){ + if(ipAddr.compare(str[i][0])==0){ + return str[i][1]; + } + } + + return string(); +} + +int family_to_level(int family) +{ + switch (family) { + case AF_INET: + return IPPROTO_IP; + case AF_INET6: + return IPPROTO_IPV6; + default: + return -1; + } +} + +mc_socket::mc_socket() : + m_sock(0), m_addrFamily(-1), m_own_socket(true) { + HC_LOG_TRACE(""); +} + +bool mc_socket::create_udp_ipv4_socket() { + HC_LOG_TRACE(""); + + if (is_udp_valid()) { + close(m_sock); + } + + // IP-Protokollv4, UDP, Protokoll + m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); //SOCK_DGRAM //IPPROTO_IP + if (m_sock < 0) { + HC_LOG_ERROR("failed to create! Error: " << strerror(errno) << " errno: " << errno); + return false; // failed + } else { + HC_LOG_DEBUG("get socket discriptor number: " << m_sock); + m_addrFamily = AF_INET; + m_own_socket = true; + return true; + } + +} + +bool mc_socket::create_udp_ipv6_socket() { + HC_LOG_TRACE(""); + + if (is_udp_valid()) { + close(m_sock); + } + + // IP-Protokollv6, UDP, Protokoll + m_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP); //SOCK_DGRAM //IPPROTO_IP + if (m_sock < 0) { + HC_LOG_ERROR("failed to create! Error: " << strerror(errno) << " errno: " << errno); + return false; // failed + } else { + HC_LOG_DEBUG("get socket discriptor number: " << m_sock); + m_addrFamily = AF_INET6; + m_own_socket = true; + return true; + } +} + +bool mc_socket::set_own_socket(int sck, int addr_family){ + HC_LOG_TRACE(""); + + if (is_udp_valid()) { + close(m_sock); + } + + if (sck < 0) { + HC_LOG_ERROR("wrong socket discriptor! socket: " << sck); + return false; // failed + } else { + if(addr_family == AF_INET || addr_family == AF_INET6){ + m_sock= sck; + m_addrFamily = addr_family; + m_own_socket = false; + }else{ + HC_LOG_ERROR("wrong address family: " << addr_family); + return false; // failed + } + return true; + } +} + +int mc_socket::get_addr_family(){ + return m_addrFamily; +} + +bool mc_socket::bind_udp_socket(int port) { + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + //struct sockaddr_storage tmp; + struct sockaddr* m_addr; + struct sockaddr_in m_addr_v4; + struct sockaddr_in6 m_addr_v6; + int size; + int rc; + + if(m_addrFamily==AF_INET){ + m_addr_v4.sin_family = AF_INET; + m_addr_v4.sin_addr.s_addr = INADDR_ANY; + m_addr_v4.sin_port = htons(port); + m_addr = (sockaddr*) &m_addr_v4; + size = sizeof(m_addr_v4); + }else if(m_addrFamily==AF_INET6){ + m_addr_v6.sin6_family = AF_INET6; + m_addr_v6.sin6_flowinfo = 0; + m_addr_v6.sin6_port = htons(port); + m_addr_v6.sin6_addr = in6addr_any; + m_addr = (sockaddr*) &m_addr_v6; + size = sizeof(m_addr_v6); + }else{ + HC_LOG_ERROR("Unknown Errno"); + return false; + } + + rc = bind(m_sock, m_addr, size); + if (rc == -1) { + HC_LOG_ERROR("failed to bind! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + HC_LOG_DEBUG("bind to port: " << port); + return true; + } +} + +bool mc_socket::set_loop_back(bool enable) { + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + int rc; + int loopArg; + int level; + + //u_char loop; + int loop; + if (enable == true) { + loop = 1; + } else { + loop = 0; + } + + if(m_addrFamily == AF_INET){ + level = IPPROTO_IP; + loopArg = IP_MULTICAST_LOOP; + }else if(m_addrFamily == AF_INET6){ + level = IPPROTO_IPV6; + loopArg = IPV6_MULTICAST_LOOP; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + rc = setsockopt(m_sock, level, loopArg, &loop, sizeof(loop)); + + if (rc == -1) { + HC_LOG_ERROR("failed to setLoopBack(on/off)! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } +} + +bool mc_socket::send_packet(const char* addr, int port, string data){ + return send_packet(addr,port, (unsigned char*)data.c_str(),data.size()); +} + +bool mc_socket::send_packet(const char* addr, int port, const unsigned char* data, unsigned int data_size) { + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + struct addrinfo *grp = NULL; + struct addrinfo hints; + int rc=0; + + memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + string str_port = boost::lexical_cast<string>( port ); + + if ((rc = getaddrinfo(addr, str_port.c_str(), &hints, &grp)) != 0) { + HC_LOG_ERROR("failed to generate addrinfo:" << gai_strerror(rc)); + return false; + } + save_free<free_fun,struct addrinfo*> free(&freeaddrinfo,grp); + + rc = sendto(m_sock, data, data_size, 0,grp->ai_addr, grp->ai_addrlen); + + if (rc == -1) { + HC_LOG_ERROR("failed to send! Error: " << strerror(errno) << " errno: " << errno); + return false; //failed to send + } else { + return true; + } +} + +bool mc_socket::receive_packet(unsigned char* buf, int sizeOfBuf, int &sizeOfInfo) { + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + int rc; + rc = recv(m_sock, buf, sizeOfBuf, 0); + sizeOfInfo = rc; + if (rc == -1) { + if(errno == EAGAIN || errno == EWOULDBLOCK){ + sizeOfInfo = 0; + return true; + }else{ + HC_LOG_ERROR("failed to receive Error: " << strerror(errno) << " errno: " << errno); + return false; + } + } else { + return true; + } +} + +bool mc_socket::receive_msg(struct msghdr* msg, int &sizeOfInfo){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + int rc; + rc = recvmsg(m_sock, msg, 0); + sizeOfInfo = rc; + if (rc == -1) { + if(errno == EAGAIN || errno == EWOULDBLOCK){ + sizeOfInfo = 0; + return true; + }else{ + HC_LOG_ERROR("failed to receive msg Error: " << strerror(errno) << " errno: " << errno); + return false; + } + } else { + return true; + } + + //example + // //######################## + // //create msg + // //msg_name + // struct sockaddr_in6 recv_addr; + // recv_addr.sin6_family = AF_INET6; + // recv_addr.sin6_addr = in6addr_any; + // recv_addr.sin6_flowinfo= 0; + // recv_addr.sin6_port = 0; + // recv_addr.sin6_scope_id = 2; + + // //iov + // unsigned char buf[400]; + // struct iovec iov; + // iov.iov_base = buf; + // iov.iov_len = sizeof(buf); + + // //control + // unsigned char ctrl[400]; + + // //create msghdr + // struct msghdr msg; + // msg.msg_name = &recv_addr; + // msg.msg_namelen = sizeof(struct sockaddr_in6); + + // msg.msg_iov = &iov; + // msg.msg_iovlen = 1; + + // msg.msg_control = ctrl; + // msg.msg_controllen = sizeof(ctrl); + + // msg.msg_flags = 0; + // //######################## + + // //iterate + // struct cmsghdr* cmsgptr; + + // for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + // if (cmsgptr->cmsg_len == 0) { + // cout << "hier fehler" << endl; + // /* Error handling */ + // break; + // } + // cout << "\tinhalt ..." << endl; + // if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) { + // u_char *ptr; + // ptr = CMSG_DATA(cmsgptr); + // /* process data pointed to by ptr */ + // } + // } + // //####################### +} + +bool mc_socket::set_receive_timeout(long msec){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + struct timeval t; + t.tv_sec = msec/1000; + t.tv_usec = 1000 * (msec % 1000);; + + int rc= setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); + + if (rc == -1) { + HC_LOG_ERROR("failed to set timeout! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } +} + +bool mc_socket::choose_if(int if_index){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + struct in_addr inaddr; + struct ifreq ifreq; + + if( if_index > 0){ + if (if_indextoname(if_index, ifreq.ifr_name) == NULL) { + HC_LOG_ERROR("failed to get interface name! if_index:" << if_index << "! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + if (ioctl(m_sock, SIOCGIFADDR, &ifreq) < 0){ + HC_LOG_ERROR("failed to get interface address! if_name: " << ifreq.ifr_name); + return false; + } + + memcpy(&inaddr, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); + }else{ + inaddr.s_addr = htonl(INADDR_ANY); + } + + int rc= setsockopt(m_sock, IPPROTO_IP, IP_MULTICAST_IF, &inaddr, sizeof(struct in_addr)); + + if (rc == -1) { + HC_LOG_ERROR("failed to choose_if! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else if(m_addrFamily == AF_INET6){ + int rc= setsockopt(m_sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index)); + + if (rc == -1) { + HC_LOG_ERROR("failed to choose_if! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mc_socket::set_ttl(int ttl){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + rc = setsockopt(m_sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); + }else if(m_addrFamily == AF_INET6){ + rc = setsockopt(m_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + if (rc == -1) { + HC_LOG_ERROR("failed to set ttl: "<< ttl << "! Error: " << strerror(errno)); + return false; + } else { + return true; + } +} + +bool mc_socket::join_group(const char* addr, int if_index) { + HC_LOG_TRACE("g_addr: " << addr << " if_index: " << if_index); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + }else{ + HC_LOG_DEBUG("use socket discriptor number: " << m_sock); + } + + struct group_req req; + struct addrinfo *grp = NULL; + struct addrinfo hints; + int rc=0; + + memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + if ((rc = getaddrinfo (addr, 0, &hints, &grp)) != 0) { + HC_LOG_ERROR("failed to generate addrinfo:" << gai_strerror(rc)); + return false; + } + save_free<free_fun,struct addrinfo*> free(&freeaddrinfo,grp); + + if (grp->ai_addrlen > sizeof (req.gr_group)) { + HC_LOG_ERROR("wrong addrlen"); + return false; + } + + req.gr_interface = if_index; + memcpy (&req.gr_group, grp->ai_addr, grp->ai_addrlen); + + rc = setsockopt (m_sock, family_to_level(grp->ai_family), MCAST_JOIN_GROUP, &req, sizeof(req)); + + if (rc == -1) { + HC_LOG_ERROR("failed to join! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + +} + +//!! interface: IPv4 ==> InterfaceIpAddress , IPv6 ==> InterfaceName +bool mc_socket::leave_group(const char* addr, int if_index) { + HC_LOG_TRACE("g_addr: " << addr << " if_index: " << if_index); + + if (!is_udp_valid()) { + HC_LOG_ERROR("udp_socket invalid"); + return false; + }else{ + HC_LOG_DEBUG("use socket discriptor number: " << m_sock); + } + + struct group_req req; + struct addrinfo *grp = NULL; + struct addrinfo hints; + int rc=0; + + memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + if ((rc = getaddrinfo (addr, 0, &hints, &grp)) != 0) { + HC_LOG_ERROR("failed to generate addrinfo:" << gai_strerror(rc)); + return false; + } + save_free<free_fun,struct addrinfo*> free(&freeaddrinfo,grp); + + req.gr_interface = if_index; + + if (grp->ai_addrlen > sizeof (req.gr_group)) { + HC_LOG_ERROR("wrong addrlen"); + return false; + } + + memcpy (&req.gr_group, grp->ai_addr, grp->ai_addrlen); + rc = setsockopt (m_sock, family_to_level(grp->ai_family), MCAST_LEAVE_GROUP, &req, sizeof(req)); + + if (rc == -1) { + HC_LOG_ERROR("failed to join! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + +} + +void mc_socket::test_join_leave_send(){ + HC_LOG_TRACE(""); + + int sleepTime = 1; + mc_socket m; + string msg = "Hallo"; + + cout << "--<1> Join and leave ipv4 --" << endl; + m.create_udp_ipv4_socket(); + if(m.join_group("238.99.99.99",if_nametoindex("eth0"))){ + cout << "join OK!" << endl; + }else{ + cout << "join FAILED!" << endl; + } + sleep(sleepTime); + if(m.leave_group("238.99.99.99",if_nametoindex("eth0"))){ + cout << "leave OK!" << endl; + }else{ + cout << "leave FAILED!" << endl; + } + sleep(sleepTime); + + cout << "--<2> Join and leave ipv6 --" << endl; + m.create_udp_ipv6_socket(); + if(m.join_group("FF02:0:0:0:99:99:99:99",if_nametoindex("eth0"))){ + cout << "join OK!" << endl; + }else{ + cout << "join FAILED!" << endl; + } + sleep(sleepTime); + if(m.leave_group("FF02:0:0:0:99:99:99:99",if_nametoindex("eth0"))){ + cout << "leave OK!" << endl; + }else{ + cout << "leave FAILED!" << endl; + } + + sleep(sleepTime); + cout << "--<3> send Data IPv4 --" << endl; + m.create_udp_ipv4_socket(); + + if(m.choose_if(if_nametoindex("eth0"))){ + cout << "choose if (eth0) OK! " << endl; + }else{ + cout << "choose if (eth0) FAILED! " << endl; + } + + if(m.send_packet("238.99.99.99",9845,msg)){ + cout << "send OK! Hello at addr:238.99.99.99 with port 9845" << endl; + }else{ + cout << "send FAILED!" << endl; + } + + sleep(sleepTime); + + cout << "--<4> send Data IPv6 --" << endl; + m.create_udp_ipv6_socket(); + + if(m.choose_if(if_nametoindex("eth0"))){ + cout << "choose if (eth0) OK! " << endl; + }else{ + cout << "choose if (eth0) FAILED! " << endl; + } + + if(m.send_packet("FF02:0:0:0:99:99:99:99",9845,msg)){ + cout << "send OK! Hello at addr:FF02:0:0:0:99:99:99:99 with port 9845" << endl; + }else{ + cout << "send FAILED!" << endl; + } +} + +mc_socket::~mc_socket() { + HC_LOG_TRACE(""); + + if (is_udp_valid() && m_own_socket) { + close(m_sock); + } +} diff --git a/mcproxy/src/utils/mroute_socket.cpp b/mcproxy/src/utils/mroute_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c312bc903f91d7fbedf499114b4f034840a61610 --- /dev/null +++ b/mcproxy/src/utils/mroute_socket.cpp @@ -0,0 +1,1205 @@ +/* + * This file is part of mcproxy. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * written by Sebastian Woelke, in cooperation with: + * INET group, Hamburg University of Applied Sciences, + * Website: http://mcproxy.realmv6.org/ + */ + + +#include "include/hamcast_logging.h" +#include "include/utils/mroute_socket.hpp" + +#include <netinet/icmp6.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <net/if.h> +#include <errno.h> +#include <arpa/inet.h> +#include <linux/mroute.h> +#include <linux/mroute6.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include <cstdlib> + +#include <cstring> +#include <iostream> + +using namespace std; + +mroute_socket::mroute_socket(){ + HC_LOG_TRACE(""); +} + + +bool mroute_socket::create_raw_ipv4_socket(){ + HC_LOG_TRACE(""); + + if (is_udp_valid()) { + close(m_sock); + } + + // IP-Protokollv4, UDP, Protokoll + m_sock = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + if (m_sock < 0) { + HC_LOG_ERROR("failed to create! Error: " << strerror(errno) << " errno: " << errno); + return false; // failed + } else { + HC_LOG_DEBUG("get socket discriptor number: " << m_sock); + m_addrFamily = AF_INET; + m_own_socket = true; + return true; + } + +} + +bool mroute_socket::create_raw_ipv6_socket(){ + HC_LOG_TRACE(""); + + if (is_udp_valid()) { + close(m_sock); + } + + // IP-Protokollv6, UDP, Protokoll + m_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); //SOCK_DGRAM //IPPROTO_IP + if (m_sock < 0) { + HC_LOG_ERROR("failed to create! Error: " << strerror(errno) << " errno: " << errno); + return false; // failed + } else { + HC_LOG_DEBUG("get socket discriptor number: " << m_sock); + m_addrFamily = AF_INET6; + m_own_socket = true; + return true; + } +} + +bool mroute_socket::set_kernel_table(int table){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ +#ifdef MRT_TABLE + if (setsockopt (m_sock, IPPROTO_IP, MRT_TABLE, &table, sizeof (table)) < 0){ + HC_LOG_ERROR("failed to set kernel table! Error: " << strerror(errno) << " errno: " << errno); + return false; + } +#else + HC_LOG_ERROR("multiple ipv4 multicast routing table not supported: MRT_TABLE not defined"); + return false + +#endif + }else if(m_addrFamily == AF_INET6){ +#ifdef MRT6_TABLE + if (setsockopt (m_sock, IPPROTO_IPV6, MRT6_TABLE, &table, sizeof (table)) < 0){ + HC_LOG_ERROR("failed to set kernel table! Error: " << strerror(errno) << " errno: " << errno); + return false; + } +#else + HC_LOG_ERROR("multiple ipv6 multicast routing table not supported: MRT6_TABLE not defined"); + return false +#endif + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + return true; +} + +bool mroute_socket::set_no_ip_hdr(){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int proto; + if(m_addrFamily == AF_INET){ + proto = IPPROTO_IP; + }else if(m_addrFamily == AF_INET6){ + proto =IPPROTO_IPV6; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + int one = 1; + if (setsockopt (m_sock, proto, IP_HDRINCL, &one, sizeof (one)) < 0){ + HC_LOG_ERROR("failed to set no ip header! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + return true; +} + +u_int16_t mroute_socket::calc_checksum(const unsigned char* buf, int buf_size){ + HC_LOG_TRACE(""); + + u_int16_t* b=(u_int16_t*)buf; + int sum=0; + + for(int i=0; i<buf_size/2;i++){ + ADD_SIGNED_NUM_U16(sum,b[i]); + //sum +=b[i]; + } + + if(buf_size%2==1){ + //sum += buf[buf_size-1]; + ADD_SIGNED_NUM_U16(sum,buf[buf_size-1]); + } + + return ~sum; +} + +bool mroute_socket::set_default_icmp6_checksum_calc(bool enable){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + HC_LOG_ERROR("this funktion is only available vor IPv6 sockets "); + return false; + }else if(m_addrFamily == AF_INET6){ + int offset = enable? 2 : -1; + if (setsockopt (m_sock, IPPROTO_IPV6, IP_HDRINCL, &offset, sizeof (offset)) < 0){ + HC_LOG_ERROR("failed to set default ICMP6 checksum! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + return true; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + +} + +bool mroute_socket::add_extension_header(const unsigned char* buf, unsigned int buf_size){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + HC_LOG_ERROR("this funktion is only available vor IPv6 sockets "); + return false; + }else if(m_addrFamily == AF_INET6){ + int rc= setsockopt(m_sock,IPPROTO_IPV6, IPV6_HOPOPTS, buf, buf_size); + + if(rc == -1){ + HC_LOG_ERROR("failed to add extension header! Error: " << strerror(errno) << " errno: " << errno); + return false; + }else{ + return true; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mroute_socket::set_recv_icmpv6_msg(){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + HC_LOG_ERROR("this funktion is only available vor IPv6 sockets "); + return false; + }else if(m_addrFamily == AF_INET6){ + struct icmp6_filter myfilter; + + //ICMP6_FILTER_SETPASSALL(&myfilter); + ICMP6_FILTER_SETBLOCKALL(&myfilter); + ICMP6_FILTER_SETPASS(MLD_LISTENER_REPORT, &myfilter); + ICMP6_FILTER_SETPASS(MLD_LISTENER_REDUCTION, &myfilter); + + + if(setsockopt(m_sock,IPPROTO_ICMPV6,ICMP6_FILTER, &myfilter,sizeof(myfilter)) < 0){ + HC_LOG_ERROR("failed to set ICMP6 filter! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + return true; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + +} + +bool mroute_socket::set_recv_pkt_info(){ + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + HC_LOG_ERROR("this funktion is only available vor IPv6 sockets "); + return false; + }else if(m_addrFamily == AF_INET6){ + int on = 1; + + if(setsockopt(m_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0){ + HC_LOG_ERROR("failed to set IPV6_RECVPKTINFO! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + return true; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mroute_socket::set_recv_hop_by_hop_msg(){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + if(m_addrFamily == AF_INET){ + HC_LOG_ERROR("this funktion is only available vor IPv6 sockets "); + return false; + }else if(m_addrFamily == AF_INET6){ + int on = 1; + if(setsockopt(m_sock, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &on, sizeof(on)) < 0){ + HC_LOG_ERROR("failed to set IPV6_RECVHOPOPTS! Error: " << strerror(errno) << " errno: " << errno); + return false; + } + + return true; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mroute_socket::set_mrt_flag(bool enable){ + HC_LOG_TRACE("enable: " << enable); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + int proto; + int mrt_cmd; + + if(enable){ + if(m_addrFamily == AF_INET){ + proto = IPPROTO_IP; + mrt_cmd = MRT_INIT; + }else if(m_addrFamily == AF_INET6){ + proto = IPPROTO_IPV6; + mrt_cmd = MRT6_INIT; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + int val=1; + rc = setsockopt(m_sock,proto, mrt_cmd, (void*)&val, sizeof(val)); + + if(rc == -1){ + HC_LOG_ERROR("failed to set MRT flag! Error: " << strerror(errno) << " errno: " << errno); + return false; + }else{ + return true; + } + }else{ + if(m_addrFamily == AF_INET){ + proto = IPPROTO_IP; + mrt_cmd = MRT_DONE; + }else if(m_addrFamily == AF_INET6){ + proto = IPPROTO_IPV6; + mrt_cmd = MRT6_DONE; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + rc = setsockopt(m_sock,proto, mrt_cmd, NULL, 0); + + if(rc == -1){ + HC_LOG_ERROR("failed to reset MRT flag! Error: " << strerror(errno) << " errno: " << errno); + return false; + }else{ + return true; + } + } +} + +//vifNum musst the same uniqueName on delVIF (0 > vifNum < MAXVIF ==32) +//iff_register = true if used for PIM Register encap/decap +bool mroute_socket::add_vif(int vifNum, const char* ifName, const char* ipTunnelRemoteAddr){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + struct vifctl vc; + vifi_t index=if_nametoindex(ifName); + + //VIFF_TUNNEL /* vif represents a tunnel end-point */ + //VIFF_SRCRT /* tunnel uses IP src routing */ + //VIFF_REGISTER /* used for PIM Register encap/decap */ + unsigned char flags; + flags = VIFF_USE_IFINDEX; + + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = vifNum; + vc.vifc_flags = flags; + vc.vifc_threshold = MROUTE_TTL_THRESHOLD; + vc.vifc_rate_limit = MROUTE_RATE_LIMIT_ENDLESS; + vc.vifc_lcl_ifindex =index; + + if(ipTunnelRemoteAddr != NULL){ + if(!inet_pton(AF_INET, ipTunnelRemoteAddr, (void*)&vc.vifc_rmt_addr)>0){ + HC_LOG_ERROR("cannot convert ipTunnelRemoteAddr: " << ipTunnelRemoteAddr); + } + } + + rc = setsockopt(m_sock,IPPROTO_IP,MRT_ADD_VIF,(void *)&vc,sizeof(vc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add VIF! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else if(m_addrFamily == AF_INET6){ + struct mif6ctl mc; + mifi_t index=if_nametoindex(ifName); + + unsigned char flags; + flags = 0; + + memset(&mc, 0, sizeof(mc)); + mc.mif6c_mifi = vifNum; + mc.mif6c_flags = flags; + mc.vifc_rate_limit = MROUTE_RATE_LIMIT_ENDLESS; + mc.vifc_threshold = MROUTE_TTL_THRESHOLD; + mc.mif6c_pifi = index; + + rc = setsockopt(m_sock, IPPROTO_IPV6, MRT6_ADD_MIF, (void *)&mc,sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add VIF! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mroute_socket::del_vif(int vifNum){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + struct vifctl vifc; + memset(&vifc, 0, sizeof(vifc)); + + vifc.vifc_vifi= vifNum; + rc = setsockopt(m_sock, IPPROTO_IP, MRT_DEL_VIF, (char *)&vifc, sizeof(vifc)); + if (rc == -1) { + HC_LOG_ERROR("failed to del VIF! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else if(m_addrFamily == AF_INET6){ + struct mif6ctl mc; + memset(&mc, 0, sizeof(mc)); + + mc.mif6c_mifi = vifNum; + rc = setsockopt(m_sock, IPPROTO_IPV6, MRT6_DEL_MIF, (char *)&mc, sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to del VIF! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } +} + +bool mroute_socket::bind_vif_to_table(const char* ifName, int table){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + ostringstream oss_in; + ostringstream oss_out; + + string cmd; + if(m_addrFamily == AF_INET){ + cmd = "ip mrule"; + }else if(m_addrFamily == AF_INET6){ + cmd = "ip -6 mrule"; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + oss_in << cmd << " add iif " << ifName << " lookup " << table; + oss_out << cmd << " add oif " << ifName << " lookup " << table; + + if(system(oss_in.str().c_str()) != 0 ){ + HC_LOG_ERROR("failed to bind vif to table! Error on cmd: " << oss_in.str()); + return false; + } + + if(system(oss_out.str().c_str()) != 0 ){ + HC_LOG_ERROR("failed to bind vif to table! Error on cmd: " << oss_out.str()); + return false; + } + + return true; +} + + +bool mroute_socket::unbind_vif_form_table(const char* ifName, int table){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + ostringstream oss_in; + ostringstream oss_out; + + string cmd; + if(m_addrFamily == AF_INET){ + cmd = "ip mrule"; + }else if(m_addrFamily == AF_INET6){ + cmd = "ip -6 mrule"; + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + + oss_in << cmd << " del iif " << ifName << " lookup " << table; + oss_out << cmd << " del oif " << ifName << " lookup " << table; + + if(system(oss_in.str().c_str()) != 0 ){ + HC_LOG_ERROR("failed to unbind vif from table! Error on cmd: " << oss_in.str()); + return false; + } + + if(system(oss_out.str().c_str()) != 0 ){ + HC_LOG_ERROR("failed to unbind vif from table! Error on cmd: " << oss_out.str()); + return false; + } + + return true; +} + + +//source_addr is the source address of the received multicast packet +//group_addr group address of the received multicast packet +bool mroute_socket::add_mroute(int input_vifNum, const char* source_addr, const char* group_addr, unsigned int* output_vifTTL, unsigned int output_vifTTL_Ncount){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + struct mfcctl mc; + memset(&mc, 0, sizeof(mc)); + + if(!inet_pton(m_addrFamily, source_addr, &mc.mfcc_origin)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &mc.mfcc_mcastgrp)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + mc.mfcc_parent = input_vifNum; + + if(output_vifTTL_Ncount >= MAXVIFS){ + HC_LOG_ERROR("output_vifNum_size to large: " << output_vifTTL_Ncount); + return false; + } + + for (unsigned int i = 0; i < output_vifTTL_Ncount; i++){ + mc.mfcc_ttls[output_vifTTL[i]] = MROUTE_DEFAULT_TTL; + } + + rc = setsockopt(m_sock, IPPROTO_IP, MRT_ADD_MFC,(void *)&mc, sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add multicast route! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else if(m_addrFamily == AF_INET6){ + struct mf6cctl mc; + memset(&mc, 0, sizeof(mc)); + + if(!inet_pton(m_addrFamily, source_addr, &mc.mf6cc_origin.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &mc.mf6cc_mcastgrp.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + mc.mf6cc_parent = input_vifNum; + + if(output_vifTTL_Ncount >= MAXMIFS){ + HC_LOG_ERROR("output_vifNum_size to large: " << output_vifTTL_Ncount); + return false; + } + + for (unsigned int i = 0; i < output_vifTTL_Ncount; i++){ + IF_SET(output_vifTTL[i],&mc.mf6cc_ifset); + } + + rc = setsockopt(m_sock, IPPROTO_IPV6, MRT6_ADD_MFC, (void*)&mc, sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add multicast route! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + +} + +bool mroute_socket::del_mroute(int input_vifNum, const char* source_addr, const char* group_addr){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + struct mfcctl mc; + memset(&mc, 0, sizeof(mc)); + + if(!inet_pton(m_addrFamily, source_addr, &mc.mfcc_origin)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &mc.mfcc_mcastgrp)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + mc.mfcc_parent = input_vifNum; + + rc = setsockopt(m_sock, IPPROTO_IP, MRT_DEL_MFC,(void *)&mc, sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add multicast route! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else if(m_addrFamily == AF_INET6){ + struct mf6cctl mc; + memset(&mc, 0, sizeof(mc)); + + if(!inet_pton(m_addrFamily, source_addr, &mc.mf6cc_origin.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &mc.mf6cc_mcastgrp.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + mc.mf6cc_parent = input_vifNum; + + rc = setsockopt(m_sock, IPPROTO_IPV6, MRT6_DEL_MFC,(void *)&mc, sizeof(mc)); + if (rc == -1) { + HC_LOG_ERROR("failed to add multicast route! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + return false; +} + +bool mroute_socket::get_vif_stats(int vif_index, struct sioc_vif_req* req_v4, struct sioc_mif_req6* req_v6){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + if(req_v4 != NULL){ + + req_v4->vifi = vif_index; + + rc = ioctl(m_sock, SIOCGETVIFCNT, req_v4); + if (rc == -1) { + HC_LOG_ERROR("failed to get vif stats! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else{ + HC_LOG_ERROR("failed to get vif stats! Error: claimed parameter req_v4 is null"); + return false; + } + }else if(m_addrFamily == AF_INET6){ + if(req_v6 != NULL){ + + req_v6->mifi = vif_index; + + rc = ioctl(m_sock, SIOCGETMIFCNT_IN6, req_v6); + if (rc == -1) { + HC_LOG_ERROR("failed to get vif stats! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else{ + HC_LOG_ERROR("failed to get vif stats! Error: claimed parameter req_v6 is null"); + return false; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + return false; +} + +bool mroute_socket::get_mroute_stats(const char* source_addr, const char* group_addr, struct sioc_sg_req* sgreq_v4, struct sioc_sg_req6* sgreq_v6){ + HC_LOG_TRACE(""); + + if (!is_udp_valid()) { + HC_LOG_ERROR("raw_socket invalid"); + return false; + } + + int rc; + + if(m_addrFamily == AF_INET){ + if(sgreq_v4 != NULL){ + + if(!inet_pton(m_addrFamily, source_addr, &sgreq_v4->src)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &sgreq_v4->grp)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + rc = ioctl(m_sock, SIOCGETSGCNT, sgreq_v4);; + if (rc == -1) { + HC_LOG_ERROR("failed to get multicast route stats! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + + }else{ + HC_LOG_ERROR("failed to get multicast route stats! Error: claimed parameter sgreq_v4 is null"); + return false; + } + }else if(m_addrFamily == AF_INET6){ + if(sgreq_v6 != NULL){ + + memset(sgreq_v6,0,sizeof(struct sioc_sg_req6)); + + if(!inet_pton(m_addrFamily, source_addr, &sgreq_v6->src.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert source_addr: " << source_addr); + return false; + } + + if(!inet_pton(m_addrFamily, group_addr, &sgreq_v6->grp.sin6_addr)>0){ + HC_LOG_ERROR("cannot convert group_addr: " << group_addr); + return false; + } + + rc = ioctl(m_sock, SIOCGETSGCNT_IN6, sgreq_v6); + if (rc == -1) { + HC_LOG_ERROR("failed to get multicast route stats! Error: " << strerror(errno) << " errno: " << errno); + return false; + } else { + return true; + } + }else{ + HC_LOG_ERROR("failed to get multicast route stats! Error: claimed parameter sgreq_v6 is null"); + return false; + } + }else{ + HC_LOG_ERROR("wrong address family"); + return false; + } + return false; +} + +void mroute_socket::print_vif_stats(int vif_index){ + HC_LOG_TRACE(""); + + cout << "##-- vif stats --##" << endl; + cout << " -vif_index:" << vif_index << endl; + + if(m_addrFamily == AF_INET){ + sioc_vif_req req; + if(!get_vif_stats(vif_index, &req, NULL)){ + cout << "failed to get vif stats" << endl; + return; + } + + cout << " -In packets[" << req.ibytes << " bytes]:" << req.icount << endl; + cout << " -Out packets[" << req.obytes << " bytes]:" << req.ocount << endl; + + }else if(m_addrFamily == AF_INET6){ + struct sioc_mif_req6 req; + if(!get_vif_stats(vif_index, NULL, &req)){ + cout << "failed to get vif stats" << endl; + return; + } + + cout << " -In packets[" << req.ibytes << " bytes]:" << req.icount << endl; + cout << " -Out packets[" << req.obytes << " bytes]:" << req.ocount << endl; + + }else{ + HC_LOG_ERROR("wrong address family"); + cout << "wrong address family" << endl; + } +} + +void mroute_socket::print_mroute_stats(const char* source_addr, const char* group_addr){ + HC_LOG_TRACE(""); + + cout << "##-- mroute states --##" << endl; + cout << " -src: " << source_addr << " to grp: " << group_addr << endl; + + if(m_addrFamily == AF_INET){ + struct sioc_sg_req req; + if(!get_mroute_stats(source_addr, group_addr, &req, NULL)){ + cout << "failed to get mroute stats" << endl; + return; + } + + cout << " -packets[" << req.bytecnt << " bytes]:" << req.pktcnt << endl; + cout << " -wrong packets:" << req.wrong_if << endl; + + }else if(m_addrFamily == AF_INET6){ + struct sioc_sg_req6 req; + if(!get_mroute_stats(source_addr, group_addr, NULL, &req)){ + cout << "failed to get mroute stats" << endl; + return; + } + + cout << " -packets[" << req.bytecnt << " bytes]:" << req.pktcnt << endl; + cout << " -wrong packets:" << req.wrong_if << endl; + + }else{ + HC_LOG_ERROR("wrong address family"); + cout << "wrong address family" << endl; + } +} + +void mroute_socket::print_struct_mf6cctl(struct mf6cctl* mc){ + HC_LOG_TRACE(""); + + char addressBuffer[INET6_ADDRSTRLEN]; + + cout << "##-- mf6cctl --##" << endl; + cout << " -mf6cc_parent: " << mc->mf6cc_parent << endl; + cout << " -mcastgrp: " << inet_ntop(AF_INET6, &mc->mf6cc_mcastgrp.sin6_addr, addressBuffer, sizeof(addressBuffer)) << endl; + cout << " -mcastorigin: " << inet_ntop(AF_INET6, &mc->mf6cc_origin.sin6_addr, addressBuffer, sizeof(addressBuffer)) << endl; + + cout << " -mf6cc_ifset: "; + for (int i = 0; i < MAXMIFS; i++) { + if (IF_ISSET(i, &mc->mf6cc_ifset)){ + cout << i << "; "; + } + } + cout << endl; +} + +void mroute_socket::test_mcrouter_mrt_flag(){ + HC_LOG_TRACE(""); + + int sleepTime = 1; + mroute_socket m; + mroute_socket m1; + + cout << "--<1> set MRT flag ipv4 --" << endl; + m.create_raw_ipv4_socket(); + if(m.set_mrt_flag(true)){ + cout << "set OK!" << endl; + }else{ + cout << "set FAILED!" << endl; + } + + sleep(sleepTime); + + cout << "-- reset MRT flag ipv4 --" << endl; + if(m.set_mrt_flag(false)){ + cout << "reset OK!" << endl; + }else{ + cout << "reset FAILED!" << endl; + } + + sleep(sleepTime); + + cout << "-- set MRT flag ipv4 again --" << endl; + m.create_raw_ipv4_socket(); + if(m.set_mrt_flag(true)){ + cout << "set OK!" << endl; + }else{ + cout << "set FAILED!" << endl; + } + + cout << "--<2> set MRT flag ipv6 --" << endl; + m.create_raw_ipv6_socket(); + if(m.set_mrt_flag(true)){ + cout << "set OK!" << endl; + }else{ + cout << "set FAILED!" << endl; + } + + sleep(sleepTime); + + cout << "-- reset MRT flag ipv6 --" << endl; + if(m.set_mrt_flag(false)){ + cout << "reset OK!" << endl; + }else{ + cout << "reset FAILED!" << endl; + } + + sleep(sleepTime); + + cout << "--<3> error test set 2x MRT flag ipv4 --" << endl; + m.create_raw_ipv4_socket(); + m1.create_raw_ipv4_socket(); + if(m.set_mrt_flag(true)){ + cout << "set 1 OK!" << endl; + }else{ + cout << "set 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(true)){ + cout << "set 2 OK! ==> FAILED!" << endl; + }else{ + cout << "set 2 FAILED! ==> OK!" << endl; + } + + sleep(sleepTime); + + if(m.set_mrt_flag(false)){ + cout << "reset 1 OK!" << endl; + }else{ + cout << "reset 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(false)){ + cout << "reset 2 OK! ==> FAILED!" << endl; + }else{ + cout << "reset 2 FAILED! ==> OK!" << endl; + } + + sleep(sleepTime); + + cout << "--<4> error test set 2x MRT flag ipv6 --" << endl; + m.create_raw_ipv6_socket(); + m1.create_raw_ipv6_socket(); + if(m.set_mrt_flag(true)){ + cout << "set 1 OK!" << endl; + }else{ + cout << "set 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(true)){ + cout << "set 2 OK! ==> FAILED" << endl; + }else{ + cout << "set 2 FAILED! ==> OK!" << endl; + } + + sleep(sleepTime); + + if(m.set_mrt_flag(false)){ + cout << "reset 1 OK!" << endl; + }else{ + cout << "reset 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(false)){ + cout << "reset 2 OK! ==> FAILED!" << endl; + }else{ + cout << "reset 2 FAILED! ==> OK!" << endl; + } + + sleep(sleepTime); + + cout << "--<5> error test set 2x MRT flag ipv4&ipv6 --" << endl; + m.create_raw_ipv4_socket(); + m1.create_raw_ipv6_socket(); + if(m.set_mrt_flag(true)){ + cout << "set 1 OK!" << endl; + }else{ + cout << "set 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(true)){ + cout << "set 2 OK!" << endl; + }else{ + cout << "set 2 FAILED!" << endl; + } + + sleep(sleepTime); + + if(m.set_mrt_flag(false)){ + cout << "reset 1 OK!" << endl; + }else{ + cout << "reset 1 FAILED!" << endl; + } + + if(m1.set_mrt_flag(false)){ + cout << "reset 2 OK!" << endl; + }else{ + cout << "reset 2 FAILED!" << endl; + } + +} + +void mroute_socket::test_add_vifs(mroute_socket* m){ + HC_LOG_TRACE(""); + + int if_one = MROUTE_SOCKET_IF_NUM_ONE; + string str_if_one = MROUTE_SOCKET_IF_STR_ONE; + int if_two = MROUTE_SOCKET_IF_NUM_TWO; + string str_if_two = MROUTE_SOCKET_IF_STR_TWO; + + + cout << "-- addVIFs test --" << endl; + if(m->add_vif(if_one, str_if_one.c_str(),NULL)){ + cout << "addVIF " << str_if_one << " OK!" << endl; + }else{ + cout << "addVIF " << str_if_one << " FAILED!" << endl; + } + + if(m->add_vif(if_two, str_if_two.c_str(),NULL)){ + cout << "addVIF " << str_if_two << " OK!" << endl; + }else{ + cout << "addVIF " << str_if_two << " FAILED!" << endl; + } + + + /*if(m->addVIF(if_three, str_if_three.c_str(),false,false,false,NULL)){ + cout << "addVIF " << str_if_three << " OK!" << endl; + }else{ + cout << "addVIF " << str_if_three << " FAILED!" << endl; + }*/ + +} + + +void mroute_socket::test_del_vifs(mroute_socket* m){ + HC_LOG_TRACE(""); + + int if_one = MROUTE_SOCKET_IF_NUM_ONE; + int if_two = MROUTE_SOCKET_IF_NUM_TWO; + + cout << "-- delVIFs test--" << endl; + if(m->del_vif(if_one)){ + cout << "delVIF OK!" << endl; + }else{ + cout << "delVIF FAILED!" << endl; + } + + if(m->del_vif(if_two)){ + cout << "delVIF OK!" << endl; + }else{ + cout << "delVIF FAILED!" << endl; + } +} + +void mroute_socket::test_add_route(mroute_socket* m){ + HC_LOG_TRACE(""); + + const char* src_addr; + const char* g_addr; + int if_one = MROUTE_SOCKET_IF_NUM_ONE; + string str_if_one = MROUTE_SOCKET_IF_STR_ONE; + int if_two = MROUTE_SOCKET_IF_NUM_TWO; + string str_if_two = MROUTE_SOCKET_IF_STR_TWO; + + //int if_three = MROUTE_SOCKET_IF_NUM_THREE; + + if(m->get_addr_family() == AF_INET){ + src_addr= MROUTE_SOCKET_SRC_ADDR_V4; + g_addr = MROUTE_SOCKET_G_ADDR_V4; + }else if(m->get_addr_family() == AF_INET6){ + src_addr = MROUTE_SOCKET_SRC_ADDR_V6; + g_addr = MROUTE_SOCKET_G_ADDR_V6; + }else{ + cout << "FAILED to start test wrong addrFamily: "<< m->get_addr_family() << endl; + return; + } + + cout << "-- addRoute test --" << endl; + unsigned int output_vifs[]={/*if_three,*/ if_two}; //if_two + if(m->add_mroute(if_one, src_addr, g_addr ,output_vifs, sizeof(output_vifs)/sizeof(output_vifs[0]))){ + cout << "addRoute (" << str_if_one << " ==> " << str_if_two << ") OK!" << endl; + }else{ + cout << "addRoute (" << str_if_one << " ==> " << str_if_two << ") FAILED!" << endl; + } +} + +void mroute_socket::test_del_route(mroute_socket* m){ + HC_LOG_TRACE(""); + + const char* src_addr; + const char* g_addr; + int if_one = MROUTE_SOCKET_IF_NUM_ONE; + string str_if_one = MROUTE_SOCKET_IF_STR_ONE; + string str_if_two = MROUTE_SOCKET_IF_STR_TWO; + + if(m->get_addr_family() == AF_INET){ + src_addr= MROUTE_SOCKET_SRC_ADDR_V4; + g_addr = MROUTE_SOCKET_G_ADDR_V4; + }else if(m->get_addr_family() == AF_INET6){ + src_addr = MROUTE_SOCKET_SRC_ADDR_V6; + g_addr = MROUTE_SOCKET_G_ADDR_V6; + }else{ + cout << "FAILED to start test wrong addrFamily: "<< m->get_addr_family() << endl; + return; + } + + cout << "-- delRoute test --" << endl; + if(m->del_mroute(if_one, src_addr, g_addr)){ + cout << "delMRoute (" << str_if_one << " ==> " << str_if_two << ") OK!" << endl; + }else{ + cout << "delMRoute (" << str_if_one << " ==> " << str_if_two << ") FAILED!" << endl; + } +} + +void mroute_socket::test_mcrouter_vifs_routes(int addrFamily){ + HC_LOG_TRACE(""); + + mroute_socket m; + + int sleepTime = 1; + + if(addrFamily == AF_INET){ + m.create_raw_ipv4_socket(); + }else if(addrFamily == AF_INET6){ + m.create_raw_ipv6_socket(); + }else{ + cout << "FAILED to start test wrong addrFamily: "<< addrFamily << endl; + return; + } + + cout << "-- set mrt flag --" << endl; + if(m.set_mrt_flag(true)){ + cout << "set MRT flag OK!" << endl; + }else{ + cout << "set MRT flag FAILED!" << endl; + } + + m.test_add_vifs(&m); + + sleep(sleepTime); + + m.test_add_route(&m); + + m.test_del_route(&m); + + m.test_del_vifs(&m); + + cout << "-- reset mrt flag --" << endl; + if(m.set_mrt_flag(false)){ + cout << "reset MRT flag OK!" << endl; + }else{ + cout << "reset MRT flag FAILED!" << endl; + } + + sleep(sleepTime); +} + +mroute_socket::~mroute_socket() { + HC_LOG_TRACE(""); +}