Web-interface HTTPTunnel
This example explains how to create a web-page for the package httptunnel.
Usages information:
# hts --help Usage: hts [OPTION]... [PORT] Listen for incoming httptunnel connections at PORT (default port is 8888). When a connection is made, I/O is redirected to the destination specified by the --device, --forward-port or --stdin-stdout switch. -c, --content-length BYTES use HTTP PUT requests of BYTES size (k, M, and G postfixes recognized) -d, --device DEVICE use DEVICE for input and output -F, --forward-port HOST:PORT connect to PORT at HOST and use it for input and output -h, --help display this help and exit -k, --keep-alive SECONDS send keepalive bytes every SECONDS seconds (default is 5) -M, --max-connection-age SEC maximum time a connection will stay open is SEC seconds (default is 300) -s, --stdin-stdout use stdin/stdout for communication (implies --no-daemon) -S, --strict-content-length always write Content-Length bytes in requests -V, --version output version information and exit -w, --no-daemon don't fork into the background -p, --pid-file LOCATION write a PID file to LOCATION Report bugs to bug-httptunnel@gnu.org. #
First some characteristics of the HTTPTunnel package.
- There is no configuration file, all arguments are options on the command line.
- The binary (daemon) name (hts) differs from the package name (httptunnel).
- The command line options allows to specify the PID file.
Based on the usage information we can select the following variables for inclusion in the web-interface:
-F <HOST>:<HOSTPORT>
-k <KEEPALIVE>
-M <MAXCONNECTIONAGE>
-d <DEVICE>
<CLIENTPORT>
httptunnel.cfg
Next we need to create the <package>.cfg file with the default values.
We always need the <PACKAGE>_ENABLED variable with default value 'no'.
For HOST I selected 'localhost', but I actually never used this package, so I'm not sure if this default value is good from a security point of view.
export HTTPTUNNEL_ENABLED='no' export HTTPTUNNEL_HOST='localhost' export HTTPTUNNEL_HOSTPORT='22' export HTTPTUNNEL_CLIENTPORT='443' export HTTPTUNNEL_KEEPALIVE='5' export HTTPTUNNEL_MAXCONNECTIONAGE='300' export HTTPTUNNEL_DEVICE=''
httptunnel.cgi
Now the <package>.cgi can be created.
The first part is Start Type and is enclosed with the sec_begin and sec_end keywords.
This part is uses the HTTPTUNNEL_ENABLED variable, and determines if the package should be started automatically at system startup.
Two input elements with radio buttons are declared within a paragraph.
On the actual web-page the first item is Status, displaying the current status of the package and a Start, Stop and Restart button. This part is probably generated by /usr/lib/libmodcgi.sh.
For each displayed text you see a lang statement and the text in both German and the English language. This lang statement is used during build on the build environment.
To be able to test your created <package>.cgi file directly on the router you can first create one without the lang statements, using just your preferred language.
After the web-interface behaves as required you can add the lang statements and the text in both languages.
See page <package>.cgi for more information on the lang statement.
The second part, enclosed with the sec_begin and sec_end keywords, is for configuring the selected parameters.
In this case a table is used with a table row (tr) for each parameter, and a column for to display the parameter name, and a column for entering the value in an input field.
A table has the advantage that the cells in the columns are automatically aligned.
In the first table data cell (td) the displays the parameter name in the correct language. The second table data cell (td) displays the current value using the Shell instruction html "$HTTPTUNNEL_<VALUE>" as value, in the input field of size characters length displayed, and a maximum of maxlength characters that can be entered.
The entered value is assigned to the input-field element name like name='<value>', which correspond to the parameter name <PACKAGE>_<VALUE>.
The input type is here always text.
After selecting the Apply button the entered values are assigned to the <PACKAGE>_<VALUE> parameters located in /mod/etc/conf/<package>.cfg.
httptunnel.cgi without lang statements:
#!/bin/sh . /usr/lib/libmodcgi.sh check "$HTTPTUNNEL_ENABLED" yes:auto "*":man sec_begin 'Start type' cat << EOF <p> <input id="e1" type="radio" name="enabled" value="yes"$auto_chk><label for="e1">Automatic</label> <input id="e2" type="radio" name="enabled" value="no"$man_chk><label for="e2">Manual</label> EOF cat << EOF </p> EOF sec_end sec_begin 'httptunnel' cat << EOF <table border="0"> <tr> <td>Destination Host:</td> <td><input type="text" name="host" size="60" maxlength="255" value="$(html "$HTTPTUNNEL_HOST")"></td> </tr> <tr> <td>Destination Port:</td> <td><input type="text" name="hostport" size="5" maxlength="5" value="$(html "$HTTPTUNNEL_HOSTPORT")"></td> </tr> <tr> <td>Client Port:</td> <td><input type="text" name="clientport" size="5" maxlength="5" value="$(html "$HTTPTUNNEL_CLIENTPORT")"></td> </tr> <tr> <td>Keep Alive:</td> <td><input type="text" name="keepalive" size="3" maxlength="3" value="$(html "$HTTPTUNNEL_KEEPALIVE")"></td> </tr> <tr> <td>Max Connection Age:</td> <td><input type="text" name="maxconnectionage" size="4" maxlength="4" value="$(html "$HTTPTUNNEL_MAXCONNECTIONAGE")"></td> </tr> <tr> <td>Device:</td> <td><input type="text" name="device" size="10" maxlength="10" value="$(html "$HTTPTUNNEL_DEVICE")"></td> </tr> </table> EOF sec_end
httptunnel.cgi with lang statements and an entry for each language:
#!/bin/sh . /usr/lib/libmodcgi.sh check "$HTTPTUNNEL_ENABLED" yes:auto "*":man sec_begin '$(lang de:"Starttyp" en:"Start type")' cat << EOF <p> <input id="e1" type="radio" name="enabled" value="yes"$auto_chk><label for="e1">$(lang de:"Automatisch" en:"Automatic")</label> <input id="e2" type="radio" name="enabled" value="no"$man_chk><label for="e2">$(lang de:"Manuell" en:"Manual")</label> EOF cat << EOF </p> EOF sec_end sec_begin '$(lang de:"httptunnel" en:"httptunnel")' cat << EOF <table border="0"> <tr> <td>$(lang de:"Destination Host" en:"Destination Host"):</td> <td><input type="text" name="host" size="80" maxlength="255" value="$(html "$HTTPTUNNEL_HOST")"></td> </tr> <tr> <td>$(lang de:"Destination Port" en:"Destination Port"):</td> <td><input type="text" name="hostport" size="5" maxlength="5" value="$(html "$HTTPTUNNEL_HOSTPORT")"></td> </tr> <tr> <td>$(lang de:"Client Port" en:"Client Port"):</td> <td><input type="text" name="clientport" size="5" maxlength="5" value="$(html "$HTTPTUNNEL_CLIENTPORT")"></td> </tr> <tr> <td>$(lang de:"Keep Alive" en:"Keep Alive"):</td> <td><input type="text" name="keepalive" size="3" maxlength="3" value="$(html "$HTTPTUNNEL_KEEPALIVE")"></td> </tr> <tr> <td>$(lang de:"Max Connection Age" en:"Max Connection Age"):</td> <td><input type="text" name="maxconnectionage" size="4" maxlength="4" value="$(html "$HTTPTUNNEL_MAXCONNECTIONAGE")"></td> </tr> <tr> <td>$(lang de:"Device" en:"Device"):</td> <td><input type="text" name="device" size="10" maxlength="10" value="$(html "$HTTPTUNNEL_DEVICE")"></td> </tr> </table> EOF sec_end
rc.httptunnel
Now we only need to write the rc.<package> file.
For this package the package name httptunnel and the binary hts differ. This requires the use of variable DAEMON for the package name, and DAEMON_BIN for the binary.
From the usage information we get that the binary gives an option to specify the PID-file. We will use this option in the rc.httptunnel file.
The binary is executed with the modlib_startdaemon function, which is using in the start () function. As parameter the DAEMON_BIN with its parameters is used.
For this package we have one conditional parameter. The DEVICE option should only be added to the list of parameters is it contains a non-zero amount of characters.
This is accomplished using a if [ test ] then function.
The case function test for a match. See the rc.<package> page for more information.
#!/bin/sh DAEMON=httptunnel DAEMON_BIN=hts PID_FILE=/var/run/$DAEMON_BIN.pid . /etc/init.d/modlibrc start() { OPTIONS="-F $HTTPTUNNEL_HOST:$HTTPTUNNEL_HOSTPORT \ -k $HTTPTUNNEL_KEEPALIVE \ -M $HTTPTUNNEL_MAXCONNECTIONAGE \ -p $PID_FILE \ $HTTPTUNNEL_CLIENTPORT" [ -n "$HTTPTUNNEL_DEVICE" ] && OPTIONS="$OPTIONS -d $HTTPTUNNEL_DEVICE" modlib_startdaemon $DAEMON_BIN $OPTIONS } case $1 in ""|load) modreg cgi 'httptunnel' 'httptunnel' modreg daemon httptunnel modlib_start $HTTPTUNNEL_ENABLED ;; unload) modunreg daemon httptunnel modunreg cgi 'httptunnel' modlib_stop ;; start) modlib_start ;; stop) modlib_stop ;; restart) modlib_restart ;; status) modlib_status ;; *) echo "Usage: $0 [load|unload|start|stop|restart|status]" 1>&2 exit 1 ;; esac exit 0
Test on router
The following scripts can help to test the created files directly on the router.
For this the files are located on a USB-stick.
If the web-interface is working you can add the parameter 2 to obtain the config parameter values from tffs.
For the initial development of all files:
#!/bin/sh export package=httptunnel echo Will add webinterface for $package [ ! -e /mod/etc/default.$package ] && mkdir /mod/etc/default.$package [ ! -e /mod/etc/default.$package/$package.cfg ] && cp $package.cfg /mod/etc/default.$package/ if [ $1 -eq 2 ]; then modconf load $package else [ ! -e /mod/etc/conf/$package.cfg ] && cp $package.cfg /mod/etc/conf/ fi cd /var/mod/usr/lib/cgi-bin/ [ ! -e /var/mod/usr/lib/cgi-bin/$package.cgi ] && ln -s /var/media/ftp/uStor01/freetz/webinterface/$package/$package.cgi $package.cgi cd /mod/etc/init.d/ [ ! -e /mod/etc/init.d/rc.$package ] && ln -s /var/media/ftp/uStor01/freetz/webinterface/$package/rc.$package rc.$package rm /var/mod/var/cache/menu/packages modreg cgi $package $package
For verifying changes to just the rc.<package> file e.g. after already including the files in the Freetz image:
#!/bin/sh export package=httptunnel cd /mod/etc/init.d/ [ -h /mod/etc/init.d/rc.$package ] && rm /mod/etc/init.d/rc.$package [ ! -e /mod/etc/init.d/rc.$package ] && ln -s /var/media/ftp/uStor01/freetz/webinterface/$package/rc.$package rc.$package
References
To help with Bash Shell scripts: