add route for tun and global tests
authorMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 3 Jun 2025 09:54:41 +0000 (11:54 +0200)
committerMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 3 Jun 2025 09:54:41 +0000 (11:54 +0200)
mapec.c
mapec.h
mapec_test.c
mapec_valid.c
script-udp.mapec
ulvpn.c
ulvpn.sh

diff --git a/mapec.c b/mapec.c
index 312a014b7b4a5174ae5576f199d08e0a2ca8c173..5f5c31aa51b202804710436fa9c2aa72f8d7dbe2 100644 (file)
--- a/mapec.c
+++ b/mapec.c
@@ -19,6 +19,7 @@
 #include <linux/if_tun.h>
 #include <linux/sockios.h>
 #include <net/if.h>
+#include <net/route.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -209,7 +210,7 @@ int connect_udp (MAPEC_addr_t *mapec, char *local_address, char *remote_address)
 
 #define ifreq_offsetof(x) offsetof(struct ifreq, x)
 
-int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *ip_address)
+int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *local_address, char *remote_address)
 {
 
     VERBOSE (mapec, TRACE, PRINTF ("connect_tun\n"));
@@ -221,7 +222,7 @@ int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *ip_address)
         return -1;
     }
 
-    VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s\n", device_name, ip_address));
+    VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s %s\n", device_name, local_address, (remote_address) ? remote_address : ""));
 
     /* link to named device */
     struct ifreq ifr = { 0 };
@@ -246,11 +247,11 @@ int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *ip_address)
     /* set ip address */
     mapec->addrin.sin_family = AF_INET;
     mapec->addrin.sin_port   = 0;
-    mapec->addrin.sin_addr.s_addr = inet_addr (ip_address);
+    mapec->addrin.sin_addr.s_addr = inet_addr (local_address);
     memcpy (&ifr.ifr_addr, &mapec->addrin, sizeof (struct sockaddr));
 
     if ((ioctl (sock, SIOCSIFADDR, &ifr) < 0) || (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)) {
-        VERBOSE (mapec, ERROR, PRINTF ("can't set ip address '%s' on tun device '%s'\n", ip_address, device_name));
+        VERBOSE (mapec, ERROR, PRINTF ("can't set ip address '%s' on tun device '%s'\n", local_address, device_name));
         return -1;
     }
 
@@ -261,10 +262,38 @@ int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *ip_address)
     }
     close (sock);
 
+    /* create route */
+    if (remote_address) {
+        struct rtentry route = {0};
+        struct sockaddr_in *addr = (struct sockaddr_in *) &route.rt_gateway;
+        addr->sin_family = AF_INET;
+        addr->sin_addr.s_addr = inet_addr (local_address);
+        addr = (struct sockaddr_in *) &route.rt_dst;
+        addr->sin_family = AF_INET;
+        addr->sin_addr.s_addr = inet_addr (remote_address);
+        addr = (struct sockaddr_in *) &route.rt_genmask;
+        addr->sin_family = AF_INET;
+        addr->sin_addr.s_addr = inet_addr ("255.255.255.0");
+        route.rt_flags = RTF_UP | RTF_GATEWAY;
+        route.rt_metric = 0;
+
+        sock = socket( PF_INET, SOCK_DGRAM,  IPPROTO_IP);
+        if (sock < 0) {
+            VERBOSE (mapec, ERROR, PRINTF ("can't accept socket %d\n", sock));
+            errno = ENOMEM;
+            return -1;
+        }
+        if (ioctl (sock, SIOCADDRT, &route) < 0) {
+            VERBOSE (mapec, ERROR, PRINTF ("can't create route '%s'/24 via '%s'\n", remote_address, local_address));
+            return -1;
+        }
+        close (sock);
+    }
+
     return fid;
 }
 
-int MAPEC_Connect (char *arg1, char *arg2)
+int MAPEC_Connect (char *arg1, char *arg2, char *arg3)
 {
 
     VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Connect\n"));
@@ -273,11 +302,14 @@ int MAPEC_Connect (char *arg1, char *arg2)
 
     /* check type */
     int rc = parse_protocol (&mapec.type, arg1);
-    if (arg2) {
+    if ((rc > 0) && (arg2)) {
         rc = parse_protocol (&mapec.type, arg2);
     }
+    if ((rc > 0) && (arg3)) {
+        rc = parse_protocol (&mapec.type, arg3);
+    }
     if (rc < 0) {
-        VERBOSE (mapec, ERROR, PRINTF ("non coherent protocol '%s' <> '%s'\n", arg1, (arg2) ? arg2 : ""));
+        VERBOSE (mapec, ERROR, PRINTF ("non coherent protocol '%s' <> '%s' <> '%s'\n", arg1, (arg2) ? arg2 : "", (arg3) ? arg3 : ""));
         errno = EINVAL;
         return -1;
     }
@@ -285,11 +317,11 @@ int MAPEC_Connect (char *arg1, char *arg2)
     int fid;
     switch (mapec.type) {
     case MAPEC_udp_e:
-        fid = connect_udp (&mapec, arg1 + rc, arg2 + rc);
+        fid = connect_udp (&mapec, arg1 + rc, (arg2) ? arg2 + rc : NULL);
         break;
 
     case MAPEC_tun_e:
-        fid = connect_tun (&mapec, arg1 + rc, arg2 + rc);
+        fid = connect_tun (&mapec, arg1 + rc, (arg2) ? arg2 + rc : NULL, (arg3) ? arg3 + rc : NULL);
         break;
 
     default:
diff --git a/mapec.h b/mapec.h
index af382839c50aac49753aeab31f0a867535bdc41f..aecdd72f87bc888cb114e32dc60a39897a6483ce 100644 (file)
--- a/mapec.h
+++ b/mapec.h
@@ -22,26 +22,28 @@ __BEGIN_DECLS
 /**
    @defgroup MAPEC Public API of MAPEC
 
-   This library offers connections over UDP socket or TUN interface. In
-   both case, communication is based on packet exchanges.
+   This library offers connections over UDP socket or TUN interface. In both
+   case, communication is based on packet exchanges.
 
-   Values returned by MAPEC_Connect are standard Linux file descriptors
-   that can be used in select()/poll() system calls.
+   Values returned by MAPEC_Connect are standard Linux file descriptors that
+   can be used in select()/poll() system calls.
 */
 
 /**
    @ingroup MAPEC
 
-   Establish a connection between a local URL and a remote URL. Block
-   until connection is established or refused.
+   Establish a connection between a local URL and a remote URL. Block until
+   connection is established or refused.
 
    @param arg1 first argument
    @param arg2 second argrument
+   @param arg3 third argrument
 
-   For UDP connection, arguements are local and remote addresses. The
-   syntax is 'udp://hostname:port'
-   For TUN connection, first argument is an url, second argument is the
-   IP address of the tun device. The syntax is tun://device and tun://ip
+   For UDP connection, arguements are local and remote addresses. The syntax is
+   'udp://hostname:port'
+   For TUN connection, first argument is the device name, second argument is
+   the IP address of the tun device and third argument is the IP adresss of the
+   distant network. The syntax is tun://device, tun://ip, and tun://ip
 
    @return a new file descriptor associated with this connection
 
@@ -49,7 +51,7 @@ __BEGIN_DECLS
    @see MAPEC_Send()
    @see MAPEC_Receive()
 */
-int MAPEC_Connect (char *arg1, char *arg2);
+int MAPEC_Connect (char *arg1, char *arg2, char *arg3);
 
 /**
    @ingroup MAPEC
index 1848e6ddf43e4f8dd114de7d9c94c5d7cdc896a2..f59be33df1490f8aa60dc4afa3bf9bf2aad3757d 100644 (file)
@@ -48,7 +48,7 @@ void *client (UNUSED void *dummy)
     unsigned char tx_data[10][1500];
     int tx_len[10];
 
-    int fid = MAPEC_Connect (client_local_url, client_remote_url);
+    int fid = MAPEC_Connect (client_local_url, client_remote_url, NULL);
     if (fid < 0) {
         VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Connect error\n"));
         MAPEC_Echo_OK = 0;
@@ -118,7 +118,7 @@ void *server (UNUSED void *dummy)
 
     VERBOSE (mapec, TRACE, PRINTF ("server\n"));
 
-    int fid = MAPEC_Connect (server_local_url, server_remote_url);
+    int fid = MAPEC_Connect (server_local_url, server_remote_url, NULL);
     if (fid < 0) {
         VERBOSE (mapec, ERROR, PRINTF ("MAPEC_Connect (%d)\n", fid));
         exit (1);
index 0f1851b1a1d6592051faad7f55f86f77722bc4a1..25837ddeae8e3435c55d7cd377888e28dc25a56c 100644 (file)
@@ -328,7 +328,7 @@ int main (int argc, char **argv)
                 VERBOSE (mapec, ERROR, PRINTF ("missing an url (%s|%s)\n", comm->rxurl, comm->txurl));
                 return -1;
             }
-            comm->fid = MAPEC_Connect (comm->rxurl, comm->txurl);
+            comm->fid = MAPEC_Connect (comm->rxurl, comm->txurl, NULL);
             if (comm->fid < 0) {
                 VERBOSE (mapec, ERROR, PRINTF ("can't open communication for %s %s %s\n", comm->serv, comm->rxurl, comm->txurl));
                 return -1;
@@ -427,7 +427,7 @@ int main (int argc, char **argv)
         /* get values */
         char *tmp = line + offset;
         TEST_CHARS (tmp, " \t", 0);
-        if (strncmp (tmp, "PAYLOAD", 3) != 0) {
+        if (strncmp (tmp, "PAYLOAD", 6) != 0) {
             VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s' (%s)\n", line, tmp));
             continue;
         }
@@ -447,9 +447,9 @@ int main (int argc, char **argv)
             int txlen = MAPEC_Send (comm->fid, payload, len);
             /* check payload */
             if (txlen != len) {
-                VERBOSE (mapec, WARNING, PRINTF ("T%s: payloads differed %d/%d\n", comm->serv, len, txlen));
+                VERBOSE (mapec, WARNING, PRINTF ("T%s: payload not sent %d/%d\n", comm->serv, len, txlen));
             } else {
-                VERBOSE (mapec, INFO, PRINTF ("T%s: payloads matched [%d]\n", comm->serv, txlen));
+                VERBOSE (mapec, INFO, PRINTF ("T%s: payload sent [%d]\n", comm->serv, txlen));
             }
 
             if (log) {
@@ -461,9 +461,9 @@ int main (int argc, char **argv)
 
             /* check payload */
             if ((rxlen != len) || ((memcmp (rxpayload, payload, rxlen) != 0))) {
-                VERBOSE (mapec, WARNING, PRINTF ("R%s: payloads differed %d/%d\n", comm->serv, len, rxlen));
+                VERBOSE (mapec, WARNING, PRINTF ("R%s: payload differed %d/%d\n", comm->serv, len, rxlen));
             } else {
-                VERBOSE (mapec, INFO, PRINTF ("R%s: payloads matched [%d]\n", comm->serv, rxlen));
+                VERBOSE (mapec, INFO, PRINTF ("R%s: payload matched [%d]\n", comm->serv, rxlen));
             }
 
             if (log) {
@@ -493,11 +493,11 @@ int main (int argc, char **argv)
 /* test: mapec_valid.exe -r 2>&1 | grep 'receiver url not specified' */
 /* test: mapec_valid.exe -s 2>&1 | grep 'service name not specified' */
 /* test: mapec_valid.exe -t 2>&1 | grep 'transmitter url not specified' */
-/* test: mapec_valid.exe -v 2>&1 | grep 'verbose level url not specified' */
+/* test: mapec_valid.exe -v 2>&1 | grep 'verbose level not specified' */
 
 /* test: mapec_valid.exe -s UDP o -r udp://localhost:1234 2>&1 | grep 'missing an url' */
 /* test: echo | mapec_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 */
-/* test: mapec_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.marep & mapec_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.marep */
+/* test: mapec_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; mapec_valid.exe -s UDP -r udp://localhost:1235 -t udp://localhost:1234 script-udp.mapec | awk '{print "<2>", $0}' */
 /* test: mapec_valid.exe -s TUN0 -r tun://tun0 2>&1 | grep 'missing an url' */
 /* test: echo | mapec_valid.exe -s TUN0 -r tun://tun0 -t tun://1.2.3.4 */
 
index 9836487f685641c1e61d98975779ae3a53dba9d7..6c36fb2d93c698aad8e1eb295353bc7cd8d1a9c5 100644 (file)
@@ -1,10 +1,10 @@
 # Test script
 
 TUDP PAYLOAD=@plaintext.txt
-RUDP PAYLOAD=@plaintext.txt
+SLEEP 1000
 
-TUDP PAYLAOD="This\ is\ a\ text"
-RUDP PAYLAOD="This\ is\ a\ text"
+TUDP PAYLOAD="This\ is\ a\ text"
+SLEEP 1000
 
-TUDP PAYLAOD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
-RUDP PAYLAOD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
+TUDP PAYLOAD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
+SLEEP 1000
diff --git a/ulvpn.c b/ulvpn.c
index 56d04575bdc02914a6e9b528c0a234b11c1849e6..1689ea9fd9322e1e39281ad2bedaa845c1707f3d 100644 (file)
--- a/ulvpn.c
+++ b/ulvpn.c
@@ -32,7 +32,7 @@ char *version = "0.1";
 
 char *devtun = "tun://tun0";
 char *loctun = "tun://10.2.0.1";
-char *remtun = "tun://10.2.0.2";
+char *remtun = "tun://10.2.1.0";
 char *locudp = "udp://10.1.0.1:1234";
 char *remudp = "udp://10.1.0.2:1235";
 
@@ -110,7 +110,7 @@ int main (int argc, char **argv)
         case 'r':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
-                VERBOSE (ulvpn, ERROR, PRINTF ("%s: remove tun not specified\n", progname));
+                VERBOSE (ulvpn, ERROR, PRINTF ("%s: remote tun not specified\n", progname));
                 return 1;
             }
             remtun = arg;
@@ -126,7 +126,7 @@ int main (int argc, char **argv)
         case 'u':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
-                VERBOSE (ulvpn, ERROR, PRINTF ("%s: remove udp not specified\n", progname));
+                VERBOSE (ulvpn, ERROR, PRINTF ("%s: remote udp not specified\n", progname));
                 return 1;
             }
             remudp = arg;
@@ -155,12 +155,12 @@ int main (int argc, char **argv)
     }
 
     /* init communication channel */
-    int tun_fd = MAPEC_Connect (devtun, loctun);
+    int tun_fd = MAPEC_Connect (devtun, loctun, remtun);
     if (tun_fd < 0) {
-        VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s\n", devtun, loctun));
+        VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s %s\n", devtun, loctun, remtun));
         return -1;
     }
-    int udp_fd = MAPEC_Connect (locudp, remudp);
+    int udp_fd = MAPEC_Connect (locudp, remudp, NULL);
     if (udp_fd < 0) {
         VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s\n", locudp, remudp));
         return -1;
@@ -244,7 +244,15 @@ int main (int argc, char **argv)
     return rc;
 }
 
-/* test: mapec_valid.exe -h | grep usage */
-/* test: mapec_valid.exe -l 2>&1 | grep 'log file not specified' */
+/* test: ulvpn.exe -h | grep usage */
+/* test: ulvpn.exe -d 2>&1 | grep 'dev tun not specified' */
+/* test: ulvpn.exe -l 2>&1 | grep 'local tun not specified' */
+/* test: ulvpn.exe -r 2>&1 | grep 'remote tun not specified' */
+/* test: ulvpn.exe -t 2>&1 | grep 'local udp not specified' */
+/* test: ulvpn.exe -u 2>&1 | grep 'remote udp not specified' */
+/* test: ulvpn.exe -v 2>&1 | grep 'verbose level not specified' */
+/* test: ulvpn.exe -V 2>&1 | grep 'verbose level not specified' */
+/* test: ulvpn.exe -v 5 & pid=$!; sleep 1; ip route list dev tun0; rc=$?; sleep 1; kill -TERM $pid; test $rc -eq 0 */
+/* test: ulvpn.exe -v 5 & pid=$!; sleep 1; ping -c 1 -W 1 10.2.1.1; kill -TERM $pid */
 
 /* vim: set ts=4 sw=4 si et: */
index c595cd460e7582049e63668fcaa4ea37a754a11d..91d68b3e41229e3a63a02d01f2854934503f33fb 100755 (executable)
--- a/ulvpn.sh
+++ b/ulvpn.sh
@@ -6,26 +6,14 @@ title() { echo -e "\033[0;1m$@\033[0;0m"; }
 
 if $(ip add list dev enp0s4 | fgrep -q 10.1.0.2/); then
     title Remote
-    {
-      sleep 1
-      ip addr add 10.3.0.1/24 dev enp0s3
-      ip route add 10.4.0.0/24 dev tun0
-      title "ready"
-    } &
     $VPN -v 5 \
       -d tun://tun0 \
-      -r tun://10.2.0.1 -l tun://10.2.0.2 \
+      -l tun://10.2.1.1 -r tun://10.2.0.0 \
       -u udp://10.1.0.1:1234 -t udp://10.1.0.2:1235
 else
     title Local
-    {
-      sleep 1
-      ip addr add 10.4.0.1/24 dev enp0s3
-      ip route add 10.3.0.0/24 dev tun0
-      title "ready"
-    } &
     $VPN -v 5 \
       -d tun://tun0 \
-      -l tun://10.2.0.1 -r tun://10.2.0.2 \
+      -l tun://10.2.0.1 -r tun://10.2.1.0 \
       -t udp://10.1.0.1:1234 -u udp://10.1.0.2:1235
 fi