Hi,

On Sun, Aug 08, 2010 at 09:48:47PM +0200, Gert Doering wrote:
> as discussed in one of the previous the IRC meetings, I've been working
> on a test framework to enable full "fire up openvpn client, establish
> VPN connection, run ping tests, clean up, verify cleanup" automated 
> tests.

I got some feedback from Waldner on IRC, and had to make it work on
Solaris (broken /bin/sh) - so this is now built using "configure",
knows how to find "ip", "ifconfig" and "netstat" (configure does the
work :-) ), *and* has been tested on Solaris (works!).

The patch goes on top of the previous one.  Pushed to my git repo.

gert


From a91aef97487096595011a5d1716fe33fa654afe5 Mon Sep 17 00:00:00 2001
From: Gert Doering <g...@greenie.muc.de>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Tue, 10 Aug 2010 12:39:28 +0200
Subject: [PATCH] renamed t_client.sh to t_client.sh.in
 build t_client.sh by configure at run-time, with proper paths to
 ip/ifconfig/netstat binaries, and (most important) with proper #!SHELL

extend configure.ac to find "netstat" binary and to chmod +x "t_client.sh"

Signed-off-by: Gert Doering <g...@greenie.muc.de>
---
 configure.ac   |    8 ++
 t_client.sh    |  298 --------------------------------------------------------
 t_client.sh.in |  298 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 306 insertions(+), 298 deletions(-)
 delete mode 100755 t_client.sh
 create mode 100755 t_client.sh.in

diff --git a/configure.ac b/configure.ac
index 116ff7c..a495f14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,6 +267,13 @@ AC_ARG_WITH(route-path,
 )
 AC_DEFINE_UNQUOTED(ROUTE_PATH, "$ROUTE", [Path to route tool])
 
+AC_ARG_WITH(netstat-path,
+   [  --with-netstat-path=PATH  Path to netstat tool],
+   [NETSTAT="$withval"],
+   [AC_PATH_PROG([NETSTAT], [netstat], [netstat], 
[$PATH:/usr/local/sbin:/usr/sbin:/sbin:/etc])]
+)
+AC_DEFINE_UNQUOTED(NETSTAT_PATH, "$NETSTAT", [Path to netstat tool])
+
 AC_ARG_WITH(mem-check,
    [  --with-mem-check=TYPE  Build with debug memory checking, TYPE = dmalloc 
or valgrind],
    [MEMCHECK="$withval"]
@@ -911,6 +918,7 @@ if test -z "${htmldir}"; then
 fi
 # end workaround
 
+AC_CONFIG_FILES([t_client.sh], [chmod +x t_client.sh])
 AC_OUTPUT([
        Makefile
        openvpn.spec
diff --git a/t_client.sh b/t_client.sh
deleted file mode 100755
index 3a0dadb..0000000
--- a/t_client.sh
+++ /dev/null
@@ -1,298 +0,0 @@
-#!/bin/sh
-#
-# run OpenVPN client against ``test reference'' server
-# - check that ping, http, ... via tunnel works
-# - check that interface config / routes are properly cleaned after test end
-#
-# prerequisites:
-# - openvpn binary in current directory
-# - writable current directory to create subdir for logs
-# - t_client.rc in current directory OR source dir that specifies tests
-# - for "ping4" checks: fping binary in $PATH
-# - for "ping6" checks: fping6 binary in $PATH
-#
-
-if [ ! -x ./openvpn ]
-then
-    echo "no (executable) openvpn binary in current directory. FAIL." >&2
-    exit 1
-fi
-
-if [ ! -w . ]
-then
-    echo "current directory is not writable (required for logging). FAIL." >&2
-    exit 1
-fi
-
-if [ -r ./t_client.rc ] ; then
-    . ./t_client.rc
-elif [ -r "${srcdir}"/t_client.rc ] ; then
-    . "${srcdir}"/t_client.rc
-else
-    echo "cannot find 't_client.rc' in current directory or" >&2
-    echo "source dir ('${srcdir}').  FAIL." >&2
-    exit 1
-fi
-
-if [ -z "$CA_CERT" ] ; then
-    echo "CA_CERT not defined in 't_client.rc'. SKIP test." >&2
-    exit 0
-fi
-
-if [ -z "$TEST_RUN_LIST" ] ; then
-    echo "TEST_RUN_LIST empty, no tests defined.  SKIP test." >&2
-    exit 0
-fi
-
-# make sure we have permissions to run ifconfig/route from OpenVPN
-# can't use "id -u" here - doesn't work on Solaris
-ID=`id`
-if expr "$ID" : "uid=0" >/dev/null
-then :
-else
-    echo "$0: this test must run be as root. SKIP." >&2
-    exit 0
-fi
-
-LOGDIR=t_client-`hostname`-`date +%Y%m%d-%H%M%S`
-if mkdir $LOGDIR
-then :
-else
-    echo "can't create log directory '$LOGDIR'. FAIL." >&2
-    exit 1
-fi
-
-exit_code=0
-
-# ----------------------------------------------------------
-# helper functions
-# ----------------------------------------------------------
-# print failure message, increase FAIL counter
-fail()
-{
-    echo ""
-    echo "FAIL: $@" >&2
-    fail_count=$(( $fail_count + 1 ))
-}
-
-# print "all interface IP addresses" + "all routes"
-# this is higly system dependent...
-get_ifconfig_route()
-{
-    # linux / iproute2?
-    if [ -x /sbin/ip -o -x /usr/sbin/ip ]
-    then
-       echo "-- linux iproute2 --"
-       ip addr show     | grep -v valid_lft
-       ip route show
-       ip -6 route show | sed -e 's/expires [0-9]*sec //'
-       return
-    fi
-
-    # try uname
-    case `uname -s` in
-       Linux)
-          echo "-- linux / ifconfig --"
-          LANG=C ifconfig -a |egrep  "( addr:|encap:)"
-          LANG=C netstat -rn -4 -6
-          return
-          ;;
-       FreeBSD|NetBSD|Darwin)
-          echo "-- FreeBSD/NetBSD/Darwin [MacOS X] --"
-          ifconfig -a | egrep "(flags=|inet)"
-          netstat -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
-          return
-          ;;
-       OpenBSD)
-          echo "-- OpenBSD --"
-          ifconfig -a | egrep "(flags=|inet)" | \
-               sed -e 's/pltime [0-9]*//' -e 's/vltime [0-9]*//'
-          netstat -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
-          return
-          ;;
-       SunOS)
-          echo "-- Solaris --"
-          ifconfig -a | egrep "(flags=|inet)"
-          netstat -rn
-          return
-          ;;
-    esac
-
-    echo "get_ifconfig_route(): no idea how to get info on your OS.  FAIL." >&2
-    exit 20
-}
-
-# ----------------------------------------------------------
-# check ifconfig
-#  arg1: "4" or "6" -> for message
-#  arg2: IPv4/IPv6 address that must show up in out of "get_ifconfig_route"
-check_ifconfig()
-{
-    proto=$1 ; shift
-    expect_list="$@"
-
-    if [ -z "$expect_list" ] ; then return ; fi
-
-    for expect in $expect_list
-    do
-       if get_ifconfig_route | fgrep "$expect" >/dev/null
-       then :
-       else
-           fail "check_ifconfig(): expected IPv$proto address '$expect' not 
found in ifconfig output."
-       fi
-    done
-}
-
-# ----------------------------------------------------------
-# run pings
-#  arg1: "4" or "6" -> fping/fing6
-#  arg2: "want_ok" or "want_fail" (expected ping result)
-#  arg3... -> fping arguments (host list)
-run_ping_tests()
-{
-    proto=$1 ; want=$2 ; shift ; shift
-    targetlist="$@"
-
-    # "no targets" is fine
-    if [ -z "$targetlist" ] ; then return ; fi
-
-    case $proto in
-       4) cmd=fping ;;
-       6) cmd=fping6 ;;
-       *) echo "internal error in run_ping_tests arg 1: '$proto'" >&2
-          exit 1 ;;
-    esac
-
-    case $want in
-       want_ok)   sizes_list="64 1440 3000" ;;
-       want_fail) sizes_list="64" ;;
-    esac
-
-    for bytes in $sizes_list
-    do
-       echo "run IPv$proto ping tests ($want), $bytes byte packets..."
-
-       echo "$cmd -b $bytes -C 20 -p 250 -q $targetlist" 
>>$LOGDIR/$SUF:fping.out
-       $cmd -b $bytes -C 20 -p 250 -q $targetlist >>$LOGDIR/$SUF:fping.out 2>&1
-
-       # while OpenVPN is running, pings must succeed (want='want_ok')
-       # before OpenVPN is up, pings must NOT succeed (want='want_fail')
-
-       rc=$?
-       if [ $rc = 0 ]                          # all ping OK
-       then
-           if [ $want = "want_fail" ]          # not what we want
-           then
-               fail "IPv$proto ping test succeeded, but needs to *fail*."
-           fi
-       else                                    # ping failed
-           if [ $want = "want_ok" ]            # not what we wanted
-           then
-               fail "IPv$proto ping test ($bytes bytes) failed, but should 
succeed."
-           fi
-       fi
-    done
-}
-
-# ----------------------------------------------------------
-# main test loop
-# ----------------------------------------------------------
-for SUF in $TEST_RUN_LIST
-do
-    echo -e "\n### test run $SUF ###\n"
-    fail_count=0
-
-    echo "save pre-openvpn ifconfig + route"
-    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_pre.txt
-
-    # get config variables
-    eval openvpn_conf=\"\$OPENVPN_CONF_$SUF\"
-    eval expect_ifconfig4=\"\$EXPECT_IFCONFIG4_$SUF\"
-    eval expect_ifconfig6=\"\$EXPECT_IFCONFIG6_$SUF\"
-    eval ping4_hosts=\"\$PING4_HOSTS_$SUF\"
-    eval ping6_hosts=\"\$PING6_HOSTS_$SUF\"
-
-    echo -e "\nrun pre-openvpn ping tests - targets must not be reachable..."
-    run_ping_tests 4 want_fail "$ping4_hosts"
-    run_ping_tests 6 want_fail "$ping6_hosts"
-    if [ "$fail_count" = 0 ] ; then
-        echo -e "OK.\n"
-    else
-       echo -e "FAIL: make sure that ping hosts are ONLY reachable via VPN, 
SKIP test $SUF".
-       exit_code=31
-       continue
-    fi
-
-    echo " run ./openvpn $openvpn_conf"
-    ./openvpn $openvpn_conf >$LOGDIR/$SUF:openvpn.log &
-    opid=$!
-
-    # make sure openvpn client is terminated in case shell exits
-    trap "kill $opid" 0
-    trap "kill $opid ; trap - 0 ; exit 1" 1 2 3 15
-
-    echo "wait for connection to establish..."
-    sleep 10
-
-    # test whether OpenVPN process is still there
-    if kill -0 $opid
-    then :
-    else
-       echo -e "OpenVPN process has failed to start up, check log 
($LOGDIR/$SUF:openvpn.log).  FAIL.\ntail of logfile follows:\n..." >&2
-       tail $LOGDIR/$SUF:openvpn.log >&2
-       trap - 0 1 2 3 15
-       exit 10
-    fi
-
-    # compare whether anything changed in ifconfig/route setup?
-    echo "save ifconfig+route"
-    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route.txt
-
-    echo -n "compare pre-openvpn ifconfig+route with current values..."
-    if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
-           $LOGDIR/$SUF:ifconfig_route.txt >/dev/null
-    then
-       fail "no differences between ifconfig/route before OpenVPN start and 
now."
-    else
-       echo -e " OK!\n"
-    fi
-
-    # expected ifconfig values in there?
-    check_ifconfig 4 "$expect_ifconfig4"
-    check_ifconfig 6 "$expect_ifconfig6"
-
-    run_ping_tests 4 want_ok "$ping4_hosts"
-    run_ping_tests 6 want_ok "$ping6_hosts"
-    echo -e "ping tests done.\n"
-
-    echo "stopping OpenVPN"
-    kill $opid
-    wait $!
-    rc=$?
-    if [ $rc != 0 ] ; then
-       fail "OpenVPN return code $rc, expect 0"
-    fi
-
-    echo -e "\nsave post-openvpn ifconfig + route..."
-    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_post.txt
-
-    echo -n "compare pre- and post-openvpn ifconfig + route..."
-    if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
-           $LOGDIR/$SUF:ifconfig_route_post.txt 
>$LOGDIR/$SUF:ifconfig_route_diff.txt
-    then
-       echo -e " OK.\n"
-    else
-       cat $LOGDIR/$SUF:ifconfig_route_diff.txt >&2
-       fail "differences between pre- and post-ifconfig/route"
-    fi
-    if [ "$fail_count" = 0 ] ; then
-        echo -e "test run $SUF: all tests OK.\n"
-    else
-       echo -e "test run $SUF: $fail_count test failures. FAIL.\n";
-       exit_code=30
-    fi
-done
-
-# remove trap handler
-trap - 0 1 2 3 15
-exit $exit_code
diff --git a/t_client.sh.in b/t_client.sh.in
new file mode 100755
index 0000000..664b2fd
--- /dev/null
+++ b/t_client.sh.in
@@ -0,0 +1,298 @@
+#!@SHELL@
+#
+# run OpenVPN client against ``test reference'' server
+# - check that ping, http, ... via tunnel works
+# - check that interface config / routes are properly cleaned after test end
+#
+# prerequisites:
+# - openvpn binary in current directory
+# - writable current directory to create subdir for logs
+# - t_client.rc in current directory OR source dir that specifies tests
+# - for "ping4" checks: fping binary in $PATH
+# - for "ping6" checks: fping6 binary in $PATH
+#
+
+if [ ! -x ./openvpn ]
+then
+    echo "no (executable) openvpn binary in current directory. FAIL." >&2
+    exit 1
+fi
+
+if [ ! -w . ]
+then
+    echo "current directory is not writable (required for logging). FAIL." >&2
+    exit 1
+fi
+
+if [ -r ./t_client.rc ] ; then
+    . ./t_client.rc
+elif [ -r "${srcdir}"/t_client.rc ] ; then
+    . "${srcdir}"/t_client.rc
+else
+    echo "cannot find 't_client.rc' in current directory or" >&2
+    echo "source dir ('${srcdir}').  FAIL." >&2
+    exit 1
+fi
+
+if [ -z "$CA_CERT" ] ; then
+    echo "CA_CERT not defined in 't_client.rc'. SKIP test." >&2
+    exit 0
+fi
+
+if [ -z "$TEST_RUN_LIST" ] ; then
+    echo "TEST_RUN_LIST empty, no tests defined.  SKIP test." >&2
+    exit 0
+fi
+
+# make sure we have permissions to run ifconfig/route from OpenVPN
+# can't use "id -u" here - doesn't work on Solaris
+ID=`id`
+if expr "$ID" : "uid=0" >/dev/null
+then :
+else
+    echo "$0: this test must run be as root. SKIP." >&2
+    exit 0
+fi
+
+LOGDIR=t_client-`hostname`-`date +%Y%m%d-%H%M%S`
+if mkdir $LOGDIR
+then :
+else
+    echo "can't create log directory '$LOGDIR'. FAIL." >&2
+    exit 1
+fi
+
+exit_code=0
+
+# ----------------------------------------------------------
+# helper functions
+# ----------------------------------------------------------
+# print failure message, increase FAIL counter
+fail()
+{
+    echo ""
+    echo "FAIL: $@" >&2
+    fail_count=$(( $fail_count + 1 ))
+}
+
+# print "all interface IP addresses" + "all routes"
+# this is higly system dependent...
+get_ifconfig_route()
+{
+    # linux / iproute2? (-> if configure got a path)
+    if [ "@IPROUTE@" != "ip" ]
+    then
+       echo "-- linux iproute2 --"
+       @IPROUTE@ addr show     | grep -v valid_lft
+       @IPROUTE@ route show
+       @IPROUTE@ -6 route show | sed -e 's/expires [0-9]*sec //'
+       return
+    fi
+
+    # try uname
+    case `uname -s` in
+       Linux)
+          echo "-- linux / ifconfig --"
+          LANG=C @IFCONFIG@ -a |egrep  "( addr:|encap:)"
+          LANG=C @NETSTAT@ -rn -4 -6
+          return
+          ;;
+       FreeBSD|NetBSD|Darwin)
+          echo "-- FreeBSD/NetBSD/Darwin [MacOS X] --"
+          @IFCONFIG@ -a | egrep "(flags=|inet)"
+          @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
+          return
+          ;;
+       OpenBSD)
+          echo "-- OpenBSD --"
+          @IFCONFIG@ -a | egrep "(flags=|inet)" | \
+               sed -e 's/pltime [0-9]*//' -e 's/vltime [0-9]*//'
+          @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
+          return
+          ;;
+       SunOS)
+          echo "-- Solaris --"
+          @IFCONFIG@ -a | egrep "(flags=|inet)"
+          @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }'
+          return
+          ;;
+    esac
+
+    echo "get_ifconfig_route(): no idea how to get info on your OS.  FAIL." >&2
+    exit 20
+}
+
+# ----------------------------------------------------------
+# check ifconfig
+#  arg1: "4" or "6" -> for message
+#  arg2: IPv4/IPv6 address that must show up in out of "get_ifconfig_route"
+check_ifconfig()
+{
+    proto=$1 ; shift
+    expect_list="$@"
+
+    if [ -z "$expect_list" ] ; then return ; fi
+
+    for expect in $expect_list
+    do
+       if get_ifconfig_route | fgrep "$expect" >/dev/null
+       then :
+       else
+           fail "check_ifconfig(): expected IPv$proto address '$expect' not 
found in ifconfig output."
+       fi
+    done
+}
+
+# ----------------------------------------------------------
+# run pings
+#  arg1: "4" or "6" -> fping/fing6
+#  arg2: "want_ok" or "want_fail" (expected ping result)
+#  arg3... -> fping arguments (host list)
+run_ping_tests()
+{
+    proto=$1 ; want=$2 ; shift ; shift
+    targetlist="$@"
+
+    # "no targets" is fine
+    if [ -z "$targetlist" ] ; then return ; fi
+
+    case $proto in
+       4) cmd=fping ;;
+       6) cmd=fping6 ;;
+       *) echo "internal error in run_ping_tests arg 1: '$proto'" >&2
+          exit 1 ;;
+    esac
+
+    case $want in
+       want_ok)   sizes_list="64 1440 3000" ;;
+       want_fail) sizes_list="64" ;;
+    esac
+
+    for bytes in $sizes_list
+    do
+       echo "run IPv$proto ping tests ($want), $bytes byte packets..."
+
+       echo "$cmd -b $bytes -C 20 -p 250 -q $targetlist" 
>>$LOGDIR/$SUF:fping.out
+       $cmd -b $bytes -C 20 -p 250 -q $targetlist >>$LOGDIR/$SUF:fping.out 2>&1
+
+       # while OpenVPN is running, pings must succeed (want='want_ok')
+       # before OpenVPN is up, pings must NOT succeed (want='want_fail')
+
+       rc=$?
+       if [ $rc = 0 ]                          # all ping OK
+       then
+           if [ $want = "want_fail" ]          # not what we want
+           then
+               fail "IPv$proto ping test succeeded, but needs to *fail*."
+           fi
+       else                                    # ping failed
+           if [ $want = "want_ok" ]            # not what we wanted
+           then
+               fail "IPv$proto ping test ($bytes bytes) failed, but should 
succeed."
+           fi
+       fi
+    done
+}
+
+# ----------------------------------------------------------
+# main test loop
+# ----------------------------------------------------------
+for SUF in $TEST_RUN_LIST
+do
+    echo -e "\n### test run $SUF ###\n"
+    fail_count=0
+
+    echo "save pre-openvpn ifconfig + route"
+    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_pre.txt
+
+    # get config variables
+    eval openvpn_conf=\"\$OPENVPN_CONF_$SUF\"
+    eval expect_ifconfig4=\"\$EXPECT_IFCONFIG4_$SUF\"
+    eval expect_ifconfig6=\"\$EXPECT_IFCONFIG6_$SUF\"
+    eval ping4_hosts=\"\$PING4_HOSTS_$SUF\"
+    eval ping6_hosts=\"\$PING6_HOSTS_$SUF\"
+
+    echo -e "\nrun pre-openvpn ping tests - targets must not be reachable..."
+    run_ping_tests 4 want_fail "$ping4_hosts"
+    run_ping_tests 6 want_fail "$ping6_hosts"
+    if [ "$fail_count" = 0 ] ; then
+        echo -e "OK.\n"
+    else
+       echo -e "FAIL: make sure that ping hosts are ONLY reachable via VPN, 
SKIP test $SUF".
+       exit_code=31
+       continue
+    fi
+
+    echo " run ./openvpn $openvpn_conf"
+    ./openvpn $openvpn_conf >$LOGDIR/$SUF:openvpn.log &
+    opid=$!
+
+    # make sure openvpn client is terminated in case shell exits
+    trap "kill $opid" 0
+    trap "kill $opid ; trap - 0 ; exit 1" 1 2 3 15
+
+    echo "wait for connection to establish..."
+    sleep 10
+
+    # test whether OpenVPN process is still there
+    if kill -0 $opid
+    then :
+    else
+       echo -e "OpenVPN process has failed to start up, check log 
($LOGDIR/$SUF:openvpn.log).  FAIL.\ntail of logfile follows:\n..." >&2
+       tail $LOGDIR/$SUF:openvpn.log >&2
+       trap - 0 1 2 3 15
+       exit 10
+    fi
+
+    # compare whether anything changed in ifconfig/route setup?
+    echo "save ifconfig+route"
+    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route.txt
+
+    echo -n "compare pre-openvpn ifconfig+route with current values..."
+    if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
+           $LOGDIR/$SUF:ifconfig_route.txt >/dev/null
+    then
+       fail "no differences between ifconfig/route before OpenVPN start and 
now."
+    else
+       echo -e " OK!\n"
+    fi
+
+    # expected ifconfig values in there?
+    check_ifconfig 4 "$expect_ifconfig4"
+    check_ifconfig 6 "$expect_ifconfig6"
+
+    run_ping_tests 4 want_ok "$ping4_hosts"
+    run_ping_tests 6 want_ok "$ping6_hosts"
+    echo -e "ping tests done.\n"
+
+    echo "stopping OpenVPN"
+    kill $opid
+    wait $!
+    rc=$?
+    if [ $rc != 0 ] ; then
+       fail "OpenVPN return code $rc, expect 0"
+    fi
+
+    echo -e "\nsave post-openvpn ifconfig + route..."
+    get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_post.txt
+
+    echo -n "compare pre- and post-openvpn ifconfig + route..."
+    if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
+           $LOGDIR/$SUF:ifconfig_route_post.txt 
>$LOGDIR/$SUF:ifconfig_route_diff.txt
+    then
+       echo -e " OK.\n"
+    else
+       cat $LOGDIR/$SUF:ifconfig_route_diff.txt >&2
+       fail "differences between pre- and post-ifconfig/route"
+    fi
+    if [ "$fail_count" = 0 ] ; then
+        echo -e "test run $SUF: all tests OK.\n"
+    else
+       echo -e "test run $SUF: $fail_count test failures. FAIL.\n";
+       exit_code=30
+    fi
+done
+
+# remove trap handler
+trap - 0 1 2 3 15
+exit $exit_code
-- 
1.6.4.4

-- 
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             g...@greenie.muc.de
fax: +49-89-35655025                        g...@net.informatik.tu-muenchen.de

Attachment: pgpjo_K4oHHK3.pgp
Description: PGP signature

Reply via email to