local test ok
authorMazet Laurent <laurent.mazet@thalesgroup.com>
Wed, 11 Jun 2025 14:33:48 +0000 (16:33 +0200)
committerMazet Laurent <laurent.mazet@thalesgroup.com>
Wed, 11 Jun 2025 14:33:48 +0000 (16:33 +0200)
clear_data.eth
test.sh
ulvpn.c

index 5767e34a8a30ea568bbad5e0e6e1845af1c9e4ff..07a8c04f917e3c1a1487e87f7063baf7bc703ad8 100644 (file)
@@ -1 +1 @@
-T0829 MSG=0 DATA=00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:45:00:00:2f:91:d7:40:00:40:11:93:e1:0a:02:00:01:0a:02:01:01:8e:bb:0b:b8:00:1b:53:3b:54:68:69:73:20:69:73:20:61:20:6c:6f:6e:67:20:54:45:53:0a:01
+T0829 MSG=3 DATA=00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:45:00:00:3b:28:23:40:00:40:11:fd:89:0a:02:01:01:0a:02:00:01:ba:25:0b:b8:00:27:b9:c9:54:45:53:54:3a:20:54:68:69:73:20:69:73:20:61:20:76:65:72:79:20:6c:6f:6e:67:20:74:65:78:74:0a:00:00:00:00:05
diff --git a/test.sh b/test.sh
index 9fa3526cc56b41bc64e79ff98c0c2f94e1b1072b..a77c5fc9a95bbe395b90be04d59ae3398dc2a2fa 100755 (executable)
--- a/test.sh
+++ b/test.sh
@@ -1,63 +1,95 @@
-#!/bin/sh
+#!/bin/bash
 
+MODE="tx rx"
 MTU=1440
-VPN=./ulvpn.exe
-MOREP=/home/mazet/code/morep/morep_valid.exe
+#VPN=./ulvpn.exe
+MOREP=$(dirname $0)/../morep/morep_valid.exe
 
+MSG="TEST: This is a very long text"
+
+function mydata() { cat $1 | sed 's/.*=//'; }
+function title () { echo -e "\033[0;1m$*\033[0;0m"; }
+function pass () { echo -e "\033[1;32m$*\033[0;0m"; }
+function warn () { echo -e "\033[1;33m$*\033[0;0m"; test; }
+function fail () { echo -e "\033[1;31m$*\033[0;0m"; test; }
 ip addr list | grep 10\.1\.0\. || { ip link add eth0 type dummy && ip addr add dev eth0 10.1.0.1/24; }
 DEV=lo
 
 rm -f in.log out.log
 
-{ 
-    while true; do
-        echo "SLEEP 100\nR0839 MSG=0" | \
-            $MOREP -v 4 \
+pids=
+{
+if [[ "$MODE" =~ tx ]]; then
+    stop=
+    while [ "x$stop" = "x" ]; do
+        echo -e "SLEEP 100\nR0839 MSG=0" | \
+            $MOREP -v 2 \
                    -r $DEV://00:00:00:00:00:00/0839 \
                    -t $DEV://00:00:00:00:00:00/0829 \
                    -l out.log | \
             awk '{print "CM R->B [rx]:", $0}';
-            grep 54:45:53:54 out.log && break
+        grep -q 54:45:53:54 out.log && stop=1
     done;
 
-    $MOREP -v 4 \
+    $MOREP -v 2 \
        -r $DEV://00:00:00:00:00:00/0819 \
        -t $DEV://00:00:00:00:00:00/0809 \
        encrypted_data.eth | \
        awk '{print "CM R->B [tx]:", $0}';
+fi
+} &
+pids="$pids $!"
 
-    while true; do
-        echo "SLEEP 100\nR0819 MSG=2" | \
-            $MOREP -v 4 \
+{
+if [[ "$MODE" =~ rx ]]; then
+    stop=
+    while [ "x$stop" = "x" ]; do
+        echo -e "SLEEP 100\nR0819 MSG=2" | \
+            $MOREP -v 2 \
                    -r $DEV://00:00:00:00:00:00/0819 \
                    -t $DEV://00:00:00:00:00:00/0809 \
                    -l in.log | \
             awk '{print "CM B->R [rx]:", $0}';
-            grep 54:45:53:54 in.log && break
+        grep -q 54:45:53:54 in.log && stop=1
     done;
 
-    $MOREP -v 4 \
+    $MOREP -v 2 \
        -r $DEV://00:00:00:00:00:00/0839 \
        -t $DEV://00:00:00:00:00:00/0829 \
        clear_data.eth | \
        awk '{print "CM B->R [tx]:", $0}';
+fi
 } &
-pid=$!
-trap "kill -9 $pid; ip addr del dev eth0 10.1.0.1/24 && ip link del eth0 type dummy || echo no need to remove eth0;" 0 1 2 15
+pids="$pids $!"
+
+{ sleep 1; echo $MSG | nc -uq0 10.2.1.1 3000; nc -luq0 3000 > text.log; } &
+pids="$pids $!"
 
-{ sleep 1; echo "TEST: This is a very long text" | nc -uq0 10.2.1.1 3000; } &
+#trap "for p in $pids; do kill -9 $p; done; ip addr del dev eth0 10.1.0.1/24 && ip link del eth0 type dummy || echo no need to remove eth0;" 0 1 2 15
 
-#gdb $VPN --args $VPN \
-$VPN \
+$@ \
   -v 5 -V 4 \
   -d tun://tun0:$MTU \
   -l tun://10.2.0.1 -r tun://10.2.1.0 \
   -t udp://10.1.0.1:1234 -u udp://10.1.0.1:1234 \
   -x $DEV://00:00:00:00:00:00/0809 $DEV://00:00:00:00:00:00/0819 \
-  -y $DEV://00:00:00:00:00:00/0829 $DEV://00:00:00:00:00:00/0839
+  -y $DEV://00:00:00:00:00:00/0829 $DEV://00:00:00:00:00:00/0839 &
+pids="$pids $!"
 
-kill -9 $pid
+sleep 4
+
+for p in $pids; do
+    kill -TERM $p 2>/dev/null
+done
 ip addr del dev eth0 10.1.0.1/24 && ip link del eth0 type dummy || echo no need to remove eth0
 
-diff out.log clear_data.eth && echo clear data ok
-diff in.log encrypted_data.eth && echo encrypted data ok
+rc=
+[[ "$MODE" =~ rx ]] && [ "$(mydata in.log)" = "$(mydata encrypted_data.eth)" ] && pass "encrypted data ok" || fail "encrypted data ko"
+rc="$rc$?"
+[[ "$MODE" =~ tx ]] && [ "$(mydata out.log|hd|tail -8)" = "$(mydata clear_data.eth|hd|tail -8)" ] && pass "clear data ok" || fail "clear data ko"
+rc="$rc$?"
+[ -f text.log ] && { echo $MSG | diff text.log - && pass "message ok" || fail "message ko"; }
+rc="$rc$?"
+
+test "$rc" = "000"
diff --git a/ulvpn.c b/ulvpn.c
index 1655e6b2788861aff70efc310dd305c0e5dc6142..efb1e5ad28e4a91b4ea319d61431896afe145bae 100644 (file)
--- a/ulvpn.c
+++ b/ulvpn.c
@@ -48,20 +48,14 @@ int seqcheck = 0;
 int timeout = 900; /* ms */
 int stop = 0;
 
+uint8_t aad[4] = { 0, 0, 0, 0 };
+
 #define BUFMAX 4096
 
 #define MAXPAYLOAD 1500
 
 DECLARE_VERBOSE_LEVEL (ulvpn, INFO);
 
-typedef struct {
-    uint8_t aad[4];
-    int rxred;
-    int rxblack;
-    int txred;
-    int txblack;
-} cm_t;
-
 void sig_handler (int sig)
 {
     switch (sig) {
@@ -90,14 +84,14 @@ void usage (void)
     printf ("%s version %s\n", progname, version);
 }
 
-int encrypt (uint8_t *buffer, int len, cm_t *cm)
+int pack_clear_data (uint8_t *buffer, int len, int maxlen)
 {
 
     /* create clear  message */
     CLEAR_DATA_t msg = {0};
     msg.channel_id = 0;
     msg.bypass_len = 0;
-    memcpy (msg.aad + sizeof (msg.aad) - sizeof (cm->aad), cm->aad, sizeof (cm->aad));
+    memcpy (msg.aad + sizeof (msg.aad) - sizeof (aad), aad, sizeof (aad));
     int npad =  16 - (len % 16);
     if (len + npad > (int)sizeof (msg.data)) {
         VERBOSE (ulvpn, WARNING, PRINTF ("too long payload (%d)\n", len));
@@ -107,124 +101,113 @@ int encrypt (uint8_t *buffer, int len, cm_t *cm)
     VERBOSE (ulvpn, DEBUG, PRINTF ("padding %d byte%s\n", npad, (npad > 1) ? "s" : ""));
     memcpy (msg.data, buffer, len);
     msg.data[len + npad - 1] = npad;
-    //memset (buffer, 0, len);
+    memset (buffer, 0, len);
     msg.data_len = len + npad;
 
     /* serialize message and send it */
-    uint8_t out[MAXPAYLOAD] = {0};
-    int out_len = serial_clear_data (&msg, out, sizeof (out));
-    if (out_len < 0) {
+    len = serial_clear_data (&msg, buffer, maxlen);
+    if (len < 0) {
         VERBOSE (ulvpn, WARNING, PRINTF ("error when serializing clear message\n"));
         return 0;
     }
-    int seqtx = MOREP_Send (cm->txred, 0x00, out, out_len);
-    VERBOSE (ulvpn, DEBUG, PRINTF ("send %d bytes to MOREP CM red\n", out_len));
 
-    /* get encrypted message and check it */
-    uint8_t in[MAXPAYLOAD] = {0};
-    uint8_t msgtype = 0;
-    int in_len = 0;
-    int seqrx = MOREP_Receive_timeout (cm->rxblack, &msgtype, in, &in_len, timeout);
-    VERBOSE (ulvpn, DEBUG, PRINTF ("received msg %d, seq %d/%d, length %d/%d bytes from MOREP CM black\n", msgtype, seqtx, seqrx, out_len, in_len));
-    if ((msgtype != 0x01) || (in_len != out_len + 12 + 16) || ((seqcheck) && (seqtx != seqrx))) {
-        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent encrypted message\n"));
-        return 0;
+    return len;
+}
+
+#define CHECK_AND_STORE(size, statement)     \
+    if ((!error) && (len + size < maxlen)) { \
+        statement;                           \
+        len += size;                         \
+    } else {                                 \
+        error = 1;                           \
     }
+
+int depack_encrypted_data (uint8_t *buffer, int len, int maxlen)
+{
+
+    /* get encrypted message and check it */
     ENCRYPTED_DATA_t enc = {0};
-    if (!deserial_encrypted_data (in, in_len, &enc)) {
+    if (deserial_encrypted_data (buffer, len, &enc)) {
         VERBOSE (ulvpn, WARNING, PRINTF ("error when deserializing encrypted message\n"));
         return 0;
     }
+    memset (buffer, 0, len);
 
     /* build output message */
     len = 0;
-    //buf[len++] = enc.channel_id;
-    //check msg.bypass_len
-    memcpy (buffer + len, cm->aad, sizeof (cm->aad));
-    len += sizeof (cm->aad);
-    memcpy (buffer + len, enc.iv, sizeof (enc.iv));
-    len += sizeof (enc.iv);
-    memcpy (buffer + len, enc.data, enc.data_len);
-    len += enc.data_len;
-
-    return len;
+    int error = 0;
+    //CHECK_AND_STORE (1, buf[len] = enc.channel_id);
+    //if ((!error) && (msg.bypass_len != 0)) { error = 1; }
+    CHECK_AND_STORE ((int)sizeof (aad), memcpy (buffer + len, enc.aad + sizeof (enc.aad) - sizeof (aad), sizeof (aad)));
+    CHECK_AND_STORE ((int)sizeof (enc.iv), memcpy (buffer + len, enc.iv, sizeof (enc.iv)));
+    CHECK_AND_STORE (enc.data_len, memcpy (buffer + len, enc.data, enc.data_len));
+
+    return (error) ? -1 : len;
 }
 
-int decrypt (uint8_t *buffer, int len, cm_t *cm)
+#define CHECK_AND_PACK(size, statement)       \
+    if ((!error) && (offset + size <= len)) { \
+        statement;                            \
+        offset += size;                       \
+    } else {                                  \
+        error = 1;                            \
+    }
+
+int pack_encrypted_data (uint8_t *buffer, int len, int maxlen)
 {
 
     /* create encrypted  message */
     ENCRYPTED_DATA_t enc = {0};
-    int i = 0;
-    //if (i + 1 > len) {
-    //    VERBOSE (ulvpn, WARNING, PRINTF ("no channel id\n");
-    //    return 0;
-    //}
-    //enc.channel_id = buffer[i++];
+    int offset = 0;
+    int error = 0;
+    //CHECK_AND_PACK (1, enc.channel_id = buffer[offset]);
     enc.bypass_len = 0;
-    if (i + (int)sizeof (cm->aad) > len) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted aad\n"));
-        return 0;
-    }
-    memcpy (enc.aad + sizeof (enc.aad) - sizeof (cm->aad), buffer + i, sizeof (cm->aad));
-    i += sizeof (cm->aad);
-    if (i + (int)sizeof (enc.iv) > len) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted iv\n"));
-        return 0;
-    }
-    memcpy (enc.iv, buffer + i, sizeof (enc.iv));
-    i += sizeof (enc.iv);
-    if (len - i < 32) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted tag\n"));
-        return 0;
-    }
-    if ((len - i) % 16 != 0) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted encrypted message\n"));
-        return 0;
+    CHECK_AND_PACK ((int)sizeof (aad), memcpy (enc.aad + sizeof (enc.aad) - sizeof (aad), buffer + offset, sizeof (aad)));
+    CHECK_AND_PACK ((int)sizeof (enc.iv), memcpy (enc.iv, buffer + offset, sizeof (enc.iv)));
+    if ((!error) && ((len - offset >= 32) && ((len - offset) % 16 == 0))) {
+        memcpy (enc.data, buffer + offset, len - offset);
+        enc.data_len = len - offset;
+    } else {
+        return -1;
     }
-    memcpy (enc.data, buffer + i, len - i);
-    enc.data_len = len - i;
+    memset (buffer, 0, len);
 
     /* serialize message and send it */
-    uint8_t out[MAXPAYLOAD] = {0};
-    int out_len = serial_encrypted_data (&enc, out, sizeof (out));
-    if (out_len < 0) {
+    len = serial_encrypted_data (&enc, buffer, maxlen);
+    if (len < 0) {
         VERBOSE (ulvpn, WARNING, PRINTF ("error when serializing encrypted message\n"));
         return 0;
     }
-    int seqtx = MOREP_Send (cm->txblack, 0x02, out, out_len);
-    VERBOSE (ulvpn, DEBUG, PRINTF ("send %d bytes to MOREP CM black\n", out_len));
+
+    return len;
+}
+
+int depack_clear_data (uint8_t *buffer, int len, int maxlen)
+{
 
     /* get clear message and check it */
-    uint8_t in[MAXPAYLOAD] = {0};
-    uint8_t msgtype = 0;
-    int in_len = 0;
-    int seqrx = MOREP_Receive_timeout (cm->rxred, &msgtype, in, &in_len, timeout);
-    VERBOSE (ulvpn, DEBUG, PRINTF ("received msg %d, seq %d/%d, length %d/%d bytes from MOREP CM black\n", msgtype, seqtx, seqrx, out_len, in_len));
-    VERBOSE (ulvpn, DEBUG, PRINTF ("received %d bytes from MOREP CM red\n", in_len));
-    if ((msgtype != 0x03) || (in_len != out_len - 12 - 16) || ((seqcheck) && (seqtx != seqrx))) {
-        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent decrypted message\n"));
-        return 0;
-    }
     CLEAR_DATA_t msg = {0};
-    if (!deserial_clear_data (in, in_len, &msg)) {
+    if (deserial_clear_data (buffer, len, &msg)) {
         VERBOSE (ulvpn, WARNING, PRINTF ("error when deserializing decrypted message\n"));
         return 0;
     }
+    memset (buffer, 0, len);
 
     /* build output message */
     len = 0;
-    //buf[len++] = enc.channel_id;
-    //check msg.bypass_len
-    int npad = in[in_len - 1];
-    if ((npad > 16) || (msg.data_len < npad)) {
-        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent padding (%d)\n", npad));
-        return 0;
+    int error = 0;
+    CHECK_AND_STORE (msg.data_len, memcpy (buffer + len, msg.data, msg.data_len));
+    if (!error) {
+        int npad = msg.data[msg.data_len - 1];
+        if ((npad > 0) && (npad <= 16)) {
+            VERBOSE (ulvpn, DEBUG, PRINTF ("unpadding %d byte%s\n", npad, (npad > 1) ? "s" : ""));
+            len -= npad;
+        } else {
+            error = 1;
+        }
     }
-    memcpy (buffer + len, enc.data, enc.data_len - npad);
-    len += enc.data_len - npad;
 
-    return len;
+    return (error) ? -1 : len;
 }
 
 int main (int argc, char **argv)
@@ -333,7 +316,7 @@ int main (int argc, char **argv)
         }
     }
 
-    /* init communication channel */
+    /* init udp and tun communication channels */
     int tun_fd = MAPEC_Connect (devtun, loctun, remtun);
     if (tun_fd < 0) {
         VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s %s\n", devtun, loctun, remtun));
@@ -345,27 +328,16 @@ int main (int argc, char **argv)
         return -1;
     }
 
-    /* init crypto module */
-    cm_t cm = {{0, 0, 0, 0}, -1, -1, -1, -1};
-    int cmok = 0;
-    if ((cmlocblack) && (cmremblack) && (cmlocred) && (cmremred)) {
-        cmok = 1;
-        if ((cm.rxblack = MOREP_Connect (cmlocblack)) < 0) {
-            cmok = 0;
-        }
-        if ((cm.txblack = MOREP_Connect (cmremblack)) < 0) {
-            cmok = 0;
-        }
-        if ((cm.rxred = MOREP_Connect (cmlocred)) < 0) {
-            cmok = 0;
-        }
-        if ((cm.txred = MOREP_Connect (cmremred)) < 0) {
-            cmok = 0;
-        }
-    }
+    /* init crypto module communication channels */
+    int rxblack_fd = (cmlocblack) ? MOREP_Connect (cmlocblack) : -1;
+    int txblack_fd = (cmremblack) ? MOREP_Connect (cmremblack) : -1;
+    int rxred_fd = (cmlocred) ? MOREP_Connect (cmlocred) : -1;
+    int txred_fd = (cmremred) ? MOREP_Connect (cmremred) : -1;
+    int cmok = (rxblack_fd > -1) && (txblack_fd > -1) && (rxred_fd > -1) && (txred_fd > -1);
     if (!cmok) {
         VERBOSE (ulvpn, INFO, PRINTF ("CM desactivated\n"));
     }
+    VERBOSE (ulvpn, INFO, PRINTF ("fids: %d %d %d %d %d %d\n", tun_fd, udp_fd, rxblack_fd, txblack_fd, rxred_fd, txred_fd));
 
     /* signals */
     signal(SIGINT, sig_handler);
@@ -373,73 +345,173 @@ int main (int argc, char **argv)
 
     /* main loop */
     int rc;
+    int seqrx = -1;
+    int seqtx = -1;
     while (!stop) {
         rc = 2;
 
         fd_set readset;
-        FD_ZERO (&readset);
+        int max_fd = 0;
         FD_SET (tun_fd, &readset);
+        if (max_fd < tun_fd) {
+            max_fd = tun_fd;
+        }
         FD_SET (udp_fd, &readset);
-        int max_fd = ((tun_fd > udp_fd) ? tun_fd : udp_fd) + 1;
+        if (max_fd < udp_fd) {
+            max_fd = udp_fd;
+        }
+        if (cmok) {
+            FD_SET (rxblack_fd, &readset);
+            if (max_fd < rxblack_fd) {
+                max_fd = rxblack_fd;
+            }
+            FD_SET (rxred_fd, &readset);
+            if (max_fd < rxred_fd) {
+                max_fd = rxred_fd;
+            }
+        }
 
-        if (-1 == select(max_fd, &readset, NULL, NULL, NULL)) {
+        if (-1 == select (max_fd + 1, &readset, NULL, NULL, NULL)) {
             if (!stop) {
                 VERBOSE (ulvpn, ERROR, PRINTF ("select error\n"));
             }
             break;
         }
 
-        uint8_t buffer[MAXPAYLOAD] = {0};
-
         if (FD_ISSET (tun_fd, &readset)) {
-            int r = MAPEC_Receive (tun_fd, buffer, sizeof (buffer));
-            if (r < 0) {
-                // TODO: ignore some errno
-                VERBOSE (ulvpn, ERROR, PRINTF ("error when receiving from tun\n"));
-                //break;
+            uint8_t buffer[MAXPAYLOAD] = {0};
+            int rxlen = MAPEC_Receive (tun_fd, buffer, sizeof (buffer));
+            if (rxlen < 0) {
+                VERBOSE (ulvpn, WARNING, PRINTF ("error when receiving from tun\n"));
+           } else {
+                VERBOSE (ulvpn, DEBUG, PRINTF ("received %d bytes from tun\n", rxlen));
+
+                if (cmok) {
+                    int txlen = pack_clear_data (buffer, rxlen, sizeof (buffer));
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when packing clear data\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("packing %d bytes\n", txlen));
+                        seqtx = MOREP_Send (txred_fd, 0x00, buffer, txlen);
+                        if (seqtx < 0) {
+                            VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to CM red\n"));
+                        } else {
+                            VERBOSE (ulvpn, DEBUG, PRINTF ("send %d bytes to CM red\n", txlen));
+                        }
+                    }
+                } else {
+                    int txlen = MAPEC_Send (udp_fd, buffer, rxlen);
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to udp\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("sent %d bytes to udp\n", txlen));
+                    }
+                }
+            }
+
+        } else if (FD_ISSET (udp_fd, &readset)) {
+            uint8_t buffer[MAXPAYLOAD] = {0};
+            int rxlen = MAPEC_Receive (udp_fd, buffer, sizeof (buffer));
+            if (rxlen < 0) {
+                VERBOSE (ulvpn, WARNING, PRINTF ("error when receiving from udp\n"));
             } else {
-                VERBOSE (ulvpn, DEBUG, PRINTF ("received from tun %d bytes\n", r));
+                VERBOSE (ulvpn, DEBUG, PRINTF ("received %d bytes from udp\n", rxlen));
 
                 if (cmok) {
-                    r = encrypt (buffer, r, &cm);
+                    int txlen = pack_encrypted_data (buffer, rxlen, sizeof (buffer));
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when packing encrypted data\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("packing %d bytes\n", txlen));
+                        seqtx = MOREP_Send (txblack_fd, 0x02, buffer, txlen);
+                        if (seqtx < 0) {
+                            VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to CM black\n"));
+                        } else {
+                            VERBOSE (ulvpn, DEBUG, PRINTF ("send %d bytes to CM black\n", txlen));
+                        }
+                    }
+                } else {
+                    int txlen = MAPEC_Send (tun_fd, buffer, rxlen);
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to tun\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("sent %d bytes to tun\n", txlen));
+                    }
                 }
+            }
 
-                if (r > 0) {
-                    r = MAPEC_Send (udp_fd, buffer, r);
+        } else if (FD_ISSET (rxblack_fd, &readset)) {
+            uint8_t buffer[MAXPAYLOAD] = {0};
+            uint8_t msgtype = -1;
+            int rxlen = 0;
+            seqrx = MOREP_Receive (rxblack_fd, &msgtype, buffer, &rxlen);
+
+            if (rxlen <= 0) {
+                VERBOSE (ulvpn, WARNING, PRINTF ("error when receiving from CM black\n"));
+
+            } else {
+                VERBOSE (ulvpn, DEBUG, PRINTF ("received %d bytes from CM black\n", rxlen));
+
+                if (seqtx != seqrx) {
+                    VERBOSE (ulvpn, WARNING, PRINTF ("incoherent seqnum (%d/%d)\n", seqtx, seqrx));
                 }
-                if (r <= 0) {
-                    // TODO: ignore some errno
-                    VERBOSE (ulvpn, ERROR, PRINTF ("error when sending to udp\n"));
-                    //break;
-                } else if (r > 0) {
-                    VERBOSE (ulvpn, DEBUG, PRINTF ("sent to udp %d bytes\n", r));
+
+                if (msgtype == 0x01) {
+                    int txlen = depack_encrypted_data (buffer, rxlen, sizeof (buffer));
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when depacking encrypted data\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("depacking %d bytes\n", txlen));
+                        txlen = MAPEC_Send (udp_fd, buffer, txlen);
+                        if (txlen <= 0) {
+                            VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to udp\n"));
+                        } else {
+                            VERBOSE (ulvpn, DEBUG, PRINTF ("sent to udp %d bytes\n", txlen));
+                        }
+                    }
+
+
                 } else {
-                    VERBOSE (ulvpn, DEBUG, PRINTF ("nothing sent to udp\n"));
+                    VERBOSE (ulvpn, WARNING, PRINTF ("can't process msgtype %d\n", msgtype));
                 }
             }
 
-        } else if (FD_ISSET (udp_fd, &readset)) {
-            int r = MAPEC_Receive (udp_fd, buffer, sizeof (buffer));
-            if (r < 0) {
-                // TODO: ignore some errno
-                VERBOSE (ulvpn, ERROR, PRINTF ("error when receiving from udp\n"));
-                //break;
+        } else if (FD_ISSET (rxred_fd, &readset)) {
+            uint8_t buffer[MAXPAYLOAD] = {0};
+            uint8_t msgtype = -1;
+            int rxlen = 0;
+            seqrx = MOREP_Receive (rxred_fd, &msgtype, buffer, &rxlen);
+
+            if (rxlen <= 0) {
+                VERBOSE (ulvpn, WARNING, PRINTF ("error when receiving from CM bred\n"));
+
             } else {
-                VERBOSE (ulvpn, DEBUG, PRINTF ("received from udp %d bytes\n", r));
+                VERBOSE (ulvpn, DEBUG, PRINTF ("received %d bytes from CM red\n", rxlen));
 
-                if (cmok) {
-                    r = decrypt (buffer, r, &cm);
+                if (seqtx != seqrx) {
+                    VERBOSE (ulvpn, WARNING, PRINTF ("incoherent seqnum (%d/%d)\n", seqtx, seqrx));
                 }
 
-                r = MAPEC_Send (tun_fd, buffer, r);
-                if (r < 0) {
-                    // TODO: ignore some errno
-                    VERBOSE (ulvpn, ERROR, PRINTF ("error when sending to tun\n"));
-                    //break;
+                if (msgtype == 0x03) {
+                    int txlen = depack_clear_data (buffer, rxlen, sizeof (buffer));
+                    if (txlen <= 0) {
+                        VERBOSE (ulvpn, WARNING, PRINTF ("error when depacking clear data\n"));
+                    } else {
+                        VERBOSE (ulvpn, DEBUG, PRINTF ("depacking %d bytes\n", txlen));
+                        txlen = MAPEC_Send (tun_fd, buffer, txlen);
+                        if (txlen <= 0) {
+                            VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to tun\n"));
+                        } else {
+                            VERBOSE (ulvpn, DEBUG, PRINTF ("sent to tun %d bytes\n", txlen));
+                        }
+                    }
+
+
                 } else {
-                    VERBOSE (ulvpn, DEBUG, PRINTF ("sent to tun %d bytes\n", r));
+                    VERBOSE (ulvpn, WARNING, PRINTF ("can't process msgtype %d\n", msgtype));
                 }
             }
+
         }
 
         rc = 0;
@@ -489,8 +561,10 @@ int main (int argc, char **argv)
 
 /* test: ulvpn.exe -v 5 -t udp://\*:1234 -u udp://localhost:1235 & pid1=$!; sleep 1; nc -ul 1235 > pcap & pid2=$!; sleep 1; echo TEST | nc -Nuq0 10.2.1.1 3000; sleep 1; kill -TERM $pid1 $pid2; strings pcap | grep -q TEST */
 /* test: ulvpn.exe -v 5 -l tun://10.2.1.1 -r tun://10.2.0.0 -t udp://localhost:1234 -u udp://localhost:1235 & pid1=$!; sleep 1; nc -ul 3000 > text & pid2=$!; sleep 1; cat pcap | nc -4Nuq0 -p 1235 localhost 1234; sleep 1; kill -TERM $pid1 $pid2; test "$(cat text)" = TEST */
-
 /* test: rm -f pcap text */
+
 /* test: ip addr del dev eth0 10.1.0.1/24 && ip link del eth0 type dummy || echo no need to remove eth0 */
 
+/* test: ./test.sh ulvpn.exe */
+
 /* vim: set ts=4 sw=4 si et: */