--- /dev/null
+/*
+ File name : ulvpn.c
+ Projet : MERLIN
+ Date of creation : 2025/05/28
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : Ultra Lite VPN program
+
+ History :
+ - initial version
+*/
+
+/* depend: */
+/* cflags: */
+/* linker: mapec.o */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mapec.h"
+#include "verbose.h"
+
+char *progname = NULL;
+char *version = "0.1";
+
+char *devtun = "tun://tun0";
+char *loctun = "tun://1.2.0.1";
+char *remtun = "tun://1.2.0.2";
+char *locudp = "udp:///1.1.0.1:1234";
+char *remudp = "udp://1.1.0.2:1234";
+
+int stop = 0;
+
+#define BUFMAX 4096
+
+#define MAXPAYLOAD 1500
+
+void sig_handler (int sig)
+{
+ switch (sig) {
+ case SIGINT:
+ //stop = 1;
+ exit (0);
+ break;
+ case SIGTERM:
+ exit (0);
+ break;
+ }
+}
+
+void usage (void)
+{
+ printf ("usage: %s [-d devtun] [-h] [-l loctun] [-r remtun] [-t locudp] [-u remudp] [-v int] [-w]\n", progname);
+ printf (" -d: dev tun (%s)\n", devtun);
+ printf (" -h: help message\n");
+ printf (" -l: local tun (%s)\n", loctun);
+ printf (" -r: remote tun (%s)\n", remtun);
+ printf (" -t: local udp (%s)\n", locudp);
+ printf (" -u: remote udp (%s)\n", remudp);
+ printf (" -v: verbose level [%d..%d] (%d)\n", ERROR, TRACE, verbose);
+ printf ("%s version %s\n", progname, version);
+'
+int main (int argc, char **argv)
+{
+
+ /* get basename */
+ char *ptr = progname = argv[0];
+ while (*ptr) {
+ if ((*ptr == '/') || (*ptr == '\\')) {
+ progname = ptr + 1;
+ }
+ ptr++;
+ }
+
+ /* process argument */
+ while (argc-- > 1) {
+ char *arg = *(++argv);
+ if (arg[0] != '-') {
+ filename = arg;
+ continue;
+ }
+ char c = arg[1];
+ switch (c) {
+ case 'd':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: dev tun not specified\n", progname));
+ return 1;
+ }
+ devtun = arg;
+ break;
+ case 'l':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: local tun not specified\n", progname));
+ return 1;
+ }
+ loctun = arg;
+ break;
+ case 'r':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: remove tun not specified\n", progname));
+ return 1;
+ }
+ remtun = arg;
+ break;
+ case 't':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: local udp not specified\n", progname));
+ return 1;
+ }
+ locudp = arg;
+ break;
+ case 'u':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: remove udp not specified\n", progname));
+ return 1;
+ }
+ remudp = arg;
+ break;
+ case 'v':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (mapec, ERROR, PRINTF ("%s: verbose level not specified\n", progname));
+ return 1;
+ }
+ CHANGE_VERBOSE_LEVEL (mapec, atoi (arg));
+ break;
+ case 'h':
+ default:
+ usage ();
+ return (c != 'h');
+ }
+ }
+
+ /* init communication channel */
+ int tun_fd = MAPEC_Connect (devtun, locudp);
+ if (tun_fd > 0) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't open communication for %s %s\n", devtun, loctun));
+ return -1;
+ }
+ int udp_fd = MAPEC_Connect (locudp, remudp);
+ if (udp_fd > 0) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't open communication for %s %s\n", locudp, remudp));
+ return -1;
+ }
+
+ /* signals */
+ signal(SIGINT, sig_handler);
+ signal(SIGTERM, sig_handler);
+
+ /* main loop */
+ while (stop) {
+
+ fd_set readset;
+ FD_ZERO (&readset);
+ FD_SET (tun_fd, &readset);
+ FD_SET (udp_fd, &readset);
+ int max_fd = ((tun_fd > udp_fd) ? tun_fd : udp_fd) + 1;
+
+ if (-1 == select(max_fd, &readset, NULL, NULL, NULL)) {
+ VERBOSE (ulvpn, ERROR, PRINTF ("select error\n"));
+ break;
+ }
+
+ uint8_t buffer[MAXPAYLOAD] = {0};
+ int len = 0;
+
+ if (FD_ISSET (tun_fd, &readset)) {
+ int r = MAPEC_Receive (tun_fd, buffer, &len);
+ if (r < 0) {
+ // TODO: ignore some errno
+ VERBOSE (ulvpn, ERROR, PRINTF ("error when receiving from tun\n"));
+ break;
+ }
+
+ //encrypt it
+
+ r = MAPEC_Send (udp_fs, buffer, r);
+ if (r < 0) {
+ // TODO: ignore some errno
+ VERBOSE (ulvpn, ERROR, PRINTF ("error when sending to udp\n"));
+ break;
+ }
+
+ } else if (FD_ISSET (udp_fd, &readset)) {
+ int r = MAPEC_Receive (udp_fd, buffer, &len);
+ if (r < 0) {
+ // TODO: ignore some errno
+ VERBOSE (ulvpn, ERROR, PRINTF ("error when receiving from udp\n"));
+ break;
+ }
+
+ //decrypt it
+
+ r = MAPEC_Send (tun_fs, buffer, r);
+ if (r < 0) {
+ // TODO: ignore some errno
+ VERBOSE (ulvpn, ERROR, PRINTF ("error when sending to tun\n"));
+ break;
+ }
+ } else {
+ VERBOSE (ulvpn, ERROR, PRINTF ("select error\n"));
+ break;
+ }
+ }
+
+ /* cleaning */
+ close (tun_fd);
+ close (udp_fd);
+
+ return rc + GET_VERBOSE_ERRORS (mapec);
+}
+
+/* test: mapec_valid.exe -h | grep usage */
+/* test: mapec_valid.exe -l 2>&1 | grep 'log file not specified' */
+
+/* vim: set ts=4 sw=4 si et: */