add mono-directional sockets for udp connection v1.1
authorMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 2 Sep 2025 17:29:46 +0000 (19:29 +0200)
committerMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 2 Sep 2025 17:29:46 +0000 (19:29 +0200)
ulvpn.c

diff --git a/ulvpn.c b/ulvpn.c
index 112f397e4dcfb3e02a1834681f766039d5d02014..243a1dd6b33f98403205441f1a111a5b56c1c9e8 100644 (file)
--- a/ulvpn.c
+++ b/ulvpn.c
@@ -38,8 +38,10 @@ char *version = "0.9";
 char *devtun = "tun://tun0:1440";
 char *loctun = "tun://10.2.0.1";
 char *remtun = "tun://10.2.1.0";
-char *locudp = "udp://10.1.0.1:1234";
-char *remudp = "udp://10.1.0.2:1235";
+char *locudprx = "udp://10.1.0.1:1234";
+char *locudptx = NULL;
+char *remudprx = "udp://10.1.0.2:1235";
+char *remudptx = NULL;
 char *cmlocblack = "lo://00:00:00:00:00:00/0829";
 char *cmremblack = "lo://00:00:00:00:00:00/0839";
 char *cmlocred = "lo://00:00:00:00:00:00/0809";
@@ -98,14 +100,22 @@ void sig_handler (int sig)
 
 void usage (void)
 {
-    printf ("usage: %s [-d devtun] [-h] [-l loctun] [-n mod] [-r remtun] [-t locudp] [-u remudp] [-v int] [-x url url] [-y url url] [-w]\n", progname);
+    printf ("usage: %s [-d devtun] [-h] [-l loctun] [-n mod] [-r remtun] [-t[r|t] locudp] [-u[r|t] remudp] [-v int] [-x url url] [-y url url] [-w]\n", progname);
     printf (" -d: dev tun (%s)\n", devtun);
     printf (" -h: help message\n");
     printf (" -l: local tun (%s)\n", loctun);
     printf (" -n: desactivate module (tun,udp,red,black)\n");
     printf (" -r: remote tun (%s)\n", remtun);
-    printf (" -t: local udp (%s)\n", locudp);
-    printf (" -u: remote udp (%s)\n", remudp);
+    if (locudprx != locudptx) {
+        printf (" -t[r|t]: local udp [rx|tx] (%s|%s)\n", locudprx, locudptx);
+    } else {
+        printf (" -t[r|t]: local udp [rx|tx] (%s)\n", locudprx);
+    }
+    if (remudprx != remudptx) {
+        printf (" -u[r|t]: remote udp [rx|tx] (%s|%s)\n", remudprx, remudptx);
+    } else {
+        printf (" -u[r|t]: remote udp [rx|tx] (%s)\n", remudprx);
+    }
     printf (" -v: program verbose level [%d..%d] (%d)\n", ERROR, TRACE, GET_VERBOSE_LEVEL (ulvpn));
     printf (" -V: library verbose level [%d..%d] (%d)\n", ERROR, TRACE, GET_VERBOSE_LEVEL (mapec));
     printf (" -x: black CM service (%s|%s)\n", cmlocblack, cmremblack);
@@ -247,6 +257,8 @@ int depack_clear_data (uint8_t *buffer, int len, int maxlen)
 
 int main (int argc, char **argv)
 {
+    locudptx = locudprx;
+    remudptx = remudprx;
 
     /* get basename */
     char *ptr = progname = argv[0];
@@ -266,6 +278,7 @@ int main (int argc, char **argv)
             return 1;
         }
         char c = arg[1];
+        int way = 0;
         switch (c) {
         case 'd':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
@@ -294,8 +307,8 @@ int main (int argc, char **argv)
                 loctun = NULL;
                 remtun = NULL;
             } else if (strcmp (arg, "udp") == 0) {
-                locudp = NULL;
-                remudp = NULL;
+                locudprx = locudptx = NULL;
+                remudprx = remudptx = NULL;
             } else if (strcmp (arg, "black") == 0) {
                 cmlocblack = NULL;
                 cmremblack = NULL;
@@ -317,20 +330,30 @@ int main (int argc, char **argv)
             remtun = arg;
             break;
         case 't':
-            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            way = (arg[2] == 'r') ? 1 : (arg[2] == 't') ? -1 : 0;
+            arg = (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
                 VERBOSE (ulvpn, ERROR, PRINTF ("%s: local udp not specified\n", progname));
                 return 1;
             }
-            locudp = arg;
+            switch (way) {
+                case 1: locudprx = arg; break;
+                case -1: locudptx = arg; break;
+                default: locudprx = locudptx = arg; break;
+            }
             break;
         case 'u':
-            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            way = (arg[2] == 'r') ? 1 : (arg[2] == 't') ? -1 : 0;
+            arg = (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
                 VERBOSE (ulvpn, ERROR, PRINTF ("%s: remote udp not specified\n", progname));
                 return 1;
             }
-            remudp = arg;
+            switch (way) {
+                case 1: remudprx = arg; break;
+                case -1: remudptx = arg; break;
+                default: remudprx = remudptx = arg; break;
+            }
             break;
         case 'v':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
@@ -382,11 +405,20 @@ int main (int argc, char **argv)
         VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s %s\n", devtun, loctun, remtun));
         return -1;
     }
-    int udp_fd = -1;
-    if (((locudp) && (remudp)) && ((udp_fd = MAPEC_Connect (locudp, remudp, NULL)) < 0)) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s\n", locudp, remudp));
+    int udprx_fd = -1;
+    if (((locudprx) && (remudprx)) && ((udprx_fd = MAPEC_Connect (locudprx, remudprx, NULL)) < 0)) {
+        VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s %s\n", locudprx, remudprx, (locudprx == locudptx) ? "RX/TX" : "RX"));
         return -1;
     }
+    int udptx_fd = -1;
+    if (locudprx == locudptx) {
+        udptx_fd = udprx_fd;
+    } else {
+        if (((locudptx) && (remudptx)) && ((udptx_fd = MAPEC_Connect (locudptx, remudptx, NULL)) < 0)) {
+            VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s TX\n", locudptx, remudptx));
+            return -1;
+        }
+    }
 
     /* init crypto module communication channels */
     int rxblack_fd = (cmlocblack) ? MOREP_Connect (cmlocblack) : -1;
@@ -405,7 +437,7 @@ int main (int argc, char **argv)
         return -1;
     }
 
-    VERBOSE (ulvpn, INFO, PRINTF ("fids: %d %d %d %d %d %d\n", tun_fd, udp_fd, rxblack_fd, txblack_fd, rxred_fd, txred_fd));
+    VERBOSE (ulvpn, INFO, PRINTF ("fids: %d %d %d %d %d %d %d\n", tun_fd, udprx_fd, udptx_fd, rxblack_fd, txblack_fd, rxred_fd, txred_fd));
 
     /* signals */
     sigset_t mask;
@@ -433,10 +465,10 @@ int main (int argc, char **argv)
                 max_fd = tun_fd;
             }
         }
-        if (udp_fd >= 0) {
-            FD_SET (udp_fd, &readset);
-                if (max_fd < udp_fd) {
-                max_fd = udp_fd;
+        if (udprx_fd >= 0) {
+            FD_SET (udprx_fd, &readset);
+                if (max_fd < udprx_fd) {
+                max_fd = udprx_fd;
             }
         }
         if (rxblack_fd >= 0) {
@@ -488,8 +520,8 @@ int main (int argc, char **argv)
                             VERBOSE (ulvpn, DEBUG, PRINTF ("send %d bytes to CM red\n", txlen));
                         }
                     }
-                } else if (udp_fd >= 0) {
-                    int txlen = MAPEC_Send (udp_fd, buffer, rxlen);
+                } else if (udptx_fd >= 0) {
+                    int txlen = MAPEC_Send (udptx_fd, buffer, rxlen);
                     stat_udp_fd.tx++;
                     if (txlen <= 0) {
                         VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to udp\n"));
@@ -501,9 +533,9 @@ int main (int argc, char **argv)
                 }
             }
 
-        } else if (FD_ISSET (udp_fd, &readset)) {
+        } else if (FD_ISSET (udprx_fd, &readset)) {
             uint8_t buffer[MAXPAYLOAD] = {0};
-            int rxlen = MAPEC_Receive (udp_fd, buffer, sizeof (buffer));
+            int rxlen = MAPEC_Receive (udprx_fd, buffer, sizeof (buffer));
             stat_udp_fd.rx++;
             if (rxlen < 0) {
                 VERBOSE (ulvpn, WARNING, PRINTF ("error when receiving from udp\n"));
@@ -558,13 +590,13 @@ int main (int argc, char **argv)
                 }
 
                 if (msgtype == 0x01) {
-                    if (udp_fd >= 0) {
+                    if (udptx_fd >= 0) {
                         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);
+                            txlen = MAPEC_Send (udptx_fd, buffer, txlen);
                             stat_udp_fd.tx++;
                             if (txlen <= 0) {
                                 VERBOSE (ulvpn, WARNING, PRINTF ("error when sending to udp\n"));
@@ -633,7 +665,10 @@ int main (int argc, char **argv)
 
     /* cleaning */
     close (tun_fd);
-    close (udp_fd);
+    close (udprx_fd);
+    if (udprx_fd != udptx_fd) {
+        close (udptx_fd);
+    }
 
     return rc;
 }
@@ -655,7 +690,7 @@ int main (int argc, char **argv)
 /* test: ulvpn.exe -n 2>&1 | grep 'module not specified' */
 /* test: ulvpn.exe -n foo 2>&1 | grep 'unknown module' */
 /* test: ulvpn.exe -n tun -h | grep 'dev tun ((null))' */
-/* test: ulvpn.exe -n udp -h | grep 'local udp ((null))' */
+/* test: ulvpn.exe -n udp -h | fgrep 'local udp [rx|tx] ((null))' */
 /* test: ulvpn.exe -n black -h | grep 'black CM service ((null)|(null))' */
 /* test: ulvpn.exe -n red -h | grep 'red CM service ((null)|(null))' */
 
@@ -691,4 +726,8 @@ int main (int argc, char **argv)
 
 /* test: ulvpn.exe -v 5 -n black -n red -t udp://\*:1234 -u udp://localhost:1235 > ulvpn.log & pid=$!; sleep 1; echo TEST | nc -Nuq0 10.2.1.1 3000; kill -TRAP $pid; sleep 1; kill -HUP $pid; sleep 1; echo TEST | nc -Nuq0 10.2.1.1 3000; kill -TRAP $pid; sleep 1; kill -TERM $pid; grep 'tun: RX' ulvpn.log | wc -l | xargs test 2 -eq */
 
+/* test: ulvpn.exe -v 5 -n black -n red -tr udp://localhost:1234 -ur udp://localhost:1235 -tt udp://localhost:1236 -ut udp://localhost:1237 & pid1=$!; sleep 1; nc -ul 1237 > pcap & pid2=$!; sleep 1; echo | nc -Nuq0 10.2.1.1 3000; 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 -n black -n red -l tun://10.2.1.1 -r tun://10.2.0.0 -tr udp://localhost:1234 -ur udp://localhost:1235 -tt udp://localhost:1236 -ut udp://localhost:1237 & 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 */
+
 /* vim: set ts=4 sw=4 si et: */