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 &copy);
+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 &copy);
+
+     //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(&current_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("");
+}