From: Mazet Laurent Date: Thu, 5 Jun 2025 14:03:36 +0000 (+0200) Subject: add tests X-Git-Tag: v1.0~22 X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=4b19c2297e3f0e3cd671044d0981a587abfc257b;p=ulvpn.git add tests --- diff --git a/mapec_test.c b/mapec_test.c index f59be33..e44bf47 100644 --- a/mapec_test.c +++ b/mapec_test.c @@ -84,7 +84,7 @@ void *client (UNUSED void *dummy) unsigned char rx_data[32768]; do { - rx_len = MAPEC_Receive (fid, rx_data, sizeof (rx_data)); + rx_len = MAPEC_Receive_timeout (fid, rx_data, sizeof (rx_data), 100); if (rx_len == 0) { VERBOSE (mapec, DEBUG, PRINTF ("client's sleeping...\n")); usleep (1e3); diff --git a/mapec_valid.c b/mapec_valid.c deleted file mode 100644 index 25837dd..0000000 --- a/mapec_valid.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - File name : mapec_valid.c - Projet : MERLIN - Date of creation : 2025/05/23 - Version : 1.0 - Copyright : Thales SIX - Author : Laurent Mazet - - Description : Minimal API for Packet Exchange Commmunication validation - program - - History : - - initial version -*/ - -/* depend: */ -/* cflags: */ -/* linker: mapec.o */ - -#include -#include -#include -#include -#include -#include -#include - -#include "mapec.h" -#include "verbose.h" - -char *progname = NULL; - -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; - } -} - -#define TEST_CHARS(str, delim, stop) \ - while (*str != '\0') { \ - int i, stat = 0; \ - for (i = 0; (delim[i] != '\0') && (!stat); i++) { \ - if (*str == delim[i]) { \ - stat = 1; \ - } \ - } \ - if (stat == stop) { \ - break; \ - } \ - str++; \ - } - -int parse_array (char *str, uint8_t *buffer, int maxlen) -{ - int len = 0; - int slen = strlen (str); - - /* string payload: "..." (space must be protected by '\') */ - if ((*str == '"') && (slen > 1)) { - VERBOSE (mapec, TRACE, PRINTF ("string payload: \"...\"\n")); - if (maxlen < slen - 2) slen = maxlen + 2; - if (str[slen - 1] == '"') { - len = slen - 2; - if (len > maxlen) { - VERBOSE (mapec, WARNING, PRINTF ("string too large (%d > %d) for '%s'\n", len, maxlen, str)); - len = maxlen; - } - int j = 0; - for (int i = 1; i < len + 1; i++, j++) { - if ((str[i] == '\\') && (str[i + 1] == ' ')) { - i++; - } - buffer[j] = str[i]; - } - len = j; - VERBOSE (mapec, TRACE, buffer[len] = '\0'; PRINTF ("string[%d]: '%s'\n", len, buffer)); - } else { - VERBOSE (mapec, ERROR, PRINTF ("incomplet string '%s'\n", str)); - } - } - - /* file payload: @filename */ - else if (*str == '@') { - VERBOSE (mapec, TRACE, PRINTF ("file payload: @filename\n")); - FILE *fid = fopen (str + 1, "r"); - if (fid != NULL) { - while ((len < maxlen) && (!feof (fid)) && (!ferror (fid))) { - len += fread (buffer + len, 1, maxlen - len, fid); - } - if (ferror (fid)) { - VERBOSE (mapec, ERROR, PRINTF ("can't read file '%s'\n", str)); - } else if (!feof (fid)) { - fseek (fid, 0L, SEEK_SET); - fseek (fid, 0L, SEEK_END); - int flen = ftell (fid); - if (flen > maxlen) { - VERBOSE (mapec, WARNING, PRINTF ("file too large (%d > %d) for '%s'\n", flen, maxlen, str)); - } - } - fclose (fid); - } else { - VERBOSE (mapec, ERROR, PRINTF ("can't open file '%s'\n", str)); - } - } - - /* hexa payload: xx:xx:xx [0-9a-fA-F] */ - else { - if (maxlen * 3 - 1 < slen) { - slen = maxlen * 3 - 1; - } - if (slen % 3 == 2) { - VERBOSE (mapec, TRACE, PRINTF ("hexa payload: xx:xx:xx\n")); - len = slen / 3 + 1; - if (len > maxlen) { - VERBOSE (mapec, WARNING, PRINTF ("string too large (%d > %d) for '%s'\n", len, maxlen, str)); - len = maxlen; - } - for (int i = 0; i < len; i++) { - char digit[3] = {0}; - char *ptr = NULL; - digit[0] = str[3 * i]; - digit[1] = str[3 * i + 1]; - buffer[i] = strtol (digit, &ptr, 16); - if ((*ptr != ':') && (*ptr != '\0') && (*ptr != ' ') && (*ptr != '\t')) { - VERBOSE (mapec, ERROR, PRINTF ("unrecognize hexa-string (%d) '%s'\n", 3 * i, str)); - break; - } - } - } - - /* unrecognize format */ - else { - VERBOSE (mapec, WARNING, PRINTF ("can't parse buffer '%s'\n", str)); - } - } - return len; -} - -char *read_stream (FILE *sd, int *plen) -{ - VERBOSE (mapec, TRACE, PRINTF ("read_stream\n")); - - /* read and store */ - char *buffer = NULL; - size_t size = 0; - int blocklen = 0; - int length = 0; - do { - size += BUFMAX + (size == 0); - buffer = (char *) realloc (buffer, size); - memset (buffer + size - BUFMAX - 1, 0, BUFMAX + 1); - blocklen = fread (buffer + size - BUFMAX - 1, 1, BUFMAX, sd); - length += blocklen; - } while (blocklen > 0); - - /* check size */ - VERBOSE (mapec, DEBUG, PRINTF ("read length: %d\n", length)); - if (length == 0) { - free (buffer); - buffer = NULL; - } - - if (plen) { - *plen = length; - } - - return buffer; -} - -void print_message (FILE *fd, char *serv, int mode, uint8_t *payload, int len) -{ - fprintf (fd, "%c%s LEN=%d", mode ? 'T' : 'R', serv, len); - if (len > 0) { - int i; - fprintf (fd, " PAYLOAD="); - for (i = 0; i < len; i++) { - fprintf (fd, "%02x%c", payload[i], (i == len - 1) ? '\n' : ':'); - } - } -} - -typedef struct { - char *serv; - char *rxurl; - char *txurl; - int fid; -} comm_t; - -#define MAXCOMMS 32 - -int main (int argc, char **argv) -{ - char *filename = NULL; - char *logname = NULL; - char *url = NULL; - char *serv = NULL; - int mode = -1; - int nbcomms = 0; - comm_t comm_list[MAXCOMMS] = {0}; - int reverse = 0; - - /* 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 'l': - arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; - if (arg == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("%s: log file not specified\n", progname)); - return 1; - } - logname = arg; - break; - case 'n': - reverse = 1; - break; - case 'r': - arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; - if (arg == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("%s: receiver url not specified\n", progname)); - return 1; - } - url = arg; - mode = 0; - break; - case 's': - arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; - if (arg == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("%s: service name not specified\n", progname)); - return 1; - } - serv = arg; - break; - case 't': - arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; - if (arg == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("%s: transmitter url not specified\n", progname)); - return 1; - } - url = arg; - mode = 1; - 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: - printf ("usage: %s [-h] [-n] [-l log] [-r url] [-s serv] [-t url] [-v level] [file]\n", progname); - return (c != 'h'); - } - - /* store service info */ - if (mode != -1) { - int id = -1; - comm_t *comm = NULL; - for (int i = 0; i < MAXCOMMS; i++) { - comm = comm_list + i; - if ((comm->serv) && (strcmp (serv, comm->serv) == 0)) { - id = i; - break; - } - } - if ((id == -1) && (nbcomms < MAXCOMMS)) { - id = nbcomms++; - comm = comm_list + id; - } - if (id == -1) { - VERBOSE (mapec, ERROR, PRINTF ("can't connect on url '%s'\n", url)); - return -1; - } - if (comm->serv == NULL) { - comm->serv = strdup (serv); - } - if (mode == 0) { - free (comm->rxurl); - comm->rxurl = strdup (url); - } else { - free (comm->txurl); - comm->txurl = strdup (url); - } - mode = -1; - } - } - - /* checks */ - if (nbcomms == 0) { - VERBOSE (mapec, ERROR, PRINTF ("no communication channel\n")); - return -1; - } - - /* init communication channel */ - for (int i = 0; i < nbcomms; i++) { - comm_t *comm = comm_list + i; - if (comm->serv) { - if ((comm->rxurl == NULL) || (comm->txurl == NULL)) { - VERBOSE (mapec, ERROR, PRINTF ("missing an url (%s|%s)\n", comm->rxurl, comm->txurl)); - return -1; - } - 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; - } - } - } - - /* open script file */ - FILE *fid = stdin; - if (filename != NULL) { - fid = fopen (filename, "r"); - if (fid == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("can't open script file '%s' for reading\n", filename)); - return -1; - } - } - char *script = read_stream (fid, NULL); - if (fid != stdin) { - fclose (fid); - } - if (script == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("no script read\n")); - return -1; - } - - /* open log file */ - FILE *log = NULL; - if (logname != NULL) { - if (strcmp (logname, "-") == 0) { - log = stdout; - } else { - log = fopen (logname, "w"); - if (log == NULL) { - VERBOSE (mapec, ERROR, PRINTF ("can't open log file '%s' for writing\n", logname)); - return -1; - } - } - } - - /* signals */ - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); - - /* main loop */ - int rc = 0; - ptr = script; - while (*ptr != '\0') { - - /* read line */ - char *line = ptr; - TEST_CHARS (ptr, "\n\r", 1); - *ptr++ = '\0'; - - /* clean line */ - TEST_CHARS (line, " \t", 0); - if ((*line == '\0') || (*line == '#')) { - continue; - } - - /* analyse line */ - mode = -1; - if (*line == 'R') { - mode = 0 ^ reverse; - } else if (*line == 'T') { - mode = 1 ^ reverse; - } else if (strncmp (line, "SLEEP", 5) == 0) { - int duration = atoi (line + 5); - VERBOSE (mapec, INFO, PRINTF ("sleep %dms\n", duration)); - usleep (duration * 1000); - continue; - } - if (mode == -1) { - VERBOSE (mapec, WARNING, PRINTF ("unrecognize line '%s'\n", line)); - continue; - } - - /* find service */ - comm_t *comm = NULL; - int offset = 1; - int i; - for (i = 0; i < nbcomms; i++) { - comm_t *c = comm_list + i; - VERBOSE (mapec, TRACE, PRINTF ("test %s\n", c->serv)); - if (strncmp (line + offset, c->serv, strlen (c->serv)) == 0) { - comm = c; - offset += strlen (c->serv); - break; - } - } - if (comm == NULL) { - VERBOSE (mapec, TRACE, PRINTF ("no MAPEC found '%s'\n", line)); - continue; - } - VERBOSE (mapec, DEBUG, PRINTF ("work with %c[%s]\n", mode ? 'T' : 'R', comm->serv)); - - /* get values */ - char *tmp = line + offset; - TEST_CHARS (tmp, " \t", 0); - if (strncmp (tmp, "PAYLOAD", 6) != 0) { - VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s' (%s)\n", line, tmp)); - continue; - } - tmp += 7; - TEST_CHARS (tmp, " \t=", 0); - uint8_t payload[MAXPAYLOAD] = {0}; - int len = parse_array (tmp, payload, MAXPAYLOAD); - if (len == 0) { - VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s'\n", line)); - continue; - } - - VERBOSE (mapec, TRACE, PRINTF ("payload length: %d\n", len)); - - /* transmit */ - if (mode == 1) { - int txlen = MAPEC_Send (comm->fid, payload, len); - /* check payload */ - if (txlen != len) { - VERBOSE (mapec, WARNING, PRINTF ("T%s: payload not sent %d/%d\n", comm->serv, len, txlen)); - } else { - VERBOSE (mapec, INFO, PRINTF ("T%s: payload sent [%d]\n", comm->serv, txlen)); - } - - if (log) { - print_message (log, comm->serv, 1, payload, txlen); - } - } else { /* receive */ - uint8_t rxpayload[MAXPAYLOAD] = {0}; - int rxlen = MAPEC_Receive (comm->fid, rxpayload, MAXPAYLOAD); - - /* check payload */ - if ((rxlen != len) || ((memcmp (rxpayload, payload, rxlen) != 0))) { - VERBOSE (mapec, WARNING, PRINTF ("R%s: payload differed %d/%d\n", comm->serv, len, rxlen)); - } else { - VERBOSE (mapec, INFO, PRINTF ("R%s: payload matched [%d]\n", comm->serv, rxlen)); - } - - if (log) { - print_message (log, comm->serv, 0, rxpayload, rxlen); - } - } - } - - /* cleaning */ - free (script); - while (nbcomms) { - comm_t *comm = comm_list + --nbcomms; - MAPEC_Close (comm->fid); - free (comm->serv); - free (comm->rxurl); - free (comm->txurl); - } - if (log) { - fclose (log); - } - - 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' */ -/* 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 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 -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 */ - -/* vim: set ts=4 sw=4 si et: */ diff --git a/script-error.mapec b/script-error.mapec new file mode 100644 index 0000000..5e74209 --- /dev/null +++ b/script-error.mapec @@ -0,0 +1,25 @@ +# Test script + +TUDP PAYLOAD=@plaintext.txt text not ignored +SLEEP 100 + +TUDP PAYLOAD=@nofile.txt +SLEEP 100 + +TUDP PAYLOAD=@udp_valid.c +SLEEP 100 + +TUDP PAYLOAD="This is an unfinished text +SLEEP 100 + +TUDP PAYLOAD="This is a text" text not ignored +SLEEP 100 + +TUDP NOTPAYLOAD="This is a text" +SLEEP 100 + +TUDP PAYLOAD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10 text not ignored +SLEEP 100 + +TUDP PAYLOAD=01:02:fo:ob:ae:06:07:08:09:0a:0b:0c:0d:0e:0f:10 +SLEEP 100 diff --git a/udp_valid.c b/udp_valid.c new file mode 100644 index 0000000..10fea07 --- /dev/null +++ b/udp_valid.c @@ -0,0 +1,516 @@ +/* + File name : udp_valid.c + Projet : MERLIN + Date of creation : 2025/05/23 + Version : 1.0 + Copyright : Thales SIX + Author : Laurent Mazet + + Description : Minimal API for Packet Exchange Commmunication (UDP) + validation program + + History : + - initial version +*/ + +/* depend: */ +/* cflags: */ +/* linker: mapec.o */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mapec.h" +#include "verbose.h" + +char *progname = NULL; + +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; + } +} + +#define TEST_CHARS(str, delim, stop) \ + while (*str != '\0') { \ + int i, stat = 0; \ + for (i = 0; (delim[i] != '\0') && (!stat); i++) { \ + if (*str == delim[i]) { \ + stat = 1; \ + } \ + } \ + if (stat == stop) { \ + break; \ + } \ + str++; \ + } + +int parse_array (char *str, uint8_t *buffer, int maxlen) +{ + int len = 0; + int slen = strlen (str); + + /* string payload: "..." (space must be protected by '\') */ + if ((*str == '"') && (slen > 1)) { + VERBOSE (mapec, TRACE, PRINTF ("string payload: \"...\"\n")); + if (maxlen < slen - 2) slen = maxlen + 2; + if (str[slen - 1] == '"') { + len = slen - 2; + if (len > maxlen) { + VERBOSE (mapec, WARNING, PRINTF ("string too large (%d > %d) for '%s'\n", len, maxlen, str)); + len = maxlen; + } + int j = 0; + for (int i = 1; i < len + 1; i++, j++) { + if ((str[i] == '\\') && (str[i + 1] == ' ')) { + i++; + } + buffer[j] = str[i]; + } + len = j; + VERBOSE (mapec, TRACE, buffer[len] = '\0'; PRINTF ("string[%d]: '%s'\n", len, buffer)); + } else { + VERBOSE (mapec, DEBUG, PRINTF ("incomplet string '%s'\n", str)); + } + } + + /* file payload: @filename */ + else if (*str == '@') { + VERBOSE (mapec, TRACE, PRINTF ("file payload: @filename\n")); + FILE *fid = fopen (str + 1, "r"); + if (fid != NULL) { + while ((len < maxlen) && (!feof (fid)) && (!ferror (fid))) { + len += fread (buffer + len, 1, maxlen - len, fid); + } + if (ferror (fid)) { + VERBOSE (mapec, ERROR, PRINTF ("can't read file '%s'\n", str)); + } else if (!feof (fid)) { + fseek (fid, 0L, SEEK_SET); + fseek (fid, 0L, SEEK_END); + int flen = ftell (fid); + if (flen > maxlen) { + VERBOSE (mapec, WARNING, PRINTF ("file too large (%d > %d) for '%s'\n", flen, maxlen, str)); + } + } + fclose (fid); + } else { + VERBOSE (mapec, DEBUG, PRINTF ("can't open file '%s'\n", str)); + } + } + + /* hexa payload: xx:xx:xx [0-9a-fA-F] */ + else { + if (maxlen * 3 - 1 < slen) { + slen = maxlen * 3 - 1; + } + if (slen % 3 == 2) { + VERBOSE (mapec, TRACE, PRINTF ("hexa payload: xx:xx:xx\n")); + len = slen / 3 + 1; + if (len > maxlen) { + VERBOSE (mapec, WARNING, PRINTF ("string too large (%d > %d) for '%s'\n", len, maxlen, str)); + len = maxlen; + } + for (int i = 0; i < len; i++) { + char digit[3] = {0}; + char *ptr = NULL; + digit[0] = str[3 * i]; + digit[1] = str[3 * i + 1]; + buffer[i] = strtol (digit, &ptr, 16); + if ((*ptr != ':') && (*ptr != '\0') && (*ptr != ' ') && (*ptr != '\t')) { + VERBOSE (mapec, DEBUG, PRINTF ("unrecognize hexa-string (%d) '%s'\n", 3 * i, str)); + len = 0; + break; + } + } + } + + /* unrecognize format */ + else { + VERBOSE (mapec, DEBUG, PRINTF ("can't parse buffer '%s'\n", str)); + } + } + return len; +} + +char *read_stream (FILE *sd, int *plen) +{ + VERBOSE (mapec, TRACE, PRINTF ("read_stream\n")); + + /* read and store */ + char *buffer = NULL; + size_t size = 0; + int blocklen = 0; + int length = 0; + do { + size += BUFMAX + (size == 0); + buffer = (char *) realloc (buffer, size); + memset (buffer + size - BUFMAX - 1, 0, BUFMAX + 1); + blocklen = fread (buffer + size - BUFMAX - 1, 1, BUFMAX, sd); + length += blocklen; + } while (blocklen > 0); + + /* check size */ + VERBOSE (mapec, DEBUG, PRINTF ("read length: %d\n", length)); + if (length == 0) { + free (buffer); + buffer = NULL; + } + + if (plen) { + *plen = length; + } + + return buffer; +} + +void print_message (FILE *fd, char *serv, int mode, uint8_t *payload, int len) +{ + fprintf (fd, "%c%s LEN=%d", mode ? 'T' : 'R', serv, len); + if (len > 0) { + int i; + fprintf (fd, " PAYLOAD="); + for (i = 0; i < len; i++) { + fprintf (fd, "%02x%c", payload[i], (i == len - 1) ? '\n' : ':'); + } + } +} + +typedef struct { + char *serv; + char *rxurl; + char *txurl; + int fid; +} comm_t; + +#define MAXCOMMS 32 + +int main (int argc, char **argv) +{ + char *filename = NULL; + char *logname = NULL; + char *url = NULL; + char *serv = NULL; + int mode = -1; + int nbcomms = 0; + comm_t comm_list[MAXCOMMS] = {0}; + int reverse = 0; + + /* 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 'l': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("%s: log file not specified\n", progname)); + return 1; + } + logname = arg; + break; + case 'n': + reverse = 1; + break; + case 'r': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("%s: receiver url not specified\n", progname)); + return 1; + } + url = arg; + mode = 0; + break; + case 's': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("%s: service name not specified\n", progname)); + return 1; + } + serv = arg; + break; + case 't': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("%s: transmitter url not specified\n", progname)); + return 1; + } + url = arg; + mode = 1; + 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: + printf ("usage: %s [-h] [-n] [-l log] [-r url] [-s serv] [-t url] [-v level] [file]\n", progname); + return (c != 'h'); + } + + /* store service info */ + if (mode != -1) { + int id = -1; + comm_t *comm = NULL; + for (int i = 0; i < MAXCOMMS; i++) { + comm = comm_list + i; + if ((comm->serv) && (strcmp (serv, comm->serv) == 0)) { + id = i; + break; + } + } + if ((id == -1) && (nbcomms < MAXCOMMS)) { + id = nbcomms++; + comm = comm_list + id; + } + if (id == -1) { + VERBOSE (mapec, ERROR, PRINTF ("can't connect on url '%s'\n", url)); + return -1; + } + if (comm->serv == NULL) { + comm->serv = strdup (serv); + } + if (mode == 0) { + free (comm->rxurl); + comm->rxurl = strdup (url); + } else { + free (comm->txurl); + comm->txurl = strdup (url); + } + mode = -1; + } + } + + /* checks */ + if (nbcomms == 0) { + VERBOSE (mapec, ERROR, PRINTF ("no communication channel\n")); + return -1; + } + + /* init communication channel */ + for (int i = 0; i < nbcomms; i++) { + comm_t *comm = comm_list + i; + if (comm->serv) { + if ((comm->rxurl == NULL) || (comm->txurl == NULL)) { + VERBOSE (mapec, ERROR, PRINTF ("missing an url (%s|%s)\n", comm->rxurl, comm->txurl)); + return -1; + } + 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; + } + } + } + + /* open script file */ + FILE *fid = stdin; + if (filename != NULL) { + fid = fopen (filename, "r"); + if (fid == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("can't open script file '%s' for reading\n", filename)); + return -1; + } + } + char *script = read_stream (fid, NULL); + if (fid != stdin) { + fclose (fid); + } + if (script == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("no script read\n")); + return -1; + } + + /* open log file */ + FILE *log = NULL; + if (logname != NULL) { + if (strcmp (logname, "-") == 0) { + log = stdout; + } else { + log = fopen (logname, "w"); + if (log == NULL) { + VERBOSE (mapec, ERROR, PRINTF ("can't open log file '%s' for writing\n", logname)); + return -1; + } + } + } + + /* signals */ + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + /* main loop */ + int rc = 0; + ptr = script; + while (*ptr != '\0') { + + /* read line */ + char *line = ptr; + TEST_CHARS (ptr, "\n\r", 1); + *ptr++ = '\0'; + + /* clean line */ + TEST_CHARS (line, " \t", 0); + if ((*line == '\0') || (*line == '#')) { + continue; + } + + /* analyse line */ + mode = -1; + if (*line == 'R') { + mode = 0 ^ reverse; + } else if (*line == 'T') { + mode = 1 ^ reverse; + } else if (strncmp (line, "SLEEP", 5) == 0) { + int duration = atoi (line + 5); + VERBOSE (mapec, INFO, PRINTF ("sleep %dms\n", duration)); + usleep (duration * 1000); + continue; + } + if (mode == -1) { + VERBOSE (mapec, WARNING, PRINTF ("unrecognize line '%s'\n", line)); + continue; + } + + /* find service */ + comm_t *comm = NULL; + int offset = 1; + int i; + for (i = 0; i < nbcomms; i++) { + comm_t *c = comm_list + i; + VERBOSE (mapec, TRACE, PRINTF ("test %s\n", c->serv)); + if (strncmp (line + offset, c->serv, strlen (c->serv)) == 0) { + comm = c; + offset += strlen (c->serv); + break; + } + } + if (comm == NULL) { + VERBOSE (mapec, TRACE, PRINTF ("no MAPEC found '%s'\n", line)); + continue; + } + VERBOSE (mapec, DEBUG, PRINTF ("work with %c[%s]\n", mode ? 'T' : 'R', comm->serv)); + + /* get values */ + char *tmp = line + offset; + TEST_CHARS (tmp, " \t", 0); + if (strncmp (tmp, "PAYLOAD", 6) != 0) { + VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s' (%s)\n", line, tmp)); + continue; + } + tmp += 7; + TEST_CHARS (tmp, " \t=", 0); + uint8_t payload[MAXPAYLOAD] = {0}; + int len = parse_array (tmp, payload, MAXPAYLOAD); + if (len == 0) { + VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s'\n", line)); + continue; + } + + VERBOSE (mapec, TRACE, PRINTF ("payload length: %d\n", len)); + + /* transmit */ + if (mode == 1) { + int txlen = MAPEC_Send (comm->fid, payload, len); + /* check payload */ + if (txlen != len) { + VERBOSE (mapec, WARNING, PRINTF ("T%s: payload not sent %d/%d\n", comm->serv, len, txlen)); + } else { + VERBOSE (mapec, INFO, PRINTF ("T%s: payload sent [%d]\n", comm->serv, txlen)); + } + + if (log) { + print_message (log, comm->serv, 1, payload, txlen); + } + } else { /* receive */ + uint8_t rxpayload[MAXPAYLOAD] = {0}; + int rxlen = MAPEC_Receive (comm->fid, rxpayload, MAXPAYLOAD); + + /* check payload */ + if ((rxlen != len) || ((memcmp (rxpayload, payload, rxlen) != 0))) { + VERBOSE (mapec, WARNING, PRINTF ("R%s: payload differed %d/%d\n", comm->serv, len, rxlen)); + } else { + VERBOSE (mapec, INFO, PRINTF ("R%s: payload matched [%d]\n", comm->serv, rxlen)); + } + + if (log) { + print_message (log, comm->serv, 0, rxpayload, rxlen); + } + } + } + + /* cleaning */ + free (script); + while (nbcomms) { + comm_t *comm = comm_list + --nbcomms; + MAPEC_Close (comm->fid); + free (comm->serv); + free (comm->rxurl); + free (comm->txurl); + } + if (log) { + fclose (log); + } + + return rc + GET_VERBOSE_ERRORS (mapec); +} + +/* test: udp_valid.exe -h | grep usage */ +/* test: chmod a+w *.gcda */ +/* test: udp_valid.exe -l 2>&1 | grep 'log file not specified' */ +/* test: udp_valid.exe -r 2>&1 | grep 'receiver url not specified' */ +/* test: udp_valid.exe -s 2>&1 | grep 'service name not specified' */ +/* test: udp_valid.exe -t 2>&1 | grep 'transmitter url not specified' */ +/* test: udp_valid.exe -v 2>&1 | grep 'verbose level not specified' */ + +/* test: udp_valid.exe -s UDP o -r udp://localhost:1234; test $? -ne 0 */ +/* test: udp_valid.exe -s UDP -r udp://localhost -t udp://localhost:1235:1234; test $? -ne 0 */ +/* test: udp_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost; test $? -ne 0 */ +/* test: udp_valid.exe -s UDP -r udp://nowhere:1234 -t udp://localhost:1235; test $? -ne 0 */ +/* test: udp_valid.exe -s UDP -r udp://localhost:1234 -t udp://nowhere:1235; test $? -ne 0 */ +/* test: udp_valid.exe -s UDP -r udp://localhost:1234 -t tun://localhost:1235; test $? -ne 0 */ +/* test: sudo -u `awk -F: '/sh$/ && $3 != 0 {print $1; exit}' /etc/passwd` udp_valid.exe -s UDP -r udp://localhost:12 -t udp://localhost:35; test $? -ne 0 */ + +/* test: echo | udp_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 */ + +/* test: udp_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; kill -INT $pid */ +/* test: udp_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; kill -TERM $pid */ +/* test: udp_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-error.mapec; test $? -eq $(grep -c TUDP script-error.mapec) */ +/* test: udp_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; udp_valid.exe -s UDP -r udp://localhost:1235 -t udp://localhost:1234 script-udp.mapec | awk '{print "<2>", $0}' */ +/* test: udp_valid.exe -l - -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; udp_valid.exe -l script-udp.log -s UDP -r udp://localhost:1235 -t udp://localhost:1234 script-udp.mapec | awk '{print "<2>", $0}' */ + +/* vim: set ts=4 sw=4 si et: */ diff --git a/ulvpn.c b/ulvpn.c index d815d66..6138c73 100644 --- a/ulvpn.c +++ b/ulvpn.c @@ -244,6 +244,7 @@ int main (int argc, char **argv) } /* test: ulvpn.exe -h | grep usage */ +/* test: chmod a+w *.gcda */ /* test: ulvpn.exe help 2>&1 | grep usage */ /* test: ulvpn.exe -d 2>&1 | grep 'dev tun not specified' */ /* test: ulvpn.exe -l 2>&1 | grep 'local tun not specified' */ @@ -253,7 +254,7 @@ int main (int argc, char **argv) /* test: ulvpn.exe -v 2>&1 | grep 'verbose level not specified' */ /* test: ulvpn.exe -V 2>&1 | grep 'verbose level not specified' */ -/* test: sudo `awk -F: '/sh$/ && $3 != 0 {print $1; exit}' /etc/passwd` ulvpn.exe; test $? -ne 0 */ +/* test: sudo -u `awk -F: '/sh$/ && $3 != 0 {print $1; exit}' /etc/passwd` ulvpn.exe; test $? -ne 0 */ /* test: ulvpn.exe -d tun://tun0:-1; test $? -ne 0 */ /* test: ulvpn.exe -d tun://tun1; test $? -ne 0 */