First version of new http/txt server for OLSR.
authorHenning Rogge <hrogge@googlemail.com>
Tue, 26 May 2009 09:42:44 +0000 (11:42 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Tue, 26 May 2009 09:42:44 +0000 (11:42 +0200)
Txtinfo has already be changed to new server API.

37 files changed:
Makefile
README-acl [new file with mode: 0644]
README-http-txt-services [new file with mode: 0644]
files/Makefile
files/olsrd-manpages.xml
files/olsrd-metrics.3.gz
files/olsrd.8.gz
files/olsrd.conf.5.gz
lib/debuginfo/Makefile [new file with mode: 0644]
lib/debuginfo/README_DEBUGINFO [new file with mode: 0644]
lib/debuginfo/src/olsrd_debuginfo.c [new file with mode: 0644]
lib/debuginfo/src/olsrd_debuginfo.h [new file with mode: 0644]
lib/debuginfo/version-script.txt [new file with mode: 0644]
lib/txtinfo/Makefile
lib/txtinfo/README_TXTINFO
lib/txtinfo/src/olsrd_plugin.c [deleted file]
lib/txtinfo/src/olsrd_txtinfo.c
lib/txtinfo/src/olsrd_txtinfo.h
src/common/autobuf.c
src/common/autobuf.h
src/common/avl.c
src/common/avl.h
src/ipcalc.c
src/ipcalc.h
src/main.c
src/olsr_cfg.c
src/olsr_cfg.h
src/olsr_cfg_data.c
src/olsr_cfg_data.h
src/olsr_comport.c [new file with mode: 0644]
src/olsr_comport.h [new file with mode: 0644]
src/olsr_comport_http.c [new file with mode: 0644]
src/olsr_comport_http.h [new file with mode: 0644]
src/olsr_comport_txt.c [new file with mode: 0644]
src/olsr_comport_txt.h [new file with mode: 0644]
src/plugin_util.c
src/scheduler.c

index 2d78866..7a97ce8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -150,9 +150,9 @@ ifeq ($(OS),linux)
 SUBDIRS = $(notdir $(shell find lib -maxdepth 2 -name Makefile -not -path lib/Makefile -printf "%h\n"|sort))
 else
 ifeq ($(OS),win32)
-SUBDIRS := dot_draw httpinfo lq_etx_ff lq_etx_float lq_etx_fpm lq_rfc mini secure txtinfo watchdog
+SUBDIRS := debug dot_draw httpinfo lq_etx_ff lq_etx_float lq_etx_fpm lq_rfc mini secure txtinfo watchdog
 else
-SUBDIRS := bmf dot_draw dyn_gw dyn_gw_plain httpinfo lq_etx_ff lq_etx_float lq_etx_fpm lq_rfc mdns mini nameservice secure txtinfo watchdog
+SUBDIRS := bmf debuginfo dot_draw dyn_gw dyn_gw_plain httpinfo lq_etx_ff lq_etx_float lq_etx_fpm lq_rfc mdns mini nameservice secure txtinfo watchdog
 endif
 endif
 
@@ -231,6 +231,11 @@ watchdog:
                $(MAKECMD) -C lib/watchdog
                $(MAKECMD) -C lib/watchdog DESTDIR=$(DESTDIR) install
 
+debuginfo:
+               $(MAKECMD) -C lib/debuginfo clean
+               $(MAKECMD) -C lib/debuginfo
+               $(MAKECMD) -C lib/debuginfo DESTDIR=$(DESTDIR) install
+
 txtinfoshell:
        $(MAKECMD) -C contrib/txtinfoshell
 
diff --git a/README-acl b/README-acl
new file mode 100644 (file)
index 0000000..f38131f
--- /dev/null
@@ -0,0 +1,43 @@
+   Using access control lists in OLSRd
+=========================================
+
+Several plugins in OLSRd allow you to limit the access to
+their server functions by IP. This file will explain how to
+use the ACL features.
+The access is controlled by two lists of ip
+addresses and ip networks, a blacklist (reject list) and
+a whitelist (accept list). Two binary flags control which
+list is to be used first and what should be the default
+reaction to an unknown IP.
+
+The parameter "accept" contains an IP address or network
+which is allowed to access the service, the parameter "reject"
+contains a IP/network which is NOT allow to access it.
+
+The parameter "checkfirst" tells the service which of the
+two lists have to be checked first.
+The default setting is "reject".
+
+The last parameter "defaultpolicy" controls what the server
+should do with IPs which are not found in BOTH lists.
+The default setting is "reject".
+
+
+   Examples for ACL usage
+============================
+
+Examples for parameters accept/reject:
+PlParam   "accept"   "10.0.0.0/8" 
+PlParam   "reject"   "10.0.0.1" 
+PlParam   "accept"   "10.0.0.0 255.0.0.0" 
+
+Examples for parameters for binary flags
+PlParam   "checkfirst"      "reject"
+PlParam   "defaultpolicy"   "accept"
+
+
+   Legacy parameters
+=======================
+The old parameters "host", "host4", "host6", "net", "net4"
+and "net6" are just alias names for "accept".
diff --git a/README-http-txt-services b/README-http-txt-services
new file mode 100644 (file)
index 0000000..d88a02e
--- /dev/null
@@ -0,0 +1,85 @@
+   HTTP/Telnet services in olsrd
+===================================
+
+Olsrd contains an integrated telnet and http server core, which is
+used by plugins and the core to provide easy access the html pages
+and text commands.
+
+
+   HTTP services
+-------------------
+
+The http server core supports both GET and POST parameter processing,
+allows the plugin/provider to set up a ACL and provides http basic
+password authentification (should be used together with an https proxy
+for security).
+
+Plugins use the function olsr_com_add_htmlsite() to set up a static
+webpage for a filename or a whole path, the function
+olsr_com_add_htmlhandler() can be used to set up a callback for dynamic
+webpage generation.
+
+olsr_com_set_htmlsite_acl_auth() can be used on the returned
+olsr_html_site pointer from one of the "add" functions to set up an
+ip ACL and/or a list of username/passwords. The username/password
+strings must be base64 encoded as defined in the http basic
+authentification standard.
+(see  http://en.wikipedia.org/wiki/Basic_access_authentication )
+
+
+   Telnet services
+---------------------
+
+The telnet server implements a simple text interface to the olsr core,
+which can be equipped with any number of commands.
+
+The first way to use a telnet command is to enter the commands name,
+followed by it's parameters (similar to a normal console). After the
+command is finished, a new prompt will be displayed and you can
+enter another command.
+
+The second way is to prefix a command with a '/' character. No parameters
+can be used in this mode, but multiple commands can be concatenated in
+a single line. After the last command finished the telnet server will
+hang up. This mode emulates the commands of the old txtinfo plugin.
+
+Some commands will not stop after a predefined output but will continue
+to output data to the console. They can be stopped by sending a single
+character to the telnet server.
+
+The server will hang up the connection if no input/output happens for
+a certain period of time (default 120 seconds).
+
+
+   Builtin telnet commands
+-----------------------------
+
+"quit" or "exit":
+  Ends the telnet session and hangup the connection.
+
+"help":
+  Displays a list of available commands.
+
+"help <commandname>":
+  Displays a help text for a certain command (if available).
+
+"csv":
+  Activates the csv (comma separated value) output mode. All
+  commands capable to use this flag will switch to a CSV output
+  format.
+
+"csvoff"
+  Deactivates the csv output mode.
+
+"timeout <seconds>":
+  Sets the telnet session timeout to a new value. A parameter
+  of '0' will deactivate the timeout.
+
+"version"
+  Displays a version string of the olsrd.
+
+"repeat <seconds> <command and parameters>":
+  Calls another internal command every few seconds. Of course
+  the other command must not be one with continous output
+  itself.
+  
\ No newline at end of file
index ecba634..4446276 100644 (file)
@@ -42,7 +42,7 @@ MANS += olsrd-metrics.3
 
 # Requires 'apt-get install docbook2x docbook-xml'
 $(MANS): olsrd-manpages.xml
-       docbook2x-man --solinks $^
+       docbook2man.pl --solinks $^
        gzip -f $(patsubst %.gz,%, $(MANS))
 
 # Requires 'apt-get install docbook-utils'
index 9d86f0c..900d08e 100644 (file)
 
         <email>sven-olaægmx.de</email>
       </author>
+      <author>
+        <firstname>Henning</firstname>
+        <surname>Rogge</surname>
+        <email>hrogge@googlemail.com</email>
+      </author>
     </authorgroup>
 
     <abstract>
           </group>
 
           <group>
-            <arg>-X</arg>
-
-            <arg>--dispin</arg>
-          </group>
-
-          <group>
-            <arg>-O</arg>
-
-            <arg>--dispout</arg>
-          </group>
-
-          <group>
             <arg>-D</arg>
 
             <arg>--delgw</arg>
           <listitem>
             <para>Specifies the amount of debug information to be printed out
             during operation. If set to 0, <productname>olsrd</productname>
-            will run in the background.</para>
+            will run in the background unless you use the nofork option.</para>
           </listitem>
         </varlistentry>
 
         </varlistentry>
 
         <varlistentry>
-          <term><option>-X</option> or <option>--dispin</option></term>
-
-          <listitem>
-            <para>This option causes <productname>olsrd</productname> to
-            display all incoming packet data.</para>
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
-          <term><option>-O</option> or <option>--dispout</option></term>
-
-          <listitem>
-            <para>This option causes <productname>olsrd</productname> to
-            display all outgoing packet data.</para>
-          </listitem>
-        </varlistentry>
-
-        <varlistentry>
           <term><option>-D</option> or <option>--delgw</option></term>
 
           <listitem>
         </varlistentry>
 
         <varlistentry>
-          <term><option>-L options</option> or
-          <option>--log=options</option></term>
+          <term><option>--log_debug=options</option></term>
 
           <listitem>
             <para>This option controls the output of the logging system of
-            olsrd. The options are a comma-separated string of keys and
-            key/value pairs. Activating a lower level logging output (DEBUG,
-            WARN, INFO, ERROR) will automatically activate all higher level
-            outputs of the source too. All error messages will be activated
-            unless one or multiple log sources are specified for error logging
-            level.</para>
-
-            <variablelist>
-              <varlistentry>
-                <term><option>list</option></term>
-
-                <listitem>
-                  <para>lists all implemented log sources and log targets.
-                  <productname>olsrd</productname> terminates after displaying
-                  this values.</para>
-                </listitem>
-              </varlistentry>
-
-              <varlistentry>
-                <term><option>stderr</option></term>
-
-                <listitem>
-                  <para>activates stderr as a logging target. If no target is
-                  activated, stderr is considered the default target.</para>
-                </listitem>
-              </varlistentry>
-
-              <varlistentry>
-                <term><option>syslog</option></term>
-
-                <listitem>
-                  <para>activates the syslog as a logging target.</para>
-                </listitem>
-              </varlistentry>
-
-              <varlistentry>
-                <term><option>file=[filename]</option></term>
-
-                <listitem>
-                  <para>activates a user specified file as a logging target.
-                  All logging output will be appended to the file.</para>
-                </listitem>
-              </varlistentry>
-
-              <varlistentry>
-                <term><option>debug=[logsource1/logsource2/...]</option></term>
-
-                <listitem>
-                  <para>activates the debug output for a number of logfiles.
-                  Debugging output will display lots of internal information
-                  about a logging source, so be careful to activate too many
-                  sources. If not specified, debug output is switched
-                  off.</para>
-                </listitem>
-              </varlistentry>
-
-              <varlistentry>
-                <term><option>info=[logsource1/logsource2/...]</option></term>
-
-                <listitem>
-                  <para>activates information output for a number of logfiles.
-                  Information output will display a small amount of data about
-                  the log source. If not specified, information output is
-                  switched off.</para>
-                </listitem>
-              </varlistentry>
+            olsrd. The options are a comma-separated string of log sources
+            which should produce DEBUG level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_info=options</option></term>
 
-              <varlistentry>
-                <term><option>warn=[logsource1/logsource2/...]</option></term>
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce INFO level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_warn=options</option></term>
 
-                <listitem>
-                  <para>activates warnings for a number of logfiles. Warnings
-                  are generated when an error has happened within the logging
-                  source, but <productname>olsrd</productname> can recover
-                  from the problem and continue to run. If not specified,
-                  warning output is switched off.</para>
-                </listitem>
-              </varlistentry>
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce WARN level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_error=options</option></term>
 
-              <varlistentry>
-                <term><option>error=[logsource1/logsource2/...]</option></term>
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce ERROR level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_stderr</option></term>
+          
+          <listitem>
+            <para>This option activates log output to stderr. If no target is
+            activated, stderr is considered the default target.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_syslog</option></term>
+          
+          <listitem>
+            <para>This option activates log output to the syslog.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--log_file=filename</option></term>
+          
+          <listitem>
+            <para>This option activates log output to a file.
+            </para>
+          </listitem>
+        </varlistentry>
 
-                <listitem>
-                  <para>activates errors for a number of logfiles. Most errors
-                  are generated if an unrecoverable problem happens, so
-                  <productname>olsrd</productname> will shut down most times
-                  after an error. If not specified, error output is
-                  activated.</para>
-                </listitem>
-              </varlistentry>
-            </variablelist>
+        <varlistentry>
+          <term><option>--olsrport=portnumber</option></term>
+          
+          <listitem>
+            <para>This option sets the port for the OLSR protocol messages.
+            Default value is 698.
+            </para>
           </listitem>
         </varlistentry>
 
         <varlistentry>
+          <term><option>--dlpath=path</option></term>
+          
+          <listitem>
+            <para>This option tells <productname>olsrd</productname> to
+            load all dynamic libraries from a certain path.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--httpport=portnumber</option></term>
+          
+          <listitem>
+            <para>This option sets the listening port for http services.
+            Default value is 8080.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--httplimit=connectioncount</option></term>
+          
+          <listitem>
+            <para>This option sets the maximum number of simultanous
+            http sessions. Default value is 3.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--txtport=portnumber</option></term>
+          
+          <listitem>
+            <para>This option sets the listening port for telnet services.
+            Default value is 2006.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>--txtlimit=connectioncount</option></term>
+          
+          <listitem>
+            <para>This option sets the maximum number of simultanous
+            telnet sessions. Default value is 3.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
           <term><option><replaceable>interface1</replaceable>
           interface2...</option></term>
 
           <replaceable>0</replaceable>-<replaceable>9</replaceable></term>
 
           <listitem>
-            <para>Controls the amount of debug output
-            <productname>olsrd</productname> prints out. If set to
+            <para>This option is legacy support for the new
+            <productname>olsrd</productname> logging system. If set to
             <replaceable>0</replaceable>, <productname>olsrd</productname>
             will detach from the current process and run in the background. A
-            value of <replaceable>9</replaceable> yields a maximum of debug
-            output. Defaults to <replaceable>0</replaceable>.</para>
+            value of <replaceable>3</replaceable> yields a maximum of log
+            output, a value of <replaceable>-2</replaceable> will mean no log
+            output at all, not even error messages.
+            Defaults to <replaceable>0</replaceable>.</para>
           </listitem>
         </varlistentry>
 
             loss when the first interface of a router vanishes.</para>
           </listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><option>Log_debug=options</option></term>
+
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce DEBUG level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_info=options</option></term>
+
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce INFO level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_warn=options</option></term>
+
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce WARN level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_error=options</option></term>
+
+          <listitem>
+            <para>This option controls the output of the logging system of
+            olsrd. The options are a comma-separated string of log sources
+            which should produce ERROR level output (if available). Call
+            <productname>olsrd</productname> with parameter
+            <option>--help=log</option> for a complete list of debug sources.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_stderr</option></term>
+          
+          <listitem>
+            <para>This option activates log output to stderr. If no target is
+            activated, stderr is considered the default target.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_syslog</option></term>
+          
+          <listitem>
+            <para>This option activates log output to the syslog.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>Log_file=filename</option></term>
+          
+          <listitem>
+            <para>This option activates log output to a file.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><option>Dlpath=path</option></term>
+          
+          <listitem>
+            <para>This option tells <productname>olsrd</productname> to
+            load all dynamic libraries from a certain path.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>HttpPort=portnumber</option></term>
+          
+          <listitem>
+            <para>This option sets the listening port for http services.
+            Default value is 8080.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>HttpLimit=connectioncount</option></term>
+          
+          <listitem>
+            <para>This option sets the maximum number of simultanous
+            http sessions. Default value is 3.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>TxtPort=portnumber</option></term>
+          
+          <listitem>
+            <para>This option sets the listening port for telnet services.
+            Default value is 2006.
+            </para>
+          </listitem>
+        </varlistentry>
+        
+        <varlistentry>
+          <term><option>TxtLimit=connectioncount</option></term>
+          
+          <listitem>
+            <para>This option sets the maximum number of simultanous
+            telnet sessions. Default value is 3.
+            </para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect1>
 
index 8d1ecd5..8505662 100644 (file)
Binary files a/files/olsrd-metrics.3.gz and b/files/olsrd-metrics.3.gz differ
index fc3f494..89538ec 100644 (file)
Binary files a/files/olsrd.8.gz and b/files/olsrd.8.gz differ
index f381be4..748f7b6 100644 (file)
Binary files a/files/olsrd.conf.5.gz and b/files/olsrd.conf.5.gz differ
diff --git a/lib/debuginfo/Makefile b/lib/debuginfo/Makefile
new file mode 100644 (file)
index 0000000..8eb10e4
--- /dev/null
@@ -0,0 +1,56 @@
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+# * Neither the name of olsr.org, olsrd nor the names of its
+#   contributors may be used to endorse or promote products derived
+#   from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Visit http://www.olsr.org for more information.
+#
+# If you find this software useful feel free to make a donation
+# to the project. For more information see the website or contact
+# the copyright holders.
+#
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_debuginfo
+PLUGIN_VER =   0.1
+
+TOPDIR =       ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
diff --git a/lib/debuginfo/README_DEBUGINFO b/lib/debuginfo/README_DEBUGINFO
new file mode 100644 (file)
index 0000000..561479b
--- /dev/null
@@ -0,0 +1,34 @@
+   PLUGIN CONFIGURATION
+==========================
+
+The plugin accepts all parameters for an OLSRD "access
+control list". See README-acl for details.
+
+There are no futher parameters.
+
+   A configuration example
+-----------------------------
+
+LoadPlugin "olsrd_debuginfo.so.0.1"
+{
+    PlParam     "checkfirst"    "reject"
+    PlParam     "defaultpolicy" "reject"
+    PlParam     "accept"   "10.0.0.0/8"
+    PlParam     "reject"   "10.0.1.123"
+}
+
+This will allow access from the network
+10.0.0.0/8, but not from 10.0.1.123.
+access is always allowed from 127.0.0.1(localhost).
+
+
+   PLUGIN USAGE
+==================
+
+The plugin commands are "cookies" and "stats".
+All commands support both normal and csv mode.
+
+The plugin commands are used through the normal OLSR
+telnet server. See README-http-txt-services for details.
+
+- Henning Rogge
diff --git a/lib/debuginfo/src/olsrd_debuginfo.c b/lib/debuginfo/src/olsrd_debuginfo.c
new file mode 100644 (file)
index 0000000..11aab7f
--- /dev/null
@@ -0,0 +1,356 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+#include "olsr.h"
+#include "ipcalc.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "mpr_selector_set.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "routing_table.h"
+#include "log.h"
+#include "misc.h"
+#include "olsr_ip_prefix_list.h"
+#include "parser.h"
+#include "olsr_comport_txt.h"
+#include "olsrd_debuginfo.h"
+
+#include "common/autobuf.h"
+
+#define PLUGIN_NAME    "OLSRD debuginfo plugin"
+#define PLUGIN_VERSION "0.1"
+#define PLUGIN_AUTHOR   "Henning Rogge"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+struct debuginfo_cmd {
+  const char *name;
+  olsr_txthandler handler;
+  struct olsr_txtcommand *normal, *csv;
+};
+
+static void debuginfo_new(void) __attribute__ ((constructor));
+static void debuginfo_delete(void) __attribute__ ((destructor));
+
+static enum olsr_txtcommand_result debuginfo_stat(struct comport_connection *con,  char *cmd, char *param);
+static enum olsr_txtcommand_result debuginfo_cookies(struct comport_connection *con,  char *cmd, char *param);
+
+static void update_statistics_ptr(void *);
+static bool olsr_msg_statistics(union olsr_message *msg, struct interface *input_if, union olsr_ip_addr *from_addr);
+static char *olsr_packet_statistics(char *packet, struct interface *interface, union olsr_ip_addr *, int *length);
+static void update_statistics_ptr(void *data __attribute__ ((unused)));
+
+/* plugin configuration */
+static struct ip_acl allowed_nets;
+
+/* plugin parameters */
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+  {.name = IP_ACL_ACCEPT_PARAP,.set_plugin_parameter = &ip_acl_add_plugin_accept,.data = &allowed_nets},
+  {.name = IP_ACL_REJECT_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_reject,.data = &allowed_nets},
+  {.name = IP_ACL_CHECKFIRST_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_checkFirst,.data = &allowed_nets},
+  {.name = IP_ACL_DEFAULTPOLICY_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_defaultPolicy,.data = &allowed_nets}
+};
+
+/* command callbacks and names */
+static struct debuginfo_cmd commands[] = {
+    {"stat", &debuginfo_stat, NULL, NULL},
+    {"cookies", &debuginfo_cookies, NULL, NULL}
+};
+
+/* variables for statistics */
+static uint32_t recv_packets[60], recv_messages[60][6];
+static uint32_t recv_last_relevantTCs;
+static struct olsr_cookie_info *statistics_timer = NULL;
+
+int
+olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+void
+olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+  *params = plugin_parameters;
+  *size = ARRAYSIZE(plugin_parameters);
+}
+
+
+/**
+ *Constructor
+ */
+static void
+debuginfo_new(void)
+{
+  /* Print plugin info to stdout */
+  OLSR_INFO(LOG_PLUGINS, "%s\n", MOD_DESC);
+
+  ip_acl_init(&allowed_nets);
+
+  /* always allow localhost */
+  if (olsr_cnf->ip_version == AF_INET) {
+    union olsr_ip_addr ip;
+
+    ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
+    ip_acl_add(&allowed_nets, &ip, 32, false);
+  } else {
+    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
+    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
+  }
+}
+
+/**
+ *Destructor
+ */
+static void
+debuginfo_delete(void)
+{
+  size_t i;
+
+  for (i=0; i<ARRAYSIZE(commands); i++) {
+    olsr_com_remove_normal_txtcommand(commands[i].normal);
+    olsr_com_remove_csv_txtcommand(commands[i].csv);
+  }
+  olsr_parser_remove_function(&olsr_msg_statistics, PROMISCUOUS);
+  olsr_preprocessor_remove_function(&olsr_packet_statistics);
+  ip_acl_flush(&allowed_nets);
+}
+
+int
+olsrd_plugin_init(void)
+{
+  size_t i;
+
+  for (i=0; i<ARRAYSIZE(commands); i++) {
+    commands[i].normal = olsr_com_add_normal_txtcommand(commands[i].name, commands[i].handler);
+    commands[i].csv = olsr_com_add_csv_txtcommand(commands[i].name, commands[i].handler);
+    commands[i].normal->acl = &allowed_nets;
+    commands[i].csv->acl = &allowed_nets;
+  }
+
+  statistics_timer = olsr_alloc_cookie("debuginfo statistics timer", OLSR_COOKIE_TYPE_TIMER);
+  olsr_start_timer(1000, 0, true, &update_statistics_ptr, NULL, statistics_timer->ci_id);
+
+  memset(recv_packets, 0, sizeof(recv_packets));
+  memset(recv_messages, 0, sizeof(recv_messages));
+
+  recv_last_relevantTCs = 0;
+  olsr_parser_add_function(&olsr_msg_statistics, PROMISCUOUS);
+  olsr_preprocessor_add_function(&olsr_packet_statistics);
+  return 1;
+}
+
+
+static void
+update_statistics_ptr(void *data __attribute__ ((unused)))
+{
+  uint32_t now = now_times / 1000;
+  int i;
+
+  recv_packets[now % 60] = 0;
+  for (i = 0; i < 6; i++) {
+    recv_messages[now % 60][i] = 0;
+  }
+}
+
+/* update message statistics */
+static bool
+olsr_msg_statistics(union olsr_message *msg,
+                    struct interface *input_if __attribute__ ((unused)), union olsr_ip_addr *from_addr __attribute__ ((unused)))
+{
+  uint32_t now = now_times / 1000;
+  int idx, msgtype;
+
+  if (olsr_cnf->ip_version == AF_INET) {
+    msgtype = msg->v4.olsr_msgtype;
+  } else {
+    msgtype = msg->v6.olsr_msgtype;
+  }
+
+  switch (msgtype) {
+  case HELLO_MESSAGE:
+  case TC_MESSAGE:
+  case MID_MESSAGE:
+  case HNA_MESSAGE:
+    idx = msgtype - 1;
+    break;
+
+  case LQ_HELLO_MESSAGE:
+    idx = 0;
+    break;
+  case LQ_TC_MESSAGE:
+    idx = 1;
+    break;
+  default:
+    idx = 4;
+    break;
+  }
+
+  recv_messages[now % 60][idx]++;
+  if (recv_last_relevantTCs != getRelevantTcCount()) {
+    recv_messages[now % 60][5]++;
+    recv_last_relevantTCs++;
+  }
+  return true;
+}
+
+/* update traffic statistics */
+static char *
+olsr_packet_statistics(char *packet __attribute__ ((unused)),
+                       struct interface *interface __attribute__ ((unused)),
+                       union olsr_ip_addr *ip __attribute__ ((unused)), int *length __attribute__ ((unused)))
+{
+  uint32_t now = now_times / 1000;
+  recv_packets[now % 60] += *length;
+
+  return packet;
+}
+
+static enum olsr_txtcommand_result
+debuginfo_stat(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
+{
+  static const char *names[] = { "HELLO", "TC", "MID", "HNA", "Other", "Rel.TCs" };
+
+  uint32_t msgs[6], traffic, i, j;
+  uint32_t slot = (now_times / 1000 + 59) % 60;
+
+  if (!con->is_csv && abuf_puts(&con->out, "Table: Statistics (without duplicates)\nType\tlast seconds\t\t\t\tlast min.\taverage\n") < 0) {
+    return ABUF_ERROR;
+  }
+
+  for (j = 0; j < 6; j++) {
+    msgs[j] = 0;
+    for (i = 0; i < 60; i++) {
+      msgs[j] += recv_messages[i][j];
+    }
+  }
+
+  traffic = 0;
+  for (i = 0; i < 60; i++) {
+    traffic += recv_packets[i];
+  }
+
+  for (i = 0; i < 6; i++) {
+    if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%u\t%u\t%u\t%u\t%u\t%u\t\t%u\n" : "stat,%s,%u,%u,%u,%u,%u,%u,%u\n",
+                     names[i],
+                     recv_messages[(slot) % 60][i],
+                     recv_messages[(slot + 59) % 60][i],
+                     recv_messages[(slot + 58) % 60][i],
+                     recv_messages[(slot + 57) % 60][i],
+                     recv_messages[(slot + 56) % 60][i],
+                     msgs[i],
+                     msgs[i] / 60) < 0) {
+        return ABUF_ERROR;
+    }
+  }
+  if (abuf_appendf(&con->out, !con->is_csv ? "\nTraffic: %8u bytes/s\t%u bytes/minute\taverage %u bytes/s\n" : "stat,Traffic,%u,%u,%u\n",
+      recv_packets[(slot) % 60], traffic, traffic / 60) < 0) {
+    return ABUF_ERROR;
+  }
+  return CONTINUE;
+}
+
+static INLINE bool debuginfo_print_cookies_mem(struct autobuf *buf, const char *format) {
+  int i;
+  for (i = 1; i < COOKIE_ID_MAX; i++) {
+    struct olsr_cookie_info *c = olsr_cookie_get(i);
+    if (c == NULL || c->ci_type != OLSR_COOKIE_TYPE_MEMORY) {
+      continue;
+    }
+    if (abuf_appendf(buf, format,
+        c->ci_name == NULL ? "Unknown" : c->ci_name,
+        (unsigned long)c->ci_size, c->ci_usage, c->ci_free_list_usage) < 0) {
+      return true;
+    }
+  }
+  return false;
+}
+static INLINE bool debuginfo_print_cookies_timer(struct autobuf *buf, const char *format) {
+  int i;
+  for (i = 1; i < COOKIE_ID_MAX; i++) {
+    struct olsr_cookie_info *c = olsr_cookie_get(i);
+    if (c == NULL || c->ci_type != OLSR_COOKIE_TYPE_TIMER) {
+      continue;
+    }
+    if (abuf_appendf(buf, format, c->ci_name == NULL ? "Unknown" : c->ci_name,
+                       c->ci_usage, c->ci_changes) < 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static enum olsr_txtcommand_result
+debuginfo_cookies(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
+{
+  if (!con->is_csv && abuf_puts(&con->out, "Memory cookies:\n") < 0) {
+    return ABUF_ERROR;
+  }
+
+  if (debuginfo_print_cookies_mem(&con->out, !con->is_csv ?
+      "%-25s (MEMORY) size: %lu usage: %u freelist: %u\n" : "mem_cookie,%s,%lu,%u,%u\n")) {
+    return ABUF_ERROR;
+  }
+
+  if (!con->is_csv && abuf_puts(&con->out, "\nTimer cookies:\n") < 0) {
+    return ABUF_ERROR;
+  }
+
+  if (debuginfo_print_cookies_timer(&con->out, !con->is_csv ?
+      "%-25s (TIMER) usage: %u changes: %u\n" : "tmr_cookie,%s,%u,%u\n")) {
+    return ABUF_ERROR;
+  }
+  return CONTINUE;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/debuginfo/src/olsrd_debuginfo.h b/lib/debuginfo/src/olsrd_debuginfo.h
new file mode 100644 (file)
index 0000000..c28e7fa
--- /dev/null
@@ -0,0 +1,62 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_TXTINFO
+#define _OLSRD_TXTINFO
+
+#include "olsr_types.h"
+#include "plugin.h"
+#include "plugin_util.h"
+
+extern int nompr;
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/debuginfo/version-script.txt b/lib/debuginfo/version-script.txt
new file mode 100644 (file)
index 0000000..a145659
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
index 64a77ee..62514a0 100644 (file)
@@ -38,7 +38,7 @@
 
 OLSRD_PLUGIN = true
 PLUGIN_NAME =  olsrd_txtinfo
-PLUGIN_VER =   0.1
+PLUGIN_VER =   0.2
 
 TOPDIR =       ../..
 include $(TOPDIR)/Makefile.inc
index 8b7fcff..3c9a539 100644 (file)
@@ -1,60 +1,35 @@
- PARAMETERS
+   PLUGIN CONFIGURATION
+==========================
 
-The plugin takes the parameter "Port" "[portnumber]" 
-to set the TCP port on which the server is to run. 
-It defaults to 2006.
+The plugin accepts all parameters for an OLSRD "access
+control list". See README-acl for details.
 
-The access to the plugin is controlled by two lists of ip
-addresses and ip networks, a blacklist (reject list) and
-a whitelist (accept list). Two binary flags control which
-list is to be used first and what should be the default
-reaction to an unknown IP.
+There are no futher parameters.
 
-Examples for parameters accept/reject:
-PlParam   "accept"   "10.0.0.0/8" 
-PlParam   "reject"   "10.0.0.1" 
-PlParam   "accept"   "10.0.0.0 255.0.0.0" 
+   A configuration example
+-----------------------------
 
-Examples for parameters for binary flags
-PlParam   "checkfirst"      "reject"
-PlParam   "defaultpolicy"   "accept"
-
-The old parameters "host", "host4", "host6", "net", "net4"
-and "net6" are just alias names for "accept".
-
-The default settings are checkfirst=reject and
-defaultpolicy=reject.
-
-
-A configuration example:
-LoadPlugin "olsrd_txtinfo.so.0.1"
+LoadPlugin "olsrd_txtinfo.so.0.2"
 {
-    PlParam     "port"          "80"
     PlParam     "checkfirst"    "reject"
-    PlParam     "defaultpolicy" "accept"
+    PlParam     "defaultpolicy" "reject"
     PlParam     "accept"   "10.0.0.0/8"
     PlParam     "reject"   "10.0.1.123"
 }
 
-This will run the txtinfo server on port 80(the normal
-HTTP port) and allow access from the network
+This will allow access from the network
 10.0.0.0/8, but not from 10.0.1.123.
 access is always allowed from 127.0.0.1(localhost).
 
-For CSV-Mode just add /csv to your query and receive
-a comma separated output. You can also use more than
-one flag to query the plugin. The parameters can be
-in any order.
-e.g.: /csv/link/route
 
-ABOUT
+   PLUGIN USAGE
+==================
 
-telnet 127.0.0.1 2006
-or
-wget localhost:2006 -qO -
+The plugin commands are "link", "neigh", "routes",
+"topology", "hna" and "mid". All commands support
+both normal and csv mode.
 
-installation:
-make
-make install
+The plugin commands are used through the normal OLSR
+telnet server. See README-http-txt-services for details.
 
-- Lorenz Schori
+- Henning Rogge
diff --git a/lib/txtinfo/src/olsrd_plugin.c b/lib/txtinfo/src/olsrd_plugin.c
deleted file mode 100644 (file)
index 0896da9..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-
-/*
- * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in
- *   the documentation and/or other materials provided with the
- *   distribution.
- * * Neither the name of olsr.org, olsrd nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Visit http://www.olsr.org for more information.
- *
- * If you find this software useful feel free to make a donation
- * to the project. For more information see the website or contact
- * the copyright holders.
- *
- */
-
-/*
- * Dynamic linked library for the olsr.org olsr daemon
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include "plugin.h"
-#include "olsrd_txtinfo.h"
-#include "defs.h"
-#include "ipcalc.h"
-#include "olsr_cfg.h"
-#include "olsr.h"
-#include "olsr_logging.h"
-
-#define PLUGIN_NAME    "OLSRD txtinfo plugin"
-#define PLUGIN_VERSION "0.1"
-#define PLUGIN_AUTHOR   "Lorenz Schori"
-#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
-#define PLUGIN_INTERFACE_VERSION 5
-
-
-struct ip_acl allowed_nets;
-
-int ipc_port;
-int nompr;
-
-static void my_init(void) __attribute__ ((constructor));
-static void my_fini(void) __attribute__ ((destructor));
-
-/**
- *Constructor
- */
-static void
-my_init(void)
-{
-  /* Print plugin info to stdout */
-  OLSR_INFO(LOG_PLUGINS, "%s\n", MOD_DESC);
-
-  /* defaults for parameters */
-  ipc_port = 2006;
-
-  ip_acl_init(&allowed_nets);
-  /* always allow localhost */
-  if (olsr_cnf->ip_version == AF_INET) {
-    union olsr_ip_addr ip;
-
-    ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
-    ip_acl_add(&allowed_nets, &ip, 32, false);
-  } else {
-    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
-    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
-  }
-
-  /* highlite neighbours by default */
-  nompr = 0;
-}
-
-/**
- *Destructor
- */
-static void
-my_fini(void)
-{
-  /* Calls the destruction function
-   * olsr_plugin_exit()
-   * This function should be present in your
-   * sourcefile and all data destruction
-   * should happen there - NOT HERE!
-   */
-  olsr_plugin_exit();
-  ip_acl_flush(&allowed_nets);
-}
-
-
-int
-olsrd_plugin_interface_version(void)
-{
-  return PLUGIN_INTERFACE_VERSION;
-}
-
-static const struct olsrd_plugin_parameters plugin_parameters[] = {
-  {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port},
-  {.name = IP_ACL_ACCEPT_PARAP,.set_plugin_parameter = &ip_acl_add_plugin_accept,.data = &allowed_nets},
-  {.name = IP_ACL_REJECT_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_reject,.data = &allowed_nets},
-  {.name = IP_ACL_CHECKFIRST_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_checkFirst,.data = &allowed_nets},
-  {.name = IP_ACL_DEFAULTPOLICY_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_defaultPolicy,.data = &allowed_nets}
-};
-
-void
-olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
-{
-  *params = plugin_parameters;
-  *size = ARRAYSIZE(plugin_parameters);
-}
-
-/*
- * Local Variables:
- * mode: c
- * style: linux
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
index 7a19226..3656c73 100644 (file)
@@ -42,7 +42,6 @@
 /*
  * Dynamic linked library for the olsr.org olsr daemon
  */
-#include "olsrd_txtinfo.h"
 #include "olsr.h"
 #include "ipcalc.h"
 #include "neighbor_table.h"
 #include "misc.h"
 #include "olsr_ip_prefix_list.h"
 #include "parser.h"
-
+#include "olsr_comport_txt.h"
 #include "common/autobuf.h"
 
-#include <unistd.h>
-#include <errno.h>
-
-#ifdef WIN32
-#undef EWOULDBLOCK
-#undef EAGAIN
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EAGAIN WSAEWOULDBLOCK
-#undef errno
-#define errno WSAGetLastError()
-#undef SHUT_WR
-#define SHUT_WR SD_SEND
-#undef strerror
-#define strerror(x) StrError(x)
-#define read(fd,buf,size) recv((fd), (buf), (size), 0)
-#define write(fd,buf,size) send((fd), (buf), (size), 0)
-#endif
-
-
-struct ipc_conn {
-  struct autobuf resp;
-  int respstart;
-  int requlen;
-  char requ[256];
-  char csv;
-};
-
-static int listen_socket = -1;
-
-
-static void conn_destroy(struct ipc_conn *);
-
-static void ipc_action(int, void *, unsigned int);
-
-static void ipc_http(int, void *, unsigned int);
-
-static void ipc_http_read(int, struct ipc_conn *);
-
-static void ipc_http_read_dummy(int, struct ipc_conn *);
-
-static void ipc_http_write(int, struct ipc_conn *);
-
-static int send_info(struct ipc_conn *, int);
-
-static int ipc_print_neigh(struct ipc_conn *);
-
-static int ipc_print_link(struct ipc_conn *);
-
-static int ipc_print_routes(struct ipc_conn *);
-
-static int ipc_print_topology(struct ipc_conn *);
+#include "olsrd_txtinfo.h"
 
-static int ipc_print_hna_entry(struct autobuf *, const struct olsr_ip_prefix *, const union olsr_ip_addr *, char csv);
-static int ipc_print_hna(struct ipc_conn *);
+#define PLUGIN_NAME    "OLSRD txtinfo plugin"
+#define PLUGIN_VERSION "0.2"
+#define PLUGIN_AUTHOR   "Henning Rogge"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
 
-static int ipc_print_mid(struct ipc_conn *);
+struct debuginfo_cmd {
+  const char *name;
+  olsr_txthandler handler;
+  struct olsr_txtcommand *normal, *csv;
+};
 
-static int ipc_print_stat(struct ipc_conn *);
+static void txtinfo_new(void) __attribute__ ((constructor));
+static void txtinfo_delete(void) __attribute__ ((destructor));
 
-static void update_statistics_ptr(void *);
-static bool olsr_msg_statistics(union olsr_message *msg, struct interface *input_if, union olsr_ip_addr *from_addr);
-static char *olsr_packet_statistics(char *packet, struct interface *interface, union olsr_ip_addr *, int *length);
-static void update_statistics_ptr(void *data __attribute__ ((unused)));
+static enum olsr_txtcommand_result txtinfo_neigh(struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result txtinfo_link(struct comport_connection *con,  char *cmd, char *param);
+static enum olsr_txtcommand_result txtinfo_routes(struct comport_connection *con,  char *cmd, char *param);
+static enum olsr_txtcommand_result txtinfo_topology(struct comport_connection *con,  char *cmd, char *param);
+static enum olsr_txtcommand_result txtinfo_hna(struct comport_connection *con,  char *cmd, char *param);
+static enum olsr_txtcommand_result txtinfo_mid(struct comport_connection *con,  char *cmd, char *param);
 
-#define isprefix(str, pre) (strncmp((str), (pre), strlen(pre)) == 0)
 
-#define SIW_NEIGH        (1 << 0)
-#define SIW_LINK         (1 << 1)
-#define SIW_ROUTE        (1 << 2)
-#define SIW_HNA                  (1 << 3)
-#define SIW_MID                  (1 << 4)
-#define SIW_TOPO         (1 << 5)
-#define SIW_STAT         (1 << 6)
-#define SIW_COOKIES      (1 << 7)
-#define SIW_CSV                  (1 << 8)
-#define SIW_ALL                  (SIW_NEIGH|SIW_LINK|SIW_ROUTE|SIW_HNA|SIW_MID|SIW_TOPO)
+/* plugin configuration */
+static struct ip_acl allowed_nets;
 
-/* variables for statistics */
-static uint32_t recv_packets[60], recv_messages[60][6];
-static uint32_t recv_last_relevantTCs;
-struct olsr_cookie_info *statistics_timer = NULL;
+/* plugin parameters */
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+  {.name = IP_ACL_ACCEPT_PARAP,.set_plugin_parameter = &ip_acl_add_plugin_accept,.data = &allowed_nets},
+  {.name = IP_ACL_REJECT_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_reject,.data = &allowed_nets},
+  {.name = IP_ACL_CHECKFIRST_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_checkFirst,.data = &allowed_nets},
+  {.name = IP_ACL_DEFAULTPOLICY_PARAM,.set_plugin_parameter = &ip_acl_add_plugin_defaultPolicy,.data = &allowed_nets}
+};
 
-/**
- * destructor - called at unload
- */
-void
-olsr_plugin_exit(void)
-{
-  olsr_parser_remove_function(&olsr_msg_statistics, PROMISCUOUS);
-  olsr_preprocessor_remove_function(&olsr_packet_statistics);
-  CLOSESOCKET(listen_socket);
-}
+/* command callbacks and names */
+static struct debuginfo_cmd commands[] = {
+    {"neigh", &txtinfo_neigh, NULL, NULL},
+    {"link", &txtinfo_link, NULL, NULL},
+    {"routes", &txtinfo_routes, NULL, NULL},
+    {"topology", &txtinfo_topology, NULL, NULL},
+    {"hna", &txtinfo_hna, NULL, NULL},
+    {"mid", &txtinfo_mid, NULL, NULL},
+};
 
-/**
- *Do initialization here
- *
- *This function is called by the my_init
- *function in uolsrd_plugin.c
- */
 int
-olsrd_plugin_init(void)
-{
-  struct sockaddr_storage sst;
-  uint32_t yes = 1;
-  socklen_t addrlen;
-
-  statistics_timer = olsr_alloc_cookie("Txtinfo statistics timer", OLSR_COOKIE_TYPE_TIMER);
-  olsr_start_timer(1000, 0, true, &update_statistics_ptr, NULL, statistics_timer->ci_id);
-
-  /* Init ipc socket */
-  listen_socket = socket(olsr_cnf->ip_version, SOCK_STREAM, 0);
-  if (listen_socket == -1) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) socket()=%s\n", strerror(errno));
-    return 0;
-  }
-  if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) setsockopt()=%s\n", strerror(errno));
-    CLOSESOCKET(listen_socket);
-    return 0;
-  }
-#if defined __FreeBSD__ && defined SO_NOSIGPIPE
-  if (setsockopt(listen_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) reusing address failed: %s", strerror(errno));
-    CLOSESOCKET(listen_socket);
-    return 0;
-  }
-#endif
-  /* Bind the socket */
-
-  /* complete the socket structure */
-  memset(&sst, 0, sizeof(sst));
-  if (olsr_cnf->ip_version == AF_INET) {
-    struct sockaddr_in *addr4 = (struct sockaddr_in *)&sst;
-    addr4->sin_family = AF_INET;
-    addrlen = sizeof(*addr4);
-#ifdef SIN6_LEN
-    addr4->sin_len = addrlen;
-#endif
-    addr4->sin_addr.s_addr = INADDR_ANY;
-    addr4->sin_port = htons(ipc_port);
-  } else {
-    struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sst;
-    addr6->sin6_family = AF_INET6;
-    addrlen = sizeof(*addr6);
-#ifdef SIN6_LEN
-    addr6->sin6_len = addrlen;
-#endif
-    addr6->sin6_addr = in6addr_any;
-    addr6->sin6_port = htons(ipc_port);
-  }
-
-  /* bind the socket to the port number */
-  if (bind(listen_socket, (struct sockaddr *)&sst, addrlen) == -1) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) bind()=%s\n", strerror(errno));
-    CLOSESOCKET(listen_socket);
-    return 0;
-  }
-
-  /* show that we are willing to listen */
-  if (listen(listen_socket, 1) == -1) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) listen()=%s\n", strerror(errno));
-    CLOSESOCKET(listen_socket);
-    return 0;
-  }
-
-  /* Register with olsrd */
-  add_olsr_socket(listen_socket, NULL, &ipc_action, NULL, SP_IMM_READ);
-
-  OLSR_INFO(LOG_PLUGINS, "(TXTINFO) listening on port %d\n", ipc_port);
-
-  memset(recv_packets, 0, sizeof(recv_packets));
-  memset(recv_messages, 0, sizeof(recv_messages));
-
-  recv_last_relevantTCs = 0;
-  olsr_parser_add_function(&olsr_msg_statistics, PROMISCUOUS);
-  olsr_preprocessor_add_function(&olsr_packet_statistics);
-  return 1;
-}
-
-
-static void
-update_statistics_ptr(void *data __attribute__ ((unused)))
+olsrd_plugin_interface_version(void)
 {
-  uint32_t now = now_times / 1000;
-  int i;
-
-  recv_packets[now % 60] = 0;
-  for (i = 0; i < 6; i++) {
-    recv_messages[now % 60][i] = 0;
-  }
+  return PLUGIN_INTERFACE_VERSION;
 }
 
-/* update message statistics */
-static bool
-olsr_msg_statistics(union olsr_message *msg,
-                    struct interface *input_if __attribute__ ((unused)), union olsr_ip_addr *from_addr __attribute__ ((unused)))
-{
-  uint32_t now = now_times / 1000;
-  int idx, msgtype;
-
-  if (olsr_cnf->ip_version == AF_INET) {
-    msgtype = msg->v4.olsr_msgtype;
-  } else {
-    msgtype = msg->v6.olsr_msgtype;
-  }
-
-  switch (msgtype) {
-  case HELLO_MESSAGE:
-  case TC_MESSAGE:
-  case MID_MESSAGE:
-  case HNA_MESSAGE:
-    idx = msgtype - 1;
-    break;
-
-  case LQ_HELLO_MESSAGE:
-    idx = 0;
-    break;
-  case LQ_TC_MESSAGE:
-    idx = 1;
-    break;
-  default:
-    idx = 4;
-    break;
-  }
-
-  recv_messages[now % 60][idx]++;
-  if (recv_last_relevantTCs != getRelevantTcCount()) {
-    recv_messages[now % 60][5]++;
-    recv_last_relevantTCs++;
-  }
-  return true;
-}
-
-/* update traffic statistics */
-static char *
-olsr_packet_statistics(char *packet __attribute__ ((unused)),
-                       struct interface *interface __attribute__ ((unused)),
-                       union olsr_ip_addr *ip __attribute__ ((unused)), int *length __attribute__ ((unused)))
+void
+olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
 {
-  uint32_t now = now_times / 1000;
-  recv_packets[now % 60] += *length;
-
-  return packet;
+  *params = plugin_parameters;
+  *size = ARRAYSIZE(plugin_parameters);
 }
 
-/* destroy the connection */
-static void
-conn_destroy(struct ipc_conn *conn)
-{
-  abuf_free(&conn->resp);
-  free(conn);
-}
 
+/**
+ * Constructor of plugin, called before parameters are initialized
+ */
 static void
-kill_connection(int fd, struct ipc_conn *conn)
+txtinfo_new(void)
 {
-  remove_olsr_socket(fd, NULL, &ipc_http);
-  CLOSESOCKET(fd);
-  conn_destroy(conn);
-}
+  /* Print plugin info to stdout */
+  OLSR_INFO(LOG_PLUGINS, "%s\n", MOD_DESC);
 
-static void
-ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
-{
-  struct ipc_conn *conn;
-  struct sockaddr_storage pin;
-#if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_WARN
-  struct ipaddr_str buf;
-#endif
-  socklen_t addrlen = sizeof(pin);
-  int http_connection;
-  union olsr_ip_addr *ipaddr;
-
-  http_connection = accept(fd, (struct sockaddr *)&pin, &addrlen);
-  if (http_connection == -1) {
-    /* this may well happen if the other side immediately closes the connection. */
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) accept()=%s\n", strerror(errno));
-    return;
-  }
+  ip_acl_init(&allowed_nets);
 
-  /* check if we want ot speak with it */
+  /* always allow localhost */
   if (olsr_cnf->ip_version == AF_INET) {
-    struct sockaddr_in *addr4 = (struct sockaddr_in *)&pin;
-    ipaddr = (union olsr_ip_addr *)&addr4->sin_addr;
-  } else {
-    struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pin;
-    ipaddr = (union olsr_ip_addr *)&addr6->sin6_addr;
-  }
-
-  if (!ip_acl_acceptable(&allowed_nets, ipaddr, olsr_cnf->ip_version)) {
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) From host(%s) not allowed!\n", olsr_ip_to_string(&buf, ipaddr));
-    CLOSESOCKET(http_connection);
-    return;
-  }
-  OLSR_DEBUG(LOG_PLUGINS, "(TXTINFO) Connect from %s\n", olsr_ip_to_string(&buf, ipaddr));
+    union olsr_ip_addr ip;
 
-  /* make the fd non-blocking */
-  if (set_nonblocking(http_connection) < 0) {
-    CLOSESOCKET(http_connection);
-    return;
+    ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
+    ip_acl_add(&allowed_nets, &ip, 32, false);
+  } else {
+    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
+    ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
   }
-
-  conn = olsr_malloc(sizeof(*conn), "Connection object for ");
-  conn->requlen = 0;
-  *conn->requ = '\0';
-  conn->respstart = 0;
-  abuf_init(&conn->resp, 1000);
-  add_olsr_socket(http_connection, NULL, &ipc_http, conn, SP_IMM_READ);
 }
 
+/**
+ * Destructor of plugin
+ */
 static void
-ipc_http_read_dummy(int fd, struct ipc_conn *conn)
+txtinfo_delete(void)
 {
-  /* just read dummy stuff */
-  ssize_t bytes_read;
-  char dummybuf[128];
-  do {
-    bytes_read = read(fd, dummybuf, sizeof(dummybuf));
-  } while (bytes_read > 0);
-  if (bytes_read == 0) {
-    /* EOF */
-    if (conn->respstart < conn->resp.len && conn->resp.len > 0) {
-      disable_olsr_socket(fd, NULL, &ipc_http, SP_IMM_READ);
-      conn->requlen = -1;
-      return;
-    }
-  } else if (errno == EINTR || errno == EAGAIN) {
-    /* ignore interrupted sys-calls */
-    return;
-  }
-  /* we had either an error or EOF and we are completely done */
-  kill_connection(fd, conn);
-}
+  size_t i;
 
-static void
-ipc_http_read(int fd, struct ipc_conn *conn)
-{
-  int send_what = 0;
-  const char *p;
-  ssize_t bytes_read = read(fd, conn->requ + conn->requlen, sizeof(conn->requ) - conn->requlen - 1);    /* leave space for a terminating '\0' */
-  if (bytes_read < 0) {
-    if (errno == EINTR || errno == EAGAIN) {
-      return;
-    }
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) read error: %s", strerror(errno));
-    kill_connection(fd, conn);
-    return;
-  }
-  conn->requlen += bytes_read;
-  conn->requ[conn->requlen] = '\0';
-  conn->csv = 0;
-
-  /* look if we have the necessary info. We get here somethign like "GET /path HTTP/1.0" */
-  p = strchr(conn->requ, '/');
-  if (p == NULL) {
-    /* input buffer full ? */
-    if ((sizeof(conn->requ) - conn->requlen - 1) == 0) {
-      kill_connection(fd, conn);
-      return;
-    }
-    /* we didn't get all. Wait for more data. */
-    return;
+  for (i=0; i<ARRAYSIZE(commands); i++) {
+    olsr_com_remove_normal_txtcommand(commands[i].normal);
+    olsr_com_remove_csv_txtcommand(commands[i].csv);
   }
-  while (p != NULL) {
-    if (isprefix(p, "/neighbours"))
-      send_what = send_what | SIW_LINK | SIW_NEIGH;
-    else if (isprefix(p, "/neigh"))
-      send_what = send_what | SIW_NEIGH;
-    else if (isprefix(p, "/link"))
-      send_what = send_what | SIW_LINK;
-    else if (isprefix(p, "/route"))
-      send_what = send_what | SIW_ROUTE;
-    else if (isprefix(p, "/hna"))
-      send_what = send_what | SIW_HNA;
-    else if (isprefix(p, "/mid"))
-      send_what = send_what | SIW_MID;
-    else if (isprefix(p, "/topo"))
-      send_what = send_what | SIW_TOPO;
-    else if (isprefix(p, "/stat"))
-      send_what = send_what | SIW_STAT;
-    else if (isprefix(p, "/cookies"))
-      send_what = send_what | SIW_COOKIES;
-    else if (isprefix(p, "/csv"))
-      send_what = send_what | SIW_CSV;
-    p = strchr(++p, '/');
-  }
-  if (send_what == 0) {
-    send_what = SIW_ALL;
-  } else if (send_what == SIW_CSV) {
-    send_what = SIW_ALL | SIW_CSV;
-  }
-
-  if (send_info(conn, send_what) < 0) {
-    kill_connection(fd, conn);
-    return;
-  }
-  enable_olsr_socket(fd, NULL, &ipc_http, SP_IMM_WRITE);
+  ip_acl_flush(&allowed_nets);
 }
 
-static void
-ipc_http_write(int fd, struct ipc_conn *conn)
+/*
+ * Initialization of plugin AFTER parameters have been read
+ */
+int
+olsrd_plugin_init(void)
 {
-  ssize_t bytes_written = write(fd, conn->resp.buf + conn->respstart,
-                                conn->resp.len - conn->respstart);
-  if (bytes_written < 0) {
-    if (errno == EINTR || errno == EAGAIN) {
-      return;
-    }
-    OLSR_WARN(LOG_PLUGINS, "(TXTINFO) write error: %s", strerror(errno));
-    kill_connection(fd, conn);
-    return;
-  }
-  conn->respstart += bytes_written;
-  if (conn->respstart >= conn->resp.len) {
-    /* we are done. */
-    if (conn->requlen < 0) {
-      /* we are completely done. */
-      kill_connection(fd, conn);
-    } else if (shutdown(fd, SHUT_WR) < 0) {
-      kill_connection(fd, conn);
-    } else {
-      disable_olsr_socket(fd, NULL, &ipc_http, SP_IMM_WRITE);
-    }
-  }
-}
+  size_t i;
 
-static void
-ipc_http(int fd, void *data, unsigned int flags)
-{
-  struct ipc_conn *conn = data;
-  if ((flags & SP_IMM_READ) != 0) {
-    if (conn->resp.len > 0) {
-      ipc_http_read_dummy(fd, conn);
-    } else {
-      ipc_http_read(fd, conn);
-    }
-  }
-  if ((flags & SP_IMM_WRITE) != 0) {
-    ipc_http_write(fd, conn);
+  for (i=0; i<ARRAYSIZE(commands); i++) {
+    commands[i].normal = olsr_com_add_normal_txtcommand(commands[i].name, commands[i].handler);
+    commands[i].csv = olsr_com_add_csv_txtcommand(commands[i].name, commands[i].handler);
+    commands[i].normal->acl = &allowed_nets;
+    commands[i].csv->acl = &allowed_nets;
   }
+  return 1;
 }
 
-
-static int
-ipc_print_neigh(struct ipc_conn *conn)
+/**
+ * Callback for neigh command
+ */
+static enum olsr_txtcommand_result
+txtinfo_neigh(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   struct nbr_entry *neigh;
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
-      return -1;
-    }
+  if (!con->is_csv && abuf_puts(&con->out, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* Neighbors */
   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
-    struct nbr2_list_entry *list_2;
     struct ipaddr_str buf1;
-    int thop_cnt = 0;
-    OLSR_FOR_ALL_NBR2_LIST_ENTRIES(neigh, list_2) {
-      thop_cnt++;
-    } OLSR_FOR_ALL_NBR2_LIST_ENTRIES_END(neigh, list_2);
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp,
-                       "%s\t%s\t%s\t%s\t%d\t%d\n",
+    if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%s\t%s\t%d\t%d\n" : "neigh,%s,%s,%s,%s,%d,%d\n",
                        olsr_ip_to_string(&buf1, &neigh->neighbor_main_addr),
                        neigh->status == SYM ? "YES" : "NO",
                        neigh->is_mpr ? "YES" : "NO",
-                       olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO", neigh->willingness, thop_cnt) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp,
-                       "neigh,%s,%s,%s,%s,%d,%d\n",
-                       olsr_ip_to_string(&buf1, &neigh->neighbor_main_addr),
-                       neigh->status == SYM ? "YES" : "NO",
-                       neigh->is_mpr ? "YES" : "NO",
-                       olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO", neigh->willingness, thop_cnt) < 0) {
-        return -1;
-      }
+                       olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO", neigh->willingness, neigh->nbr2_list_tree.count) < 0) {
+        return ABUF_ERROR;
     }
-  }
-  OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
+  return CONTINUE;
 }
 
-static int
-ipc_print_link(struct ipc_conn *conn)
+/**
+ * Callback for link command
+ */
+static enum olsr_txtcommand_result
+txtinfo_link(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   struct link_entry *lnk;
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: Links\nLocal IP\tRemote IP\tLQ\tNLQ\tCost\n") < 0) {
-      return -1;
-    }
+  OLSR_DEBUG(LOG_NETWORKING, "Starting 'link' command...\n");
+  if (!con->is_csv && abuf_puts(&con->out, "Table: Links\nLocal IP\tRemote IP\tLQ\tNLQ\tCost\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* Link set */
   OLSR_FOR_ALL_LINK_ENTRIES(lnk) {
     struct ipaddr_str buf1, buf2;
     struct lqtextbuffer lqbuffer1, lqbuffer2;
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp,
-                       "%s\t%s\t%s\t%s\t\n",
-                       olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
-                       olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
-                       get_link_entry_text(lnk, '\t', &lqbuffer1), get_linkcost_text(lnk->linkcost, false, &lqbuffer2)) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp,
-                       "link,%s,%s,%s,%s\n",
-                       olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
-                       olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
-                       get_link_entry_text(lnk, ',', &lqbuffer1), get_linkcost_text(lnk->linkcost, false, &lqbuffer2)) < 0) {
-        return -1;
-      }
+    if (abuf_appendf(&con->out,
+                     !con->is_csv ? "%s\t%s\t%s\t%s\t\n" : "link,%s,%s,%s,%s\n",
+                     olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
+                     olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
+                     get_link_entry_text(lnk, '\t', &lqbuffer1), get_linkcost_text(lnk->linkcost, false, &lqbuffer2)) < 0) {
+        return ABUF_ERROR;
     }
-  }
-  OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
+  return CONTINUE;
 }
 
-static int
-ipc_print_routes(struct ipc_conn *conn)
+/**
+ * Callback for routes command
+ */
+static enum olsr_txtcommand_result
+txtinfo_routes(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   struct rt_entry *rt;
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n") < 0) {
-      return -1;
-    }
+  if (!con->is_csv && abuf_puts(&con->out, "Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* Walk the route table */
   OLSR_FOR_ALL_RT_ENTRIES(rt) {
-    struct ipaddr_str buf;
+    struct ipaddr_str ipbuf;
     struct ipprefix_str prefixstr;
     struct lqtextbuffer lqbuffer;
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp,
-                       "%s\t%s\t%u\t%s\t%s\t\n",
-                       olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
-                       olsr_ip_to_string(&buf, &rt->rt_best->rtp_nexthop.gateway),
-                       rt->rt_best->rtp_metric.hops,
-                       get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer),
-                       rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]") < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp,
-                       "route,%s,%s,%u,%s,%s\n",
-                       olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
-                       olsr_ip_to_string(&buf, &rt->rt_best->rtp_nexthop.gateway),
-                       rt->rt_best->rtp_metric.hops,
-                       get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer),
-                       rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]") < 0) {
-        return -1;
-      }
-    }
-  }
-  OLSR_FOR_ALL_RT_ENTRIES_END(rt);
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
+    if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%u\t%s\t%s\t\n" : "route,%s,%s,%u,%s,%s\n",
+                     olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
+                     olsr_ip_to_string(&ipbuf, &rt->rt_best->rtp_nexthop.gateway),
+                     rt->rt_best->rtp_metric.hops,
+                     get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer),
+                     rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]") < 0) {
+      return ABUF_ERROR;
+    }
+  } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
+  return CONTINUE;
 }
 
-static int
-ipc_print_topology(struct ipc_conn *conn)
+/**
+ * Callback for topology command
+ */
+static enum olsr_txtcommand_result
+txtinfo_topology(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   struct tc_entry *tc;
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n") < 0) {
-      return -1;
-    }
+  if (!con->is_csv && abuf_puts(&con->out, "Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* Topology */
@@ -660,69 +275,49 @@ ipc_print_topology(struct ipc_conn *conn)
       if (tc_edge->edge_inv) {
         struct ipaddr_str dstbuf, addrbuf;
         struct lqtextbuffer lqbuffer1, lqbuffer2;
-        if (!conn->csv) {
-          if (abuf_appendf(&conn->resp,
-                           "%s\t%s\t%s\t%s\n",
-                           olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
-                           olsr_ip_to_string(&addrbuf, &tc->addr),
-                           get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
-                           get_linkcost_text(tc_edge->cost, false, &lqbuffer2)) < 0) {
-            return -1;
-          }
-        } else {
-          if (abuf_appendf(&conn->resp,
-                           "topo,%s,%s,%s,%s\n",
-                           olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
-                           olsr_ip_to_string(&addrbuf, &tc->addr),
-                           get_tc_edge_entry_text(tc_edge, ',', &lqbuffer1),
-                           get_linkcost_text(tc_edge->cost, false, &lqbuffer2)) < 0) {
-            return -1;
-          }
+        if (abuf_appendf(&con->out, !con->is_csv ? "%s\t%s\t%s\t%s\n" : "topo,%s,%s,%s,%s\n",
+                         olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
+                         olsr_ip_to_string(&addrbuf, &tc->addr),
+                         get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
+                         get_linkcost_text(tc_edge->cost, false, &lqbuffer2)) < 0) {
+          return ABUF_ERROR;
         }
       }
-    }
-    OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
-  }
-  OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+    } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
+  return CONTINUE;
 }
 
-static int
-ipc_print_hna_entry(struct autobuf *autobuf, const struct olsr_ip_prefix *hna_prefix, const union olsr_ip_addr *ipaddr, char csv)
+/**
+ * helper which prints an HNA entry
+ */
+static INLINE bool
+txtinfo_print_hna_entry(struct autobuf *buf, const char *format, const struct olsr_ip_prefix *hna_prefix, const union olsr_ip_addr *ipaddr)
 {
   struct ipaddr_str mainaddrbuf;
   struct ipprefix_str addrbuf;
-  if (!csv) {
-    return abuf_appendf(autobuf,
-                        "%s\t%s\n", olsr_ip_prefix_to_string(&addrbuf, hna_prefix), olsr_ip_to_string(&mainaddrbuf, ipaddr));
-  } else {
-    return abuf_appendf(autobuf,
-                        "hna,%s,%s\n", olsr_ip_prefix_to_string(&addrbuf, hna_prefix), olsr_ip_to_string(&mainaddrbuf, ipaddr));
-  }
+  return abuf_appendf(buf, format, olsr_ip_prefix_to_string(&addrbuf, hna_prefix), olsr_ip_to_string(&mainaddrbuf, ipaddr)) < 0;
 }
 
-static int
-ipc_print_hna(struct ipc_conn *conn)
+/**
+ * Callback for hna command
+ */
+static enum olsr_txtcommand_result
+txtinfo_hna(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   const struct ip_prefix_entry *hna;
   struct tc_entry *tc;
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: HNA\nDestination\tGateway\n") < 0) {
-      return -1;
-    }
+  const char *format = !con->is_csv ? "%s\t%s\n" : "hna,%s,%s\n";
+  if (!con->is_csv && abuf_puts(&con->out, "Table: HNA\nDestination\tGateway\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* Announced HNA entries */
   OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna) {
-    if (ipc_print_hna_entry(&conn->resp, &hna->net, &olsr_cnf->router_id, conn->csv) < 0) {
-      return -1;
+    if (txtinfo_print_hna_entry(&con->out, format, &hna->net, &olsr_cnf->router_id)) {
+      return ABUF_ERROR;
     }
   }
   OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
@@ -732,258 +327,49 @@ ipc_print_hna(struct ipc_conn *conn)
     struct hna_net *tmp_net;
     /* Check all networks */
     OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, tmp_net) {
-      if (ipc_print_hna_entry(&conn->resp, &tmp_net->hna_prefix, &tc->addr, conn->csv) < 0) {
-        return -1;
+      if (txtinfo_print_hna_entry(&con->out, format, &tmp_net->hna_prefix, &tc->addr)) {
+        return ABUF_ERROR;
       }
-    }
-    OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, tmp_net);
-  }
-  OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+    } OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, tmp_net);
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
+  return CONTINUE;
 }
 
-static int
-ipc_print_mid(struct ipc_conn *conn)
+/**
+ * Callback for mid command
+ */
+static enum olsr_txtcommand_result
+txtinfo_mid(struct comport_connection *con,  char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused)))
 {
   struct tc_entry *tc;
+  const char *prefix = !con->is_csv ? "" : "mid,";
+  const char sep = !con->is_csv ? '\t' : ',';
 
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: MID\nIP address\tAliases\n") < 0) {
-      return -1;
-    }
+  if (!con->is_csv && abuf_puts(&con->out, "Table: MID\nIP address\tAliases\n") < 0) {
+    return ABUF_ERROR;
   }
 
   /* MID root is the TC entry */
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
-    struct ipaddr_str buf;
+    struct ipaddr_str ipbuf;
     struct mid_entry *alias;
-    char sep = '\t';
-    if (conn->csv) {
-      sep = ',';
-    }
 
-    if (!conn->csv) {
-      if (abuf_puts(&conn->resp, olsr_ip_to_string(&buf, &tc->addr)) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp, "mid,%s", olsr_ip_to_string(&buf, &tc->addr)) < 0) {
-        return -1;
-      }
+    if (abuf_appendf(&con->out, "%s%s", prefix, olsr_ip_to_string(&ipbuf, &tc->addr)) < 0) {
+      return ABUF_ERROR;
     }
 
     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
-      if (abuf_appendf(&conn->resp, "%c%s", sep, olsr_ip_to_string(&buf, &alias->mid_alias_addr)) < 0) {
-        return -1;
-      }
-      if (!conn->csv) {
-        sep = ';';
-      } else {
-        sep = ',';
+      if (abuf_appendf(&con->out, "%c%s", sep, olsr_ip_to_string(&ipbuf, &alias->mid_alias_addr)) < 0) {
+        return ABUF_ERROR;
       }
     }
     OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  OLSR_FOR_ALL_TC_ENTRIES_END(tc);
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
-}
-
-static int
-ipc_print_stat(struct ipc_conn *conn)
-{
-  static const char *names[] = { "HELLO", "TC", "MID", "HNA", "Other", "Rel.TCs" };
-
-  uint32_t msgs[6], traffic, i, j;
-  uint32_t slot = (now_times / 1000 + 59) % 60;
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Table: Statistics (without duplicates)\nType\tlast seconds\t\t\t\tlast min.\taverage\n") < 0) {
-      return -1;
-    }
-  }
-
-  for (j = 0; j < 6; j++) {
-    msgs[j] = 0;
-    for (i = 0; i < 60; i++) {
-      msgs[j] += recv_messages[i][j];
+    if (abuf_appendf(&con->out, "\n") < 0) {
+      return ABUF_ERROR;
     }
-  }
-
-  traffic = 0;
-  for (i = 0; i < 60; i++) {
-    traffic += recv_packets[i];
-  }
-
-  for (i = 0; i < 6; i++) {
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp, "%s\t%u\t%u\t%u\t%u\t%u\t%u\t\t%u\n", names[i],
-                       recv_messages[(slot) % 60][i],
-                       recv_messages[(slot + 59) % 60][i],
-                       recv_messages[(slot + 58) % 60][i],
-                       recv_messages[(slot + 57) % 60][i], recv_messages[(slot + 56) % 60][i], msgs[i], msgs[i] / 60) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp, "stat,%s,%u,%u,%u,%u,%u,%u,%u\n", names[i],
-                       recv_messages[(slot) % 60][i],
-                       recv_messages[(slot + 59) % 60][i],
-                       recv_messages[(slot + 58) % 60][i],
-                       recv_messages[(slot + 57) % 60][i], recv_messages[(slot + 56) % 60][i], msgs[i], msgs[i] / 60) < 0) {
-        return -1;
-      }
-    }
-  }
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\nTraffic: %8u bytes/s\t%u bytes/minute\taverage %u bytes/s\n",
-                     recv_packets[(slot) % 60], traffic, traffic / 60) < 0) {
-      return -1;
-    }
-  } else {
-    if (abuf_appendf(&conn->resp, "stat,Traffic,%u,%u,%u\n", recv_packets[(slot) % 60], traffic, traffic / 60) < 0) {
-      return -1;
-    }
-  }
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
-}
-
-static int
-ipc_print_cookies(struct ipc_conn *conn)
-{
-  int i;
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "Memory cookies:\n") < 0) {
-      return -1;
-    }
-  }
-
-  for (i = 1; i < COOKIE_ID_MAX; i++) {
-    struct olsr_cookie_info *c = olsr_cookie_get(i);
-    if (c == NULL || c->ci_type != OLSR_COOKIE_TYPE_MEMORY) {
-      continue;
-    }
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp, "%-25s ", c->ci_name == NULL ? "Unknown" : c->ci_name) < 0) {
-        return -1;
-      }
-      if (abuf_appendf(&conn->resp, "(MEMORY) size: %lu usage: %u freelist: %u\n",
-                       (unsigned long)c->ci_size, c->ci_usage, c->ci_free_list_usage) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp, "mem_cookie,%s,%lu,%u,%u\n", c->ci_name == NULL ? "Unknown" : c->ci_name,
-                       (unsigned long)c->ci_size, c->ci_usage, c->ci_free_list_usage) < 0) {
-        return -1;
-      }
-    }
-  }
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\nTimer cookies:\n") < 0) {
-      return -1;
-    }
-  }
-
-  for (i = 1; i < COOKIE_ID_MAX; i++) {
-    struct olsr_cookie_info *c = olsr_cookie_get(i);
-    if (c == NULL || c->ci_type != OLSR_COOKIE_TYPE_TIMER) {
-      continue;
-    }
-    if (!conn->csv) {
-      if (abuf_appendf(&conn->resp, "%-25s ", c->ci_name == NULL ? "Unknown" : c->ci_name) < 0) {
-        return -1;
-      }
-      if (abuf_appendf(&conn->resp, "(TIMER) usage: %u changes: %u\n", c->ci_usage, c->ci_changes) < 0) {
-        return -1;
-      }
-    } else {
-      if (abuf_appendf(&conn->resp, "tmr_cookie,%s,%u,%u\n", c->ci_name == NULL ? "Unknown" : c->ci_name,
-                       c->ci_usage, c->ci_changes) < 0) {
-        return -1;
-      }
-    }
-  }
-
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "\n") < 0) {
-      return -1;
-    }
-  }
-  return 0;
-}
-
-static int
-send_info(struct ipc_conn *conn, int send_what)
-{
-  int rv;
-
-  /* comma separated values output format */
-  if ((send_what & SIW_CSV) != 0) {
-    conn->csv = 1;
-  }
-
-  /* Print minimal http header */
-  if (!conn->csv) {
-    if (abuf_appendf(&conn->resp, "HTTP/1.0 200 OK\n" "Content-type: text/plain\n\n") < 0) {
-      return -1;
-    }
-  }
-
-  /* Print tables to IPC socket */
-
-  rv = 0;
-  /* links + Neighbors */
-  if ((send_what & SIW_LINK) != 0 && ipc_print_link(conn) < 0) {
-    rv = -1;
-  }
-  if ((send_what & SIW_NEIGH) != 0 && ipc_print_neigh(conn) < 0) {
-    rv = -1;
-  }
-  /* topology */
-  if ((send_what & SIW_TOPO) != 0) {
-    rv = ipc_print_topology(conn);
-  }
-  /* hna */
-  if ((send_what & SIW_HNA) != 0) {
-    rv = ipc_print_hna(conn);
-  }
-  /* mid */
-  if ((send_what & SIW_MID) != 0) {
-    rv = ipc_print_mid(conn);
-  }
-  /* routes */
-  if ((send_what & SIW_ROUTE) != 0) {
-    rv = ipc_print_routes(conn);
-  }
-  /* statistics */
-  if ((send_what & SIW_STAT) != 0) {
-    rv = ipc_print_stat(conn);
-  }
-  /* cookies */
-  if ((send_what & SIW_COOKIES) != 0) {
-    rv = ipc_print_cookies(conn);
-  }
-  return rv;
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc)
+  return CONTINUE;
 }
 
 /*
index b06da7c..c28e7fa 100644 (file)
 #include "plugin.h"
 #include "plugin_util.h"
 
-extern struct ip_acl allowed_nets;
-
-extern int ipc_port;
 extern int nompr;
 
-int olsrd_plugin_interface_version(void);
-int olsrd_plugin_init(void);
-void olsr_plugin_exit(void);
-void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
-
 #endif
 
 /*
index 7b834d6..e41d654 100644 (file)
@@ -61,7 +61,7 @@ abuf_init(struct autobuf *autobuf, int initial_size)
     return 0;
   }
   autobuf->size = ROUND_UP_TO_POWER_OF_2(initial_size, AUTOBUFCHUNK);
-  autobuf->buf = malloc(autobuf->size);
+  autobuf->buf = calloc(autobuf->size, 1);
   if (autobuf->buf == NULL) {
     autobuf->size = 0;
     return -1;
@@ -82,10 +82,11 @@ abuf_free(struct autobuf *autobuf)
 static int
 autobuf_enlarge(struct autobuf *autobuf, int new_size)
 {
-  if (new_size >= autobuf->size) {
+  new_size++;
+  if (new_size > autobuf->size) {
     char *p;
-    autobuf->size = ROUND_UP_TO_POWER_OF_2(new_size, AUTOBUFCHUNK);
-    p = realloc(autobuf->buf, autobuf->size);
+    int roundUpSize = ROUND_UP_TO_POWER_OF_2(new_size, AUTOBUFCHUNK);
+    p = realloc(autobuf->buf, roundUpSize);
     if (p == NULL) {
 #ifdef WIN32
       WSASetLastError(ENOMEM);
@@ -95,13 +96,14 @@ autobuf_enlarge(struct autobuf *autobuf, int new_size)
       return -1;
     }
     autobuf->buf = p;
+
+    memset(&autobuf->buf[autobuf->size], 0, roundUpSize - autobuf->size);
+    autobuf->size = roundUpSize;
   }
   return 0;
 }
 
-static int abuf_vappendf(struct autobuf *autobuf, const char *fmt, va_list ap) __attribute__ ((format(printf, 2, 0)));
-
-static int
+int
 abuf_vappendf(struct autobuf *autobuf, const char *format, va_list ap)
 {
   int rc;
@@ -173,6 +175,42 @@ abuf_memcpy(struct autobuf *autobuf, const void *p, const unsigned int len)
   return len;
 }
 
+int
+abuf_memcpy_prefix(struct autobuf *autobuf, const void *p, const unsigned int len)
+{
+  if (autobuf_enlarge(autobuf, autobuf->len + len) < 0) {
+    return -1;
+  }
+  memmove(&autobuf->buf[len], autobuf->buf, autobuf->len);
+  memcpy(autobuf->buf, p, len);
+  autobuf->len += len;
+  return len;
+}
+
+int
+abuf_pull(struct autobuf * autobuf, int len) {
+  char *p;
+  size_t newsize;
+
+  if (len != autobuf->len) {
+    memmove(autobuf->buf, &autobuf->buf[len], autobuf->len - len);
+  }
+  autobuf->len -= len;
+
+  newsize = ROUND_UP_TO_POWER_OF_2(autobuf->len + 1, AUTOBUFCHUNK);
+  p = realloc(autobuf->buf, newsize);
+  if (p == NULL) {
+#ifdef WIN32
+    WSASetLastError(ENOMEM);
+#else
+    errno = ENOMEM;
+#endif
+    return -1;
+  }
+  autobuf->buf = p;
+  autobuf->size = newsize;
+  return 0;
+}
 /*
  * Local Variables:
  * mode: c
index ea2aa23..6791b07 100644 (file)
@@ -55,11 +55,13 @@ struct autobuf {
 
 int EXPORT(abuf_init) (struct autobuf * autobuf, int initial_size);
 void EXPORT(abuf_free) (struct autobuf * autobuf);
+int EXPORT(abuf_vappendf) (struct autobuf *autobuf, const char *fmt, va_list ap) __attribute__ ((format(printf, 2, 0)));
 int EXPORT(abuf_appendf) (struct autobuf * autobuf, const char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
 int EXPORT(abuf_puts) (struct autobuf * autobuf, const char *s);
 int EXPORT(abuf_strftime) (struct autobuf * autobuf, const char *format, const struct tm * tm);
 int EXPORT(abuf_memcpy) (struct autobuf * autobuf, const void *p, const unsigned int len);
-
+int EXPORT(abuf_memcpy_prefix) (struct autobuf *autobuf, const void *p, const unsigned int len);
+int EXPORT(abuf_pull) (struct autobuf * autobuf, int len);
 #endif
 
 /*
index fda43ef..049679c 100644 (file)
@@ -74,6 +74,10 @@ avl_comp_mac(const void *ip1, const void *ip2)
   return memcmp(ip1, ip2, 6);
 }
 
+int avl_comp_strcasecmp(const void *txt1, const void *txt2) {
+  return strcasecmp(txt1, txt2);
+}
+
 void
 avl_init(struct avl_tree *tree, avl_tree_comp comp)
 {
index 1ecb564..36583f9 100644 (file)
@@ -125,6 +125,7 @@ extern avl_tree_comp avl_comp_prefix_origin_default;
 extern int avl_comp_ipv4(const void *, const void *);
 extern int avl_comp_ipv6(const void *, const void *);
 extern int avl_comp_mac(const void *, const void *);
+extern int avl_comp_strcasecmp(const void *, const void *);
 
 /*
  * Macro to define an inline function to map from a list_node offset back to the
index eb65cb5..6867947 100644 (file)
@@ -57,6 +57,14 @@ const struct in6_addr in6addr_v4mapped_loopback = IN6ADDR_V4MAPPED_LOOPBACK_INIT
 /* initialize it with all zeroes */
 const union olsr_ip_addr all_zero = {.v6 = IN6ADDR_ANY_INIT };
 
+void
+ip_map_4to6(union olsr_ip_addr *addr) {
+  /* ipv4-mapped-ipv6 = ::ff:<ipv4> */
+  memmove(&addr->v6.s6_addr[12], &addr->v4.s_addr, 4 * sizeof(uint8_t));
+  memset(&addr->v6.s6_addr[0], 0x00, 10 * sizeof(uint8_t));
+  memset(&addr->v6.s6_addr[10], 0xff, 2 * sizeof(uint8_t));
+}
+
 int
 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
 {
index b948a63..a383b12 100644 (file)
@@ -178,6 +178,9 @@ prefix_to_netmask4(uint8_t prefixlen)
 }
 
 extern const struct in6_addr EXPORT(in6addr_v4mapped_loopback);
+
+void EXPORT(ip_map_4to6) (union olsr_ip_addr *ip);
+
 #endif
 
 /*
index 15ae05d..29268db 100644 (file)
@@ -64,6 +64,7 @@
 #include "mid_set.h"
 #include "duplicate_set.h"
 #include "kernel_routes.h"
+#include "olsr_comport.h"
 
 #if defined linux
 #include <linux/types.h>
@@ -126,8 +127,6 @@ main(int argc, char *argv[])
   setbuf(stdout, NULL);
   setbuf(stderr, NULL);
 
-  OLSR_INFO(LOG_MAIN, "\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
-
   /* Using PID as random seed */
   srandom(getpid());
 
@@ -174,6 +173,8 @@ main(int argc, char *argv[])
     break;
   }                             /* switch */
 
+  OLSR_INFO(LOG_MAIN, "\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
+
   /* Sanity check configuration */
   if (olsr_sanity_check_cfg(olsr_cnf) < 0) {
     olsr_exit(EXIT_FAILURE);
@@ -318,6 +319,9 @@ main(int argc, char *argv[])
   /* Initialisation of different tables to be used. */
   olsr_init_tables();
 
+  /* initialize built in server services */
+  olsr_com_init();
+
   /* daemon mode */
 #ifndef WIN32
   if (!olsr_cnf->no_fork) {
index ac61637..ee13666 100644 (file)
 #endif
 
 /* options that have no short command line variant */
-#define CFG_LOG_DEBUG       256
-#define CFG_LOG_INFO        257
-#define CFG_LOG_WARN        258
-#define CFG_LOG_ERROR       269
-#define CFG_LOG_STDERR      270
-#define CFG_LOG_SYSLOG      271
-#define CFG_LOG_FILE        272
-
-#define CFG_OLSRPORT        273
-#define CFG_DLPATH          274
+enum cfg_long_options {
+  CFG_LOG_DEBUG = 256,
+  CFG_LOG_INFO,
+  CFG_LOG_WARN,
+  CFG_LOG_ERROR,
+  CFG_LOG_STDERR,
+  CFG_LOG_SYSLOG,
+  CFG_LOG_FILE,
+
+  CFG_OLSRPORT,
+  CFG_DLPATH,
+
+  CFG_HTTPPORT,
+  CFG_HTTPLIMIT,
+  CFG_TXTPORT,
+  CFG_TXTLIMIT
+};
 
 /* remember which log severities have been explicitly set */
 static bool cfg_has_log[LOG_SEVERITY_COUNT];
@@ -1078,6 +1085,42 @@ parse_cfg_option(const int optint, char *argstr, const int line, struct olsr_con
     rcfg->dlPath = strdup(argstr);
     PARSER_DEBUG_PRINTF("Dynamic library path: %s\n", rcfg->dlPath);
     break;
+  case CFG_HTTPPORT:
+    {
+      int arg = -1;
+      sscanf(argstr, "%d", &arg);
+      if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_http))))
+        rcfg->comport_http = arg;
+      PARSER_DEBUG_PRINTF("HTTP port: %d\n", rcfg->comport_http);
+    }
+    break;
+  case CFG_HTTPLIMIT:
+    {
+      int arg = -1;
+      sscanf(argstr, "%d", &arg);
+      if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_http_limit))))
+        rcfg->comport_http_limit = arg;
+      PARSER_DEBUG_PRINTF("HTTP connection limit: %d\n", rcfg->comport_http_limit);
+    }
+    break;
+  case CFG_TXTPORT:
+    {
+      int arg = -1;
+      sscanf(argstr, "%d", &arg);
+      if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_txt))))
+        rcfg->comport_txt = arg;
+      PARSER_DEBUG_PRINTF("TXT port: %d\n", rcfg->comport_txt);
+    }
+    break;
+  case CFG_TXTLIMIT:
+    {
+      int arg = -1;
+      sscanf(argstr, "%d", &arg);
+      if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_txt_limit))))
+        rcfg->comport_txt_limit = arg;
+      PARSER_DEBUG_PRINTF("TXT connection limit: %d\n", rcfg->comport_txt_limit);
+    }
+    break;
   default:
     sprintf(rmsg, "Unknown arg in line %d.\n", line);
     return CFG_ERROR;
@@ -1181,8 +1224,12 @@ olsr_parse_cfg(int argc, char *argv[], const char *file, char *rmsg, struct olsr
     {"Willingness",              required_argument, 0, 'w'}, /* (i) */
     {"RouterId",                 required_argument, 0, 'o'}, /* (ip) */
     {"SourceIpMode",             required_argument, 0, 's'}, /* (yes/no) */
-    {"OlsrPort",                 required_argument, 0, CFG_OLSRPORT}, /* (i) */
-    {"dlPath",                   required_argument, 0, CFG_DLPATH}, /* (path) */
+    {"OlsrPort",                 required_argument, 0, CFG_OLSRPORT},  /* (i) */
+    {"dlPath",                   required_argument, 0, CFG_DLPATH},    /* (path) */
+    {"HttpPort",                 required_argument, 0, CFG_HTTPPORT},  /* (i) */
+    {"HttpLimit",                required_argument, 0, CFG_HTTPLIMIT}, /* (i) */
+    {"TxtPort",                  required_argument, 0, CFG_TXTPORT},   /* (i) */
+    {"TxtLimit",                 required_argument, 0, CFG_TXTLIMIT},  /* (i) */
 
     {"UseHysteresis",            required_argument, 0,  0 }, /* ignored */
     {"HystScaling",              required_argument, 0,  0 }, /* ignored */
@@ -1281,7 +1328,7 @@ olsr_parse_cfg(int argc, char *argv[], const char *file, char *rmsg, struct olsr
       break;
 #endif
     case 'v':                  /* version */
-      /* Version string already printed */
+      fprintf(stderr,  "*** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
       rslt = CFG_EXIT;
       break;
     case 'h':                  /* help */
@@ -1618,6 +1665,11 @@ olsr_get_default_cfg(void)
   cfg->olsr_port = OLSRPORT;
   assert(cfg->dlPath == NULL);
 
+  cfg->comport_http       = DEF_HTTPPORT;
+  cfg->comport_http_limit = DEF_HTTPLIMIT;
+  cfg->comport_txt        = DEF_TXTPORT;
+  cfg->comport_txt_limit  = DEF_TXTLIMIT;
+
   assert(0 == memcmp(&all_zero, &cfg->router_id, sizeof(cfg->router_id)));
   assert(0 == cfg->source_ip_mode);
   cfg->will_int = 10 * HELLO_INTERVAL;
index 1899d09..4b42506 100644 (file)
 #define DEF_LQ_NAT_THRESH      1.0
 #define DEF_LQ_AGING           0.1
 #define DEF_CLEAR_SCREEN       false
+#define DEF_HTTPPORT           8080
+#define DEF_HTTPLIMIT          3
+#define DEF_TXTPORT            2006
+#define DEF_TXTLIMIT           3
 
 /* Bounds */
 
@@ -213,6 +217,11 @@ struct olsr_config {
   uint16_t olsr_port;                  /* port number used for OLSR packages */
   char *dlPath;                        /* absolute path for dynamic libraries */
 
+  uint16_t comport_http;               /* communication port for http connections */
+  uint16_t comport_http_limit;         /* maximum number of connections (including interactive ones) */
+  uint16_t comport_txt;                /* communication port for txt connections */
+  uint16_t comport_txt_limit;          /* maximum number of interactive connections */
+
   /*
    * Someone has added global variables to the config struct.
    * Because this saves binary link info we keep it that way.
index 390f91e..5432f36 100644 (file)
@@ -70,6 +70,7 @@ const char *LOG_SOURCE_NAMES[] = {
   "mid",
   "duplicate-set",
   "cookie",
+  "comport"
 };
 
 const char *LOG_SEVERITY_NAMES[] = {
index 3ec2280..1fd9fa6 100644 (file)
@@ -68,6 +68,7 @@ enum log_source {
   LOG_MID,                             //!< LOG_MID
   LOG_DUPLICATE_SET,                   //!< LOG_DUPLICATE_SET
   LOG_COOKIE,                          //!< LOG_COOKIE
+  LOG_COMPORT,                         //!< LOG_COMPORT
 
   /* this one must be the last of the enums ! */
   LOG_SOURCE_COUNT                     //!< LOG_SOURCE_COUNT
diff --git a/src/olsr_comport.c b/src/olsr_comport.c
new file mode 100644 (file)
index 0000000..623eda9
--- /dev/null
@@ -0,0 +1,637 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <netdb.h>
+#endif
+
+#include "defs.h"
+#include "olsr_logging.h"
+#include "olsr_cfg.h"
+#include "scheduler.h"
+#include "olsr_cookie.h"
+#include "common/autobuf.h"
+#include "common/avl.h"
+#include "ipcalc.h"
+#include "olsr.h"
+#include "olsr_comport_http.h"
+#include "olsr_comport_txt.h"
+#include "olsr_comport.h"
+
+#define HTTP_TIMEOUT  30000
+#define TXT_TIMEOUT 60000
+
+#define MAX_HTTP_PARA 10
+#define COMPORT_MAX_INPUTBUFFER 65536
+
+/* server socket */
+static int comsocket_http = 0;
+static int comsocket_txt = 0;
+
+static struct olsr_cookie_info *connection_cookie;
+static struct olsr_cookie_info *connection_timeout;
+
+/* counter for open connections */
+static int connection_http_count;
+static int connection_txt_count;
+
+static int olsr_com_openport(int port);
+
+static void olsr_com_parse_request(int fd, void *data, unsigned int flags);
+static void olsr_com_parse_connection(int fd, void *data, unsigned int flags);
+static void olsr_com_cleanup_session(struct comport_connection *con);
+static void olsr_com_parse_http(struct comport_connection *con,
+    unsigned int flags);
+static void olsr_com_parse_txt(struct comport_connection *con,
+    unsigned int flags);
+
+static void olsr_com_timeout_handler(void *);
+
+void olsr_com_init(void) {
+  connection_cookie = olsr_alloc_cookie("comport connections",
+      OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(connection_cookie,
+      sizeof(struct comport_connection));
+
+  connection_timeout = olsr_alloc_cookie("comport timout",
+      OLSR_COOKIE_TYPE_TIMER);
+
+  if (olsr_cnf->comport_http > 0) {
+    if ((comsocket_http = olsr_com_openport(olsr_cnf->comport_http)) == -1) {
+      return;
+    }
+
+    add_olsr_socket(comsocket_http, &olsr_com_parse_request, NULL, NULL,
+        SP_PR_READ);
+  }
+  if (olsr_cnf->comport_txt > 0) {
+    if ((comsocket_txt = olsr_com_openport(olsr_cnf->comport_txt)) == -1) {
+      return;
+    }
+
+    add_olsr_socket(comsocket_txt, &olsr_com_parse_request, NULL, NULL,
+        SP_PR_READ);
+  }
+
+  connection_http_count = 0;
+  connection_txt_count = 0;
+
+  olsr_com_init_http();
+  olsr_com_init_txt();
+}
+
+void olsr_com_activate_output(struct comport_connection *con) {
+  enable_olsr_socket(con->fd, &olsr_com_parse_connection, NULL, SP_PR_WRITE);
+}
+
+static int olsr_com_openport(int port) {
+  struct sockaddr_storage sst;
+  uint32_t yes = 1;
+  socklen_t addrlen;
+
+#if !defined REMOVE_LOG_WARN
+  char ipchar = olsr_cnf->ip_version == AF_INET ? '4' : '6';
+#endif
+
+  /* Init ipc socket */
+  int s = socket(olsr_cnf->ip_version, SOCK_STREAM, 0);
+  if (s == -1) {
+    OLSR_WARN(LOG_COMPORT, "Cannot open %d com-socket for IPv%c: %s\n", port, ipchar, strerror(errno));
+    return -1;
+  }
+
+  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(yes)) < 0) {
+    OLSR_WARN(LOG_COMPORT, "Com-port %d SO_REUSEADDR for IPv%c failed: %s\n", port, ipchar, strerror(errno));
+    CLOSESOCKET(s);
+    return -1;
+  }
+
+  /* Bind the socket */
+
+  /* complete the socket structure */
+  memset(&sst, 0, sizeof(sst));
+  if (olsr_cnf->ip_version == AF_INET) {
+    struct sockaddr_in *addr4 = (struct sockaddr_in *) &sst;
+    addr4->sin_family = AF_INET;
+    addrlen = sizeof(*addr4);
+#ifdef SIN6_LEN
+    addr4->sin_len = addrlen;
+#endif
+    addr4->sin_addr.s_addr = INADDR_ANY;
+    addr4->sin_port = htons(port);
+  } else {
+    struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &sst;
+    addr6->sin6_family = AF_INET6;
+    addrlen = sizeof(*addr6);
+#ifdef SIN6_LEN
+    addr6->sin6_len = addrlen;
+#endif
+    addr6->sin6_addr = in6addr_any;
+    addr6->sin6_port = htons(port);
+  }
+
+  /* bind the socket to the port number */
+  if (bind(s, (struct sockaddr *) &sst, addrlen) == -1) {
+    OLSR_WARN(LOG_COMPORT, "Com-port %d bind failed for IPv%c: %s\n", port, ipchar, strerror(errno));
+    CLOSESOCKET(s);
+    return -1;
+  }
+
+  /* show that we are willing to listen */
+  if (listen(s, 1) == -1) {
+    OLSR_WARN(LOG_COMPORT, "Com-port %d listen for IPv%c failed %s\n", port, ipchar, strerror(errno));
+    CLOSESOCKET(s);
+    return -1;
+  }
+
+  return s;
+}
+
+static void olsr_com_parse_request(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
+  struct comport_connection *con;
+  struct sockaddr_storage addr;
+  socklen_t addrlen;
+  int sock;
+#if !defined REMOVE_LOG_DEBUG
+  struct ipaddr_str buf;
+#endif
+
+  addrlen = sizeof(addr);
+  sock = accept(fd, (struct sockaddr *) &addr, &addrlen);
+  if (sock < 0) {
+    return;
+  }
+
+  con = olsr_cookie_malloc(connection_cookie);
+  abuf_init(&con->in, 1024);
+  abuf_init(&con->out, 0);
+
+  con->is_http = fd == comsocket_http;
+  con->is_csv = false;
+  con->fd = sock;
+
+  if (olsr_cnf->ip_version == AF_INET6) {
+    struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr;
+    con->addr.v6 = addr6->sin6_addr;
+  } else {
+    struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr;
+    con->addr.v4 = addr4->sin_addr;
+  }
+
+  if (con->is_http) {
+    if (connection_http_count < olsr_cnf->comport_http_limit) {
+      connection_http_count++;
+      con->state = HTTP_LOGIN;
+      con->send_as = PLAIN;
+      con->timeout_value = HTTP_TIMEOUT;
+    } else {
+      con->state = SEND_AND_QUIT;
+      con->send_as = HTTP_503_SERVICE_UNAVAILABLE;
+    }
+  } else { /* !con->is_http */
+    if (connection_txt_count < olsr_cnf->comport_txt_limit) {
+      connection_txt_count++;
+      con->state = INTERACTIVE;
+      con->send_as = PLAIN;
+      con->timeout_value = TXT_TIMEOUT;
+    } else {
+      abuf_puts(&con->out, "Too many txt connections, sorry...\n");
+      con->state = SEND_AND_QUIT;
+      con->send_as = PLAIN;
+    }
+  }
+
+  OLSR_DEBUG(LOG_COMPORT, "Got connection through socket %d from %s.\n",
+      sock, olsr_ip_to_string(&buf, &con->addr));
+
+  con->timeout = olsr_start_timer(con->timeout_value, 0, false,
+      &olsr_com_timeout_handler, con, connection_timeout->ci_id);
+
+  add_olsr_socket(sock, &olsr_com_parse_connection, NULL, con, SP_PR_READ
+      | SP_PR_WRITE);
+}
+
+static void olsr_com_cleanup_session(struct comport_connection *con) {
+  if (con->is_http) {
+    connection_http_count--;
+  } else {
+    connection_txt_count--;
+  }
+
+  if (con->stop_handler) {
+    con->stop_handler(con);
+  }
+  remove_olsr_socket(con->fd, &olsr_com_parse_connection, NULL);
+  CLOSESOCKET(con->fd);
+
+  abuf_free(&con->in);
+  abuf_free(&con->out);
+
+  olsr_cookie_free(connection_cookie, con);
+}
+
+static void olsr_com_timeout_handler(void *data) {
+  struct comport_connection *con = data;
+  olsr_com_cleanup_session(con);
+}
+
+static void olsr_com_parse_connection(int fd, void *data, unsigned int flags) {
+  struct comport_connection *con = data;
+#if !defined(REMOVE_LOG_WARN)
+  struct ipaddr_str buf;
+#endif
+
+  OLSR_DEBUG(LOG_COMPORT, "Parsing connection of socket %d\n", fd);
+  /* read data if necessary */
+  if (flags & SP_PR_READ) {
+    char buffer[1024];
+    int len;
+
+    len = recv(fd, buffer, sizeof(buffer), 0);
+    if (len > 0) {
+      OLSR_DEBUG(LOG_COMPORT, "  recv returned %d\n", len);
+      if (con->state != SEND_AND_QUIT) {
+        abuf_memcpy(&con->in, buffer, len);
+      }
+
+      if (con->in.len > COMPORT_MAX_INPUTBUFFER) {
+        if (con->state == INTERACTIVE) {
+          abuf_puts(&con->out, "Sorry, input buffer overflow...\n");
+        } else if (con->state == HTTP_LOGIN) {
+          con->send_as = HTTP_413_REQUEST_TOO_LARGE;
+        }
+        con->state = SEND_AND_QUIT;
+      }
+    } else if (len < 0) {
+      OLSR_WARN(LOG_COMPORT, "Error while reading from communication stream with %s: %s\n",
+          olsr_ip_to_string(&buf, &con->addr), strerror(errno));
+      con->state = CLEANUP;
+    }
+  }
+
+  switch (con->state) {
+    case HTTP_LOGIN:
+      olsr_com_parse_http(con, flags);
+      break;
+    case INTERACTIVE:
+      olsr_com_parse_txt(con, flags);
+      break;
+    default:
+      break;
+  }
+
+  /* maybe we have to create an error message */
+  if (con->out.len == 0 && con->state == SEND_AND_QUIT && con->send_as != PLAIN
+      && con->send_as != HTTP_PLAIN && con->send_as != HTTP_200_OK) {
+    olsr_com_create_httperror(con);
+  }
+
+  /* send data if necessary */
+  if (con->out.len > 0) {
+    if (con->state == SEND_AND_QUIT && con->send_as != PLAIN) {
+      /* create header */
+      olsr_com_build_httpheader(con);
+      con->send_as = PLAIN;
+    }
+
+    if (flags & SP_PR_WRITE) {
+      int len;
+
+      len = send(fd, con->out.buf, con->out.len, 0);
+      if (len > 0) {
+        OLSR_DEBUG(LOG_COMPORT, "  send returned %d\n", len);
+        abuf_pull(&con->out, len);
+      } else if (len < 0) {
+        OLSR_WARN(LOG_COMPORT, "Error while writing to communication stream with %s: %s\n",
+            olsr_ip_to_string(&buf, &con->addr), strerror(errno));
+        con->state = CLEANUP;
+      }
+    } else {
+      OLSR_DEBUG(LOG_COMPORT, "  activating output in scheduler\n");
+      enable_olsr_socket(fd, &olsr_com_parse_connection, NULL, SP_PR_WRITE);
+    }
+  }
+  if (con->out.len == 0) {
+    OLSR_DEBUG(LOG_COMPORT, "  deactivating output in scheduler\n");
+    disable_olsr_socket(fd, &olsr_com_parse_connection, NULL, SP_PR_WRITE);
+    if (con->state == SEND_AND_QUIT) {
+      con->state = CLEANUP;
+    }
+  }
+
+  fprintf(stderr, "State: %d\n", con->state);
+
+  /* end of connection ? */
+  if (con->state == CLEANUP) {
+    OLSR_DEBUG(LOG_COMPORT, "  cleanup\n");
+    /* clean up connection by calling timeout directly */
+    olsr_stop_timer(con->timeout);
+    olsr_com_cleanup_session(con);
+  }
+  return;
+}
+
+static void olsr_com_parse_http(struct comport_connection *con,
+    unsigned int flags  __attribute__ ((unused))) {
+  char *para_keyvalue[MAX_HTTP_PARA * 2] = { NULL }, *para = NULL, *str = NULL;
+  int para_count = 0;
+  char req_type[11] = { 0 };
+  char filename[252] = { 0 };
+  char filename_copy[252] = { 0 };
+  char http_version[11] = { 0 };
+
+  int idx = 0;
+  int i = 0;
+
+  /*
+   * find end of http header, might be useful for POST to keep the index !
+   * (implemented as a finite element automaton)
+   */
+
+  while (i < 5) {
+    switch (con->in.buf[idx++]) {
+      case '\0':
+        i = 6;
+        break;
+      case '\r':
+        i = (i == 3) ? 4 : 2;
+        break;
+      case '\n':
+        if (i == 1 || i == 4) {
+          i = 5;
+        } else if (i == 2) {
+          i = 3;
+        } else {
+          i = 1;
+        }
+        break;
+      default:
+        i = 0;
+        break;
+    }
+  }
+
+  if (i != 5) {
+    OLSR_DEBUG(LOG_COMPORT, "  need end of http header, still waiting...\n");
+    return;
+  }
+
+  /* got http header */
+  if (sscanf(con->in.buf, "%10s %250s %10s\n", req_type, filename, http_version)
+      != 3 || (strcmp(http_version, "HTTP/1.1") != 0 && strcmp(http_version,
+      "HTTP/1.0") != 0)) {
+    con->send_as = HTTP_400_BAD_REQ;
+    con->state = SEND_AND_QUIT;
+    return;
+  }
+
+  OLSR_DEBUG(LOG_COMPORT, "HTTP Request: %s %s %s\n", req_type, filename, http_version);
+
+  /* store a copy for the http_handlers */
+  strcpy(filename_copy, filename);
+  if (strcmp(req_type, "POST") == 0) {
+    /* load the rest of the header for POST commands */
+    char *lengthField = strstr(con->in.buf, "\nContent-Length:");
+    int clen = 0;
+
+    if (lengthField == NULL) {
+      con->send_as = HTTP_400_BAD_REQ;
+      con->state = SEND_AND_QUIT;
+      return;
+    }
+
+    sscanf(lengthField, "%*s %d\n", &clen);
+    if (con->in.len < idx + clen) {
+      /* we still need more data */
+      return;
+    }
+    para = &con->in.buf[idx];
+  }
+
+  /* strip the URL marker away */
+  str = strchr(filename, '#');
+  if (str) {
+    *str = 0;
+  }
+
+  /* we have everything to process the http request */
+  con->state = SEND_AND_QUIT;
+  if (strcmp(req_type, "GET") == 0) {
+    /* HTTP-GET request */
+    para = strchr(filename, '?');
+    if (para != NULL) {
+      *para++ = 0;
+    }
+  } else if (strcmp(req_type, "POST") != 0) {
+    con->send_as = HTTP_501_NOT_IMPLEMENTED;
+    return;
+  }
+
+  /* handle HTTP GET & POST including parameters */
+  while (para && para_count < MAX_HTTP_PARA * 2) {
+    /* split the string at the next '=' (the key/value splitter) */
+    str = strchr(para, '=');
+    if (!str) {
+      break;
+    }
+    *str++ = 0;
+
+    /* we have null terminated key at *para. Now decode the key */
+    para_keyvalue[para_count++] = para;
+    olsr_com_decode_url(para);
+
+    /* split the string at the next '&' (the splitter of multiple key/value pairs */
+    para = strchr(str, '&');
+    if (para) {
+      *para++ = 0;
+    }
+
+    /* we have a null terminated value at *str, Now decode it */
+    olsr_com_decode_url(str);
+    para_keyvalue[para_count++] = str;
+  }
+
+  /* create body */
+  i = strlen(filename);
+
+  /*
+   * add a '/' at the end if it's not there to detect
+   *  paths without terminating '/' from the browser
+   */
+  if (filename[i - 1] != '/') {
+    strcat(filename, "/");
+  }
+
+  while (i > 0) {
+    if (olsr_com_handle_htmlsite(con, filename, filename_copy, para_count >> 1,
+        para_keyvalue)) {
+      return;
+    }
+
+    /* try to find a handler for a path prefix */
+    do {
+      filename[i--] = 0;
+    } while (i > 0 && filename[i] != '/');
+  }
+  con->send_as = HTTP_404_NOT_FOUND;
+}
+
+static void olsr_com_parse_txt(struct comport_connection *con,
+    unsigned int flags  __attribute__ ((unused))) {
+  enum olsr_txtcommand_result res;
+  char *eol;
+  int len;
+  bool processedCommand = false;
+  uint32_t old_timeout;
+
+  old_timeout = con->timeout_value;
+
+  /* loop over input */
+  while (con->in.len > 0 && con->state == INTERACTIVE) {
+    char *para = NULL, *cmd = NULL, *next = NULL;
+
+    /* search for end of line */
+    eol = memchr(con->in.buf, '\n', con->in.len);
+
+    if (eol == NULL) {
+      break;
+    }
+
+    /* terminate line with a 0 */
+    if (eol != con->in.buf && eol[-1] == '\r') {
+      eol[-1] = 0;
+    }
+    *eol++ = 0;
+
+    /* handle line */
+    OLSR_DEBUG(LOG_COMPORT, "Interactive console: %s\n", con->in.buf);
+    cmd = &con->in.buf[0];
+    processedCommand = true;
+
+    while (cmd) {
+      len = con->out.len;
+
+      /* handle difference between multicommand and singlecommand mode */
+      if (cmd[0] != '/') {
+        para = strchr(cmd, ' ');
+        if (para != NULL) {
+          *para++ = 0;
+        }
+      } else {
+        cmd++; /* skip first '/' */
+
+        next = strchr(cmd, '/');
+        if (next) {
+          *next++ = 0;
+        }
+      }
+
+      /* if we are doing continous output, stop it ! */
+      if (con->stop_handler) {
+        con->stop_handler(con);
+        con->stop_handler = NULL;
+      }
+
+      if (strlen(cmd) != 0) {
+        res = olsr_com_handle_txtcommand(con, cmd, para);
+        switch (res) {
+          case CONTINUE:
+            break;
+          case CONTINOUS:
+            break;
+          case ABUF_ERROR:
+            con->out.len = len;
+            abuf_appendf(&con->out,
+                "Error in autobuffer during command '%s'.\n", cmd);
+            break;
+          case UNKNOWN:
+            con->out.len = len;
+            abuf_appendf(&con->out, "Error, unknown command '%s'\n",
+                con->in.buf);
+            break;
+          case QUIT:
+            con->state = SEND_AND_QUIT;
+            break;
+        }
+        /* put an empty line behind each command if not in csv mode */
+        if (!con->is_csv) {
+          abuf_puts(&con->out, "\n");
+        }
+      }
+      cmd = next;
+    }
+
+    /* remove line from input buffer */
+    abuf_pull(&con->in, eol - con->in.buf);
+
+    if (con->in.buf[0] == '/') {
+      /* end of multiple command line */
+      con->state = SEND_AND_QUIT;
+    }
+  }
+
+  if (old_timeout != con->timeout_value) {
+    if (con->timeout) {
+      if (con->timeout_value > 0) {
+        olsr_change_timer(con->timeout, con->timeout_value, 0, false);
+      }
+      else {
+        olsr_stop_timer(con->timeout);
+        con->timeout = NULL;
+      }
+    } else if (con->timeout_value > 0) {
+      con->timeout = olsr_start_timer(con->timeout_value, 0, false,
+          &olsr_com_timeout_handler, con, connection_timeout->ci_id);
+    }
+  }
+
+  /* print prompt */
+  if (processedCommand && con->state == INTERACTIVE && !con->is_csv) {
+    abuf_puts(&con->out, "> ");
+  }
+}
+
diff --git a/src/olsr_comport.h b/src/olsr_comport.h
new file mode 100644 (file)
index 0000000..f06b028
--- /dev/null
@@ -0,0 +1,106 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#ifndef OLSR_COMPORT_H_
+#define OLSR_COMPORT_H_
+
+#include "defs.h"
+#include "common/autobuf.h"
+
+enum http_header_type {
+  PLAIN,
+  HTTP_PLAIN,
+  HTTP_200_OK = 200,
+  HTTP_400_BAD_REQ = 400,
+  HTTP_401_UNAUTHORIZED = 401,
+  HTTP_403_FORBIDDEN = 403,
+  HTTP_404_NOT_FOUND = 404,
+  HTTP_413_REQUEST_TOO_LARGE = 413,
+  HTTP_501_NOT_IMPLEMENTED = 501,
+  HTTP_503_SERVICE_UNAVAILABLE = 503
+};
+
+enum connection_state {
+  HTTP_LOGIN, INTERACTIVE, SEND_AND_QUIT, CLEANUP
+};
+
+struct comport_connection;
+typedef void (*olsr_txt_stop_continous) (struct comport_connection *con);
+
+struct comport_connection {
+  /*
+   * public part of the session data
+   *
+   * variables marked RW might be written from txt commands, those with
+   * an "R" mark are read only
+   */
+
+  /* timeout for txt sessions (RW) */
+  uint32_t timeout_value;
+
+  /* ip addr of peer (R) */
+  union olsr_ip_addr addr;
+
+  /* true if the txt session is in CSV mode (RW) */
+  bool is_csv;
+
+  /* callback and data to stop a continous output txt command (RW) */
+  olsr_txt_stop_continous stop_handler;
+  void *stop_data[4];
+
+  /* output buffer, anything inside will be written to the peer as
+   * soon as possible */
+  struct autobuf out;
+
+  /*
+   * internal part of the server
+   */
+  int fd;
+  enum connection_state state;
+  enum http_header_type send_as;
+  struct timer_entry *timeout;
+  bool is_http;
+  struct autobuf in;
+};
+
+void olsr_com_init(void);
+void EXPORT(olsr_com_activate_output) (struct comport_connection *con);
+
+#endif /* OLSR_COMPORT_H_ */
diff --git a/src/olsr_comport_http.c b/src/olsr_comport_http.c
new file mode 100644 (file)
index 0000000..1cdee83
--- /dev/null
@@ -0,0 +1,280 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#include <string.h>
+
+#include "common/autobuf.h"
+#include "common/avl.h"
+#include "olsr_logging.h"
+#include "olsr_cookie.h"
+#include "olsr_comport.h"
+#include "olsr_comport_http.h"
+#include "olsr_cfg.h"
+
+#define HTTP_VERSION "HTTP/1.1"
+
+static struct avl_tree http_handler_tree;
+static struct olsr_cookie_info *htmlsite_cookie;
+
+/**Response types */
+static char http_200_response[] = "OK";
+static char http_400_response[] = "Bad Request";
+static char http_401_response[] = "Unauthorized";
+static char http_403_response[] = "Forbidden";
+static char http_404_response[] = "Not Found";
+static char http_413_response[] = "Request Entity Too Large";
+static char http_501_response[] = "Not Implemented";
+static char http_503_response[] = "Service Unavailable";
+
+/* sample for a static html page */
+static void init_test(void) {
+  static char content[] = "<html><body>Yes, you got it !</body></html>";
+  static char path[] = "/";
+  static char acl[] = "d2lraTpwZWRpYQ=="; /* base 64 .. this is "wikipedia" */
+  static char *aclPtr[] = { acl };
+  struct olsr_html_site *site;
+
+  site = olsr_com_add_htmlsite(path, content, strlen(content));
+  olsr_com_set_htmlsite_acl_auth(site, NULL, 1, aclPtr);
+}
+
+void
+olsr_com_init_http(void) {
+  avl_init(&http_handler_tree, &avl_comp_strcasecmp);
+
+  htmlsite_cookie = olsr_alloc_cookie("comport http sites", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(htmlsite_cookie, sizeof(struct olsr_html_site));
+
+  init_test();
+}
+
+struct olsr_html_site *
+olsr_com_add_htmlsite(char *path, char *content, size_t length) {
+  struct olsr_html_site *site;
+
+  site = olsr_cookie_malloc(htmlsite_cookie);
+  site->node.key = strdup(path);
+
+  site->static_site = true;
+  site->site_data = content;
+  site->site_length = length;
+
+  avl_insert(&http_handler_tree, &site->node, AVL_DUP_NO);
+  return site;
+}
+
+struct olsr_html_site *
+olsr_com_add_htmlhandler(void(*sitehandler)(struct autobuf *buf, char *path, int parameter_count, char *parameters[]),
+    char *path) {
+  struct olsr_html_site *site;
+
+  site = olsr_cookie_malloc(htmlsite_cookie);
+  site->node.key = strdup(path);
+
+  site->static_site = false;
+  site->sitehandler = sitehandler;
+
+  avl_insert(&http_handler_tree, &site->node, AVL_DUP_NO);
+  return site;
+}
+
+void
+olsr_com_remove_htmlsite(struct olsr_html_site *site) {
+  avl_delete(&http_handler_tree, &site->node);
+  free(site->node.key);
+  olsr_cookie_free(htmlsite_cookie, site);
+}
+
+void
+olsr_com_set_htmlsite_acl_auth(struct olsr_html_site *site, struct ip_acl *ipacl, int auth_count, char **auth_entries) {
+  site->acl = ipacl;
+  site->auth_count = auth_count;
+  site->auth = auth_entries;
+}
+
+/* handle the html site. returns true on successful handling (even if it was unauthorized)
+ * false if we did not find a site
+*/
+bool
+olsr_com_handle_htmlsite(struct comport_connection *con, char *path,
+    char *fullpath, int para_count, char **para) {
+  char *str;
+  int i;
+  struct olsr_html_site *site;
+
+  site = (struct olsr_html_site *)avl_find(&http_handler_tree, path);
+  if (site == NULL) {
+    return false;
+  }
+
+  /* check if username/password is necessary */
+  if (site->auth) {
+    /* test for correct ACL */
+    char key[256] = { 0 };
+
+    con->send_as = HTTP_401_UNAUTHORIZED;
+
+    str = strstr(con->in.buf, "\nAuthorization: Basic ");
+    if (str != NULL && sscanf(str + 1, "%*s %*s %s\n", key) == 1) {
+      OLSR_DEBUG(LOG_COMPORT, "ACL string received: %s\n", key);
+      for (i = 0; i < site->auth_count; i++) {
+        if (strcmp(site->auth[i], key) == 0) {
+          con->send_as = HTTP_200_OK;
+          break;
+        }
+      }
+    }
+    if (con->send_as == HTTP_401_UNAUTHORIZED) {
+      return true;
+    }
+  }
+
+  /* check if ip is allowed */
+  if (site->acl != NULL && !ip_acl_acceptable(site->acl, &con->addr, olsr_cnf->ip_version)) {
+    con->send_as = HTTP_403_FORBIDDEN;
+    return true;
+  }
+
+  /* call site handler */
+  if (site->static_site) {
+    abuf_memcpy(&con->out, site->site_data, site->site_length);
+  } else {
+    site->sitehandler(&con->out, fullpath, para_count, para);
+  }
+  con->send_as = HTTP_200_OK;
+  return true;
+}
+
+void
+olsr_com_build_httpheader(struct comport_connection *con) {
+  struct autobuf buf;
+  time_t currtime;
+
+  abuf_init(&buf, 1024);
+
+  abuf_appendf(&buf, "%s %d %s\r\n", HTTP_VERSION, con->send_as, olsr_com_get_http_message(con->send_as));
+
+  /* Date */
+  time(&currtime);
+  abuf_strftime(&buf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
+
+  /* Server version */
+  abuf_appendf(&buf, "Server: %s %s %s %s\r\n", olsrd_version, build_date, build_host, HTTP_VERSION);
+
+  /* connection-type */
+  abuf_puts(&buf, "Connection: closed\r\n");
+
+  /* MIME type */
+  abuf_appendf(&buf, "Content-type: text/%s\r\n", con->send_as != HTTP_PLAIN ? "html" : "plain");
+
+  /* Content length */
+  if (con->out.len > 0) {
+    abuf_appendf(&buf, "Content-length: %u\r\n", con->out.len);
+  }
+
+  if (con->send_as == HTTP_401_UNAUTHORIZED) {
+    abuf_appendf(&buf, "WWW-Authenticate: Basic realm=\"%s\"\r\n", "RealmName");
+  }
+  /* Cache-control
+   * No caching dynamic pages
+   */
+  abuf_puts(&buf, "Cache-Control: no-cache\r\n");
+
+  if (con->send_as == HTTP_PLAIN) {
+    abuf_puts(&buf, "Accept-Ranges: bytes\r\n");
+  }
+  /* End header */
+  abuf_puts(&buf, "\r\n");
+
+  abuf_memcpy_prefix(&con->out, buf.buf, buf.len);
+  OLSR_DEBUG(LOG_PLUGINS, "HEADER:\n%s", buf.buf);
+
+  abuf_free(&buf);
+}
+
+void
+olsr_com_create_httperror(struct comport_connection *con) {
+  abuf_appendf(&con->out, "<body><h1>HTTP error %d: %s</h1></body>", con->send_as, olsr_com_get_http_message(con->send_as));
+}
+
+char *
+olsr_com_get_http_message(enum http_header_type type) {
+  static char nothing[] = "";
+
+  switch (type) {
+    case HTTP_PLAIN:
+    case HTTP_200_OK:
+      return http_200_response;
+    case HTTP_400_BAD_REQ:
+      return http_400_response;
+    case HTTP_401_UNAUTHORIZED:
+      return http_401_response;
+    case HTTP_403_FORBIDDEN:
+      return http_403_response;
+    case HTTP_404_NOT_FOUND:
+      return http_404_response;
+    case HTTP_413_REQUEST_TOO_LARGE:
+      return http_413_response;
+    case HTTP_501_NOT_IMPLEMENTED:
+      return http_501_response;
+    case HTTP_503_SERVICE_UNAVAILABLE:
+      return http_503_response;
+    default:
+      return nothing;
+  }
+}
+
+void olsr_com_decode_url(char *str) {
+  char *dst = str;
+
+  while (*str) {
+    if (*str == '%') {
+      int value = 0;
+
+      str++;
+      sscanf(str, "%02x", &value);
+      *dst++ = (char) value;
+      str += 2;
+    } else {
+      *dst++ = *str++;
+    }
+  }
+  *dst = 0;
+}
diff --git a/src/olsr_comport_http.h b/src/olsr_comport_http.h
new file mode 100644 (file)
index 0000000..45c0bc9
--- /dev/null
@@ -0,0 +1,88 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#ifndef OLSR_COMPORT_HTTP_H_
+#define OLSR_COMPORT_HTTP_H_
+
+#include "common/avl.h"
+#include "common/autobuf.h"
+#include "olsr_ip_acl.h"
+#include "olsr_comport.h"
+
+/* this is a html site datastructure for each site */
+/* it is stored in an AVL tree */
+struct olsr_html_site {
+  struct avl_node node;
+
+  bool static_site;   /* is this a static site y/n? */
+
+  char **auth;           /* ptr to list of char* name=passwd in base64 */
+  int auth_count;        /* number of list entries */
+
+  struct ip_acl *acl; /* allow only certain IPs ? */
+
+       /* for static sites... */
+  char *site_data;
+  size_t site_length;
+
+       /* for non static, this is the handler */
+  void (*sitehandler)(struct autobuf *buf, char *path, int parameter_count, char *parameters[]);
+};
+
+void olsr_com_init_http(void);
+
+struct olsr_html_site *EXPORT(olsr_com_add_htmlsite) (
+    char *path, char *content, size_t length);
+struct olsr_html_site *EXPORT(olsr_com_add_htmlhandler) (
+    void (*sitehandler)(struct autobuf *buf, char *path, int parameter_count, char *parameters[]),
+    char *path);
+void EXPORT(olsr_com_remove_htmlsite) (struct olsr_html_site *site);
+void EXPORT(olsr_com_set_htmlsite_acl_auth) (struct olsr_html_site *site,
+    struct ip_acl *acl, int auth_count, char **auth_entries);
+
+bool olsr_com_handle_htmlsite(struct comport_connection *con, char *path,
+    char *filename, int para_count, char **para);
+
+void EXPORT(olsr_com_build_httpheader) (struct comport_connection *con);
+void EXPORT(olsr_com_create_httperror) (struct comport_connection *con);
+char *EXPORT(olsr_com_get_http_message) (enum http_header_type type);
+void EXPORT(olsr_com_decode_url) (char *str);
+
+#endif /* OLSR_COMPORT_HTTP_H_ */
diff --git a/src/olsr_comport_txt.c b/src/olsr_comport_txt.c
new file mode 100644 (file)
index 0000000..6bd1629
--- /dev/null
@@ -0,0 +1,343 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#include <string.h>
+
+#include "olsr_cfg.h"
+#include "olsr_logging.h"
+#include "olsr_cookie.h"
+#include "olsr_ip_acl.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "olsr_comport.h"
+#include "olsr_comport_txt.h"
+
+struct txt_repeat_data {
+  struct timer_entry *timer;
+  struct autobuf *buf;
+  char *cmd;
+  char *param;
+  bool csv;
+};
+
+static struct avl_tree txt_normal_tree, txt_csv_tree, txt_help_tree;
+static struct olsr_cookie_info *txtcommand_cookie, *txt_repeattimer_cookie;
+
+static enum olsr_txtcommand_result olsr_txtcmd_quit(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_help(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_csv(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_csvoff(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_repeat(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_timeout(
+    struct comport_connection *con, char *cmd, char *param);
+static enum olsr_txtcommand_result olsr_txtcmd_version(
+    struct comport_connection *con, char *cmd, char *param);
+
+static enum olsr_txtcommand_result olsr_txtcmd_displayhelp(
+    struct comport_connection *con, char *cmd, char *param);
+
+
+static const char *txt_internal_names[] = {
+  "quit",
+  "exit",
+  "help",
+  "csv",
+  "csvoff",
+  "repeat",
+  "timeout",
+  "version"
+};
+
+static const char *txt_internal_help[] = {
+  "shuts down the terminal connection\n",
+  "shuts down the terminal connection\n",
+  "display the online help text\n",
+  "activates the csv (comma separated value) flag\n",
+  "deactivates the csv (comma separated value) flag\n",
+  "repeat <interval> <command>: repeats a command every <interval> seconds\n",
+  "timeout <interval>: set the timeout interval to <interval> seconds, 0 means no timeout\n"
+  "displays the version of the olsrd\n"
+};
+
+static olsr_txthandler txt_internal_handlers[] = {
+  olsr_txtcmd_quit,
+  olsr_txtcmd_quit,
+  olsr_txtcmd_help,
+  olsr_txtcmd_csv,
+  olsr_txtcmd_csvoff,
+  olsr_txtcmd_repeat,
+  olsr_txtcmd_timeout,
+  olsr_txtcmd_version
+};
+
+void olsr_com_init_txt(void) {
+  size_t i;
+
+  avl_init(&txt_normal_tree, &avl_comp_strcasecmp);
+  avl_init(&txt_csv_tree, &avl_comp_strcasecmp);
+  avl_init(&txt_help_tree, &avl_comp_strcasecmp);
+
+  txtcommand_cookie = olsr_alloc_cookie("comport txt commands", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(txtcommand_cookie, sizeof(struct olsr_txtcommand));
+
+  txt_repeattimer_cookie = olsr_alloc_cookie("txt repeat timer", OLSR_COOKIE_TYPE_TIMER);
+
+  for (i=0; i < ARRAYSIZE(txt_internal_names); i++) {
+    olsr_com_add_normal_txtcommand(txt_internal_names[i], txt_internal_handlers[i]);
+    olsr_com_add_csv_txtcommand(txt_internal_names[i], txt_internal_handlers[i]);
+    olsr_com_add_help_txtcommand(txt_internal_names[i], olsr_txtcmd_displayhelp);
+  }
+}
+
+struct olsr_txtcommand *
+olsr_com_add_normal_txtcommand (const char *command, olsr_txthandler handler) {
+  struct olsr_txtcommand *txt;
+
+  txt = olsr_cookie_malloc(txtcommand_cookie);
+  txt->node.key = strdup(command);
+  txt->handler = handler;
+
+  avl_insert(&txt_normal_tree, &txt->node, AVL_DUP_NO);
+  return txt;
+}
+
+struct olsr_txtcommand *
+olsr_com_add_csv_txtcommand (const char *command, olsr_txthandler handler) {
+  struct olsr_txtcommand *txt;
+
+  txt = olsr_cookie_malloc(txtcommand_cookie);
+  txt->node.key = strdup(command);
+  txt->handler = handler;
+
+  avl_insert(&txt_csv_tree, &txt->node, AVL_DUP_NO);
+  return txt;
+}
+
+struct olsr_txtcommand *
+olsr_com_add_help_txtcommand (const char *command, olsr_txthandler handler) {
+  struct olsr_txtcommand *txt;
+
+  txt = olsr_cookie_malloc(txtcommand_cookie);
+  txt->node.key = strdup(command);
+  txt->handler = handler;
+
+  avl_insert(&txt_help_tree, &txt->node, AVL_DUP_NO);
+  return txt;
+}
+
+void olsr_com_remove_normal_txtcommand (struct olsr_txtcommand *cmd) {
+  avl_delete(&txt_normal_tree, &cmd->node);
+  free(cmd->node.key);
+  olsr_cookie_free(txtcommand_cookie, cmd);
+}
+
+void olsr_com_remove_csv_txtcommand (struct olsr_txtcommand *cmd) {
+  avl_delete(&txt_csv_tree, &cmd->node);
+  free(cmd->node.key);
+  olsr_cookie_free(txtcommand_cookie, cmd);
+}
+
+void olsr_com_remove_help_txtcommand (struct olsr_txtcommand *cmd) {
+  avl_delete(&txt_help_tree, &cmd->node);
+  free(cmd->node.key);
+  olsr_cookie_free(txtcommand_cookie, cmd);
+}
+
+enum olsr_txtcommand_result
+olsr_com_handle_txtcommand(struct comport_connection *con, char *cmd, char *param) {
+  struct olsr_txtcommand *ptr;
+
+  ptr = (struct olsr_txtcommand *) avl_find(con->is_csv ? (&txt_csv_tree) : (&txt_normal_tree), cmd);
+
+  OLSR_DEBUG(LOG_COMPORT, "Looking for command '%s' (%s): %s\n",
+    cmd, con->is_csv ? "csv" : "normal", ptr ? "unknown" : "available");
+  if (ptr == NULL) {
+    return UNKNOWN;
+  }
+
+  if (ptr->acl) {
+    if (!ip_acl_acceptable(ptr->acl, &con->addr, olsr_cnf->ip_version)) {
+      return UNKNOWN;
+    }
+  }
+
+  return ptr->handler(con, cmd, param);
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_quit(struct comport_connection *con __attribute__ ((unused)),
+    char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused))) {
+  return QUIT;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_displayhelp(struct comport_connection *con,
+    char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused))) {
+  size_t i;
+
+  for (i=0; i<ARRAYSIZE(txt_internal_names); i++) {
+    if (strcasecmp(txt_internal_names[i], cmd) == 0) {
+      abuf_puts(&con->out, txt_internal_help[i]);
+      return CONTINUE;
+    }
+  }
+  return UNKNOWN;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_help(struct comport_connection *con,
+    char *cmd __attribute__ ((unused)), char *param) {
+  struct olsr_txtcommand *ptr;
+
+  if (param != NULL) {
+    ptr = (struct olsr_txtcommand *)avl_find(&txt_help_tree, cmd);
+    if (ptr != NULL) {
+      return ptr->handler(con, param, NULL);
+    }
+    return UNKNOWN;
+  }
+
+  if (!con->is_csv) {
+    abuf_puts(&con->out, "Known commands:\n");
+  }
+
+  ptr = (struct olsr_txtcommand *)avl_walk_first(con->is_csv ? (&txt_csv_tree) : (&txt_normal_tree));
+  while (ptr) {
+    abuf_appendf(&con->out, con->is_csv ? ",%s" : "  %s\n", (char *)ptr->node.key);
+    ptr = (struct olsr_txtcommand *)avl_walk_next(&ptr->node);
+  }
+
+  abuf_puts(&con->out, con->is_csv ? "\n" : "Use 'help <command> to see a help text for a certain command\n");
+  return CONTINUE;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_csv(struct comport_connection *con,
+    char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused))) {
+  con->is_csv = true;
+  return CONTINUE;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_csvoff(struct comport_connection *con,
+    char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused))) {
+  con->is_csv = false;
+  return CONTINUE;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_timeout(struct comport_connection *con,
+    char *cmd __attribute__ ((unused)), char *param) {
+  con->timeout_value = (uint32_t)strtoul(param, NULL, 10);
+  return CONTINUE;
+}
+
+static void olsr_txt_repeat_stophandler(struct comport_connection *con) {
+  olsr_stop_timer((struct timer_entry *)con->stop_data[0]);
+  free(con->stop_data[1]);
+
+  con->stop_handler = NULL;
+  con->stop_data[0] = NULL;
+  con->stop_data[1] = NULL;
+  con->stop_data[2] = NULL;
+}
+
+static void olsr_txt_repeat_timer(void *data) {
+  struct comport_connection *con = data;
+
+  if (olsr_com_handle_txtcommand(con, con->stop_data[1], con->stop_data[2]) != CONTINUE) {
+    con->stop_handler(con);
+  }
+  olsr_com_activate_output(con);
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_repeat(struct comport_connection *con, char *cmd __attribute__ ((unused)), char *param) {
+  int interval = 0;
+  char *ptr;
+  struct timer_entry *timer;
+
+  if (con->stop_handler) {
+    abuf_puts(&con->out, "Error, you cannot stack continous output commands\n");
+    return CONTINUE;
+  }
+
+  if (param == NULL || (ptr = strchr(param, ' ')) == NULL) {
+    abuf_puts(&con->out, "Missing parameters for repeat\n");
+    return CONTINUE;
+  }
+
+  ptr++;
+
+  interval = atoi(param);
+
+  timer = olsr_start_timer(interval * 1000, 0, true, &olsr_txt_repeat_timer, con, txt_repeattimer_cookie->ci_id);
+  con->stop_handler = olsr_txt_repeat_stophandler;
+  con->stop_data[0] = timer;
+  con->stop_data[1] = strdup(ptr);
+  con->stop_data[2] = NULL;
+
+  /* split command/parameter and remember it */
+  ptr = strchr(con->stop_data[1], ' ');
+  if (ptr != NULL) {
+    /* found a parameter */
+    *ptr++ = 0;
+    con->stop_data[2] = ptr;
+  }
+
+  /* start command the first time */
+  if (olsr_com_handle_txtcommand(con, con->stop_data[1], con->stop_data[2]) != CONTINUE) {
+    con->stop_handler(con);
+  }
+  return CONTINOUS;
+}
+
+static enum olsr_txtcommand_result
+olsr_txtcmd_version(struct comport_connection *con, char *cmd __attribute__ ((unused)), char *param __attribute__ ((unused))) {
+  abuf_appendf(&con->out,
+      con->is_csv ? "version,%s,%s,%s\n" : " *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
+      olsrd_version, build_date, build_host);
+  return CONTINUE;
+}
diff --git a/src/olsr_comport_txt.h b/src/olsr_comport_txt.h
new file mode 100644 (file)
index 0000000..224819e
--- /dev/null
@@ -0,0 +1,84 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+#ifndef OLSR_COMPORT_TXT_H_
+#define OLSR_COMPORT_TXT_H_
+
+#include "common/autobuf.h"
+#include "common/avl.h"
+#include "olsr_ip_acl.h"
+
+#include "olsr_comport.h"
+
+enum olsr_txtcommand_result {
+  CONTINUE,
+  CONTINOUS,
+  QUIT,
+  ABUF_ERROR,
+  UNKNOWN,
+};
+
+typedef enum olsr_txtcommand_result (*olsr_txthandler)
+    (struct comport_connection *con, char *command, char *parameter);
+
+struct olsr_txtcommand {
+  struct avl_node node;
+  struct ip_acl *acl;
+
+  olsr_txthandler handler;
+};
+
+
+void olsr_com_init_txt(void);
+
+struct olsr_txtcommand *EXPORT(olsr_com_add_normal_txtcommand) (
+    const char *command, olsr_txthandler handler);
+struct olsr_txtcommand *EXPORT(olsr_com_add_csv_txtcommand) (
+    const char *command, olsr_txthandler handler);
+struct olsr_txtcommand *EXPORT(olsr_com_add_help_txtcommand) (
+    const char *command, olsr_txthandler handler);
+void EXPORT(olsr_com_remove_normal_txtcommand) (struct olsr_txtcommand *cmd);
+void EXPORT(olsr_com_remove_csv_txtcommand) (struct olsr_txtcommand *cmd);
+void EXPORT(olsr_com_remove_help_txtcommand) (struct olsr_txtcommand *cmd);
+
+enum olsr_txtcommand_result olsr_com_handle_txtcommand(struct comport_connection *con,
+    char *command, char *parameter);
+
+#endif /* OLSR_COMPORT_TXT_H_ */
index 4a79c3e..d54104d 100644 (file)
@@ -195,16 +195,14 @@ ip_acl_plugin_parse(const char *value, union olsr_ip_addr *addr)
     *slash++ = 0;
   }
 
-  if (inet_pton(olsr_cnf->ip_version, arg, addr) < 0) {
+  if (inet_pton(ipv4 ? AF_INET : AF_INET6, arg, addr) < 0) {
     OLSR_WARN(LOG_PLUGINS, "Error, illegal ip net '%s'\n", value);
     return -1;
   }
 
   if (ipv4 && prefix == 128) {
     /* translate to ipv6 if neccessary */
-    memmove(&addr->v6.s6_addr[12], &addr->v4.s_addr, 4 * sizeof(uint8_t));
-    memset(&addr->v6.s6_addr[0], 0x00, 10 * sizeof(uint8_t));
-    memset(&addr->v6.s6_addr[10], 0xff, 2 * sizeof(uint8_t));
+    ip_map_4to6(addr);
   } else if (ipv6 && olsr_cnf->ip_version == AF_INET) {
     OLSR_WARN(LOG_PLUGINS, "Ignore Ipv6 address '%s' in ipv4 mode\n", value);
     return -1;
index be1ac00..f14ce47 100644 (file)
@@ -506,7 +506,7 @@ calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val)
    * Play some tricks to avoid overflows with integer arithmetic.
    */
   jitter_time = (jitter_pct * rel_time) / 100;
-  jitter_time = random_val / (1 + RAND_MAX / jitter_time);
+  jitter_time = random_val / (1 + RAND_MAX / (jitter_time + 1));
 
   OLSR_DEBUG(LOG_SCHEDULER, "TIMER: jitter %u%% rel_time %ums to %ums\n", jitter_pct, rel_time, rel_time - jitter_time);