code completed
authorMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 8 Apr 2025 09:20:36 +0000 (11:20 +0200)
committerMazet Laurent <laurent.mazet@thalesgroup.com>
Tue, 8 Apr 2025 09:20:36 +0000 (11:20 +0200)
morep_simulator.c

index 769d7b83e674011b5f5d6c70ce8fe2d7ddb1df0c..7bdc654a544cb828aea1bdd59d71f112d6db43b4 100644 (file)
@@ -55,16 +55,16 @@ typedef enum {
 
 typedef enum {
     noserv_e = 0,
-    bypass_e,
-    control_e,
     cross_crypto_e,
     local_crypto_e,
+    provisioning_e,
     prng_e,
-    provisioning_e
-} service_t;
+    bypass_e,
+    control_e
+} service_id_t;
 
 typedef enum {
-    nopdu_e = 0,
+    undef_pdu_e = 0,
     channel_e,
     clear_data_e,
     encrypted_data_e,
@@ -72,11 +72,12 @@ typedef enum {
     prng_param_e,
     raw_data_e,
     status_e
+    nopdu_e,
 } pdu_t;
 
 typedef struct {
     char *name;
-    service_t service;
+    service_id_t service_id;
     uint8_t msgtype;
     pdu_t pdu;
 } message_t;
@@ -124,7 +125,34 @@ message_t message_list[] = {
     {"LOCK_RESP", control_e, 0xFF, status_e},
 
     /* End of list */
-    {"", noserv_e, 0x00, nopdu_e}
+    {"", noserv_e, 0x00, undef_pdu_e}
+};
+
+typedef struct {
+    int morep;
+    int mode;
+    char *etype;
+} comm_t;
+
+#define MAXCOMMS 32
+
+comm_t comm_list[MAXCOMMS] = {0};
+
+typedef struct {
+    char *name;
+    service_id_t service_id;
+    comm_t tx;
+    comm_t rx;
+} service_t;
+
+service_t service_list[] = {
+    {"CROSS_CRYPTO", cross_crypto_e, {-1, 0, "0809"}, {-1, 1, "0809"}},
+    {"LOCAL_CRYPTO", local_crypto_e, {-1, 0, "080a"}, {-1, 1, "080a"}},
+    {"PROVISIONING", provisioning_e, {-1, 0, "080b"}, {-1, 1, "080b"}},
+    {"PRNG", prng_e, {-1, 0, "080c"}, {-1, 1, "080c"}},
+    {"BYPASS", bypass_e, {-1, 0, "080d"}, {-1, 1, "080d"}},
+    {"CONTROL", control_e, {-1, 0, "080e"}, {-1, 1, "080e"}},
+    {"", noserv_e, {-1, 0, "0000"}, {-1, 1, "0000"}}
 };
 
 void sig_handler (int sig)
@@ -184,14 +212,6 @@ void print_message (FILE *fd, char *etype, int mode, uint8_t msg, int seqnum, ui
     fprintf (fd ? fd : stdout, "\n");
 }
 
-typedef struct {
-    int morep;
-    int mode;
-    char *etype;
-} comm_t;
-
-#define MAXCOMMS 32
-
 int main (int argc, char **argv)
 {
     char *filename = NULL;
@@ -199,7 +219,6 @@ int main (int argc, char **argv)
     char *url = NULL;
     int mode = -1;
     int nbcomms = 0;
-    comm_t comm_list[MAXCOMMS] = {0};
 
     /* get basename */
     char *ptr = progname = argv[0];
@@ -332,95 +351,250 @@ int main (int argc, char **argv)
         TEST_CHARS (ptr, "\n\r", 1);
         *ptr++ = '\0';
 
-        /* clean line */
+        /* skip space, avoid empty line and comments */
         TEST_CHARS (line, " \t", 0);
         if ((*line == '\0') || (*line == '#')) {
             continue;
         }
 
-        /* analyse line */
-        mode = -1;
-        if (*line == 'R') {
-            mode = 0;
-        } else if (*line == 'T') {
-            mode = 1;
-        } else if (strncmp (line, "SLEEP", 5) == 0) {
+        /* special keywords */
+        if (strncmp (line, "SLEEP", 5) == 0) {
             int duration = atoi (line + 5);
             VERBOSE (morep, INFO, PRINTF ("sleep %dms\n", duration));
             usleep (duration * 1000);
             continue;
         }
+
+        /* analyse line */
+        mode = (*line == 'R') ? 0 : (*line == 'T') ? 1 : -1;
         if (mode == -1) {
             VERBOSE (morep, WARNING, PRINTF ("unrecognize line '%s'\n", line));
             continue;
         }
+        int offset = 1;
 
-        /* find ethertype */
         comm_t *comm = NULL;
-        int offset = 1;
-        int i;
-        for (i = 0; i < nbcomms; i++) {
-            comm_t *c = comm_list + i;
+        service_t serv = NULL;
+        /* find MOREP by service name */
+        for (int i = 0; ((service_list + i)->service_id != noserv_e) && (serv == NULL); i++) {
+            service_t *s = service_list + i;
+            VERBOSE (morep, TRACE, PRINTF ("test %c[%s]\n", *line, s->name));
+            if (strncmp (line + offset, s->name, strlen (s->name)) == 0) {
+                comm = mode ? &(s->rx) : &(s->tx);
+                serv = s->service_id;
+                offset += strlen (s->name);
+            }
+        }
+        /* find MOREP by ethertype */
+        for (int j = 0; (j < nbcomms) && (comm == NULL); i++) {
+            comm_t *c = comm_list + j;
             VERBOSE (morep, TRACE, PRINTF ("test %c[%s]\n", c->mode ? 'T' : 'R', c->etype));
             if ((strncmp (line + offset, c->etype, strlen (c->etype)) == 0) && (c->mode == mode)) {
                 comm = c;
+                for (int i = 0; ((service_list + i)->service_id != noserv_e) && (serv == NULL); i++) {
+                    service_t *s = service_list + i;
+                    c = mode ? &(s->rx) : &(s->tx);
+                    if (strncmp (c->etype, comm->etype, strlen (comm->etype)) == 0) {
+                        serv = s;
+                    }
+                }
                 offset += strlen (c->etype);
-                break;
             }
         }
-        if (comm == NULL) {
+        /* check media and service */
+        if ((comm == NULL) || (serv == NULL)) {
             VERBOSE (morep, TRACE, PRINTF ("no morep found '%s'\n", line));
             continue;
         }
-        VERBOSE (morep, DEBUG, PRINTF ("work with %c[%s]\n", comm->mode ? 'T' : 'R', comm->etype));
+        VERBOSE (morep, DEBUG, PRINTF ("work with %c[%s]\n", comm->mode ? 'T' : 'R', serv->name));
 
-        /* get values */
+        /* skip space */
         char *tmp = line + offset;
-        uint8_t msgtype;
         TEST_CHARS (tmp, " \t", 0);
-        if (strncmp (tmp, "MSG", 3) != 0) {
-            VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s' (%s)\n", line, tmp));
-            continue;
+        offset = tmp - line;
+
+        message_t *msg = NULL;
+        /* get message type by name */
+        for (int i = 0; ((message_list + i)->service_id != noserv_e) && (msg == NULL); i++) {
+            message_t *m = message_list + i;
+            VERBOSE (morep, TRACE, PRINT ("test %s\n", m->name));
+            if (strncmp (line + offset, m->name, strlen (m->name)) == 0) {
+                msg = m;
+                offset += strlen (m->name);
+            }
         }
-        tmp += 3;
-        TEST_CHARS (tmp, " \t=", 0);
-        msgtype = strtol (tmp, &tmp, 0);
-        if ((*tmp != ' ') && (*tmp != '\t')) {
-            VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s'\n", line));
-            continue;
+        /* get message type by id */
+        if (msg == NULL) {
+            if (strncmp (line + offset, "MSG", 3) != 0) {
+                VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s' (%d)\n", line, offset));
+                continue;
+            }
+            tmp = line + offset + 3;
+            TEST_CHARS (tmp, " \t=", 0);
+            uint8_t msgtype = strtol (tmp, &tmp, 0);
+            offset = tmp - line;
+            if ((*tmp != ' ') && (*tmp != '\t')) {
+                VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s' (%d)\n", line, offset));
+                continue;
+            }
         }
-    
-        RAW_DATA_t payload = {0};
-        if (parse_raw_data (tmp, &payload) != 0) {
-            VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s'\n", line));
+
+        /* check message and service */ 
+        if (serv->service_id != m->service_id) {
+            VERBOSE (morep, WARNING, PRINTF ("message %s is not allowed for service %S (line '%s')\n", msg->name, serv->name, line);
             continue;
         }
-        VERBOSE (morep, TRACE, PRINTF ("payload length: %d\n", payload.data_len));
 
-        /* transmit */
-        if (mode == 1) {
-            int seqnum = MOREP_Send (comm->morep, msgtype, payload.data, payload.data_len);
-            if (log) {
-                print_message (log, comm->etype, 1, msgtype, seqnum, payload.data, payload.data_len);
+        msg_channel CHANNEL_t = {0};
+        msg_clear_data CLEAR_DATA_t = {0};
+        msg_encrypted_data ENCRYPTED_DATA_t = {0};
+        msg_key KEY_t = {0};
+        msg_prng_param PRNG_PARAM_t = {0};
+        msg_raw_data RAW_DATA_t = {0};
+        msg_status STATUS_t = {0};
+        
+        int seqnum = -1;
+        if (mode == 1) { /* transmit */
+
+            /* parse message */
+            int rc = -1;
+            switch (serv->pdu) {
+            case channel_e:
+                rc = parse_channel (line + offset, &msg_channel);
+                break;
+            case clear_data_e:
+                rc = parse_clear_data (line + offset, &msg_clear_data);
+                break;
+            case encrypted_data_e:
+                rc = parse_encrypted_data (line + offset, &msg_encrypted_data);
+                break;
+            case key_e:
+                rc = parse_key (line + offset, &msg_key);
+                break;
+            case prng_param_e:
+                rc = parse_prng_param (line + offset, &msg_prng_param);
+                break;
+            case raw_data_e:
+                rc = parse_raw_data (line + offset, &msg_raw_data);
+                break;
+            case status_e:
+                rc = parse_status (line + offset, &msg_status);
+                break;
+            }
+            if (rc != 0) {
+                VERBOSE (morep, WARNING, PRINTF ("can't parse line '%s' (%d)\n", line, offset));
+                continue;
+            }
+
+            /* send message */
+            uint8_t payload[1496] = {0};
+            int len = -1;
+            switch (serv->pdu) {
+            case channel_e:
+                rc = serial_channel (&msg_channel, payload, sizeof (payload));
+                break;
+            case clear_data_e:
+                rc = serial_clear_data (&msg_clear_data, payload, sizeof (payload));
+                break;
+            case encrypted_data_e:
+                rc = serial_encrypted_data (&msg_encrypted_data, payload, sizeof (payload));
+                break;
+            case key_e:
+                rc = serial_key (&msg_key, payload, sizeof (payload));
+                break;
+            case prng_param_e:
+                rc = serial_prng_param (&msg_prng_param, payload, sizeof (payload));
+                break;
+            case raw_data_e:
+                rc = serial_raw_data (&msg_raw_data, payload, sizeof (payload));
+                break;
+            case status_e:
+                rc = serial_status (&msg_status, payload, sizeof (payload));
+                break;
             }
+            seqnum = MOREP_Send (comm->morep, msg->msgtype, payload, len);
+
         } else { /* receive */
+
             uint8_t rxmsgtype = 0;
-            uint8_t rxpayload[1496 * 16 - 1] = {0};
+            uint8_t rxpayload[1496] = {0};
             int rxlen = -1;
             int seqnum = MOREP_Receive (comm->morep, &rxmsgtype, rxpayload, &rxlen);
 
+            /* check pdu type */
+            pdu_t pdu = undef_pdu_e;
+            for (int i = 0; ((message_list + i)->service_id) && (pdu == undef_e); i++) {
+                message_t *m = message_list + i;
+                if ((m->service_id == serv->service_id) && (m->msgtype == rxmsgtype)) {
+                    pdu = m->pdu;
+                }
+            }
+
             /* check msg type */
             if (rxmsgtype != msgtype) {
-                VERBOSE (morep, WARNING, PRINTF ("R%sx SEQ=%d MSG=%d: expected msgtype %d\n", comm->etype, seqnum, rxmsgtype, msgtype));
+                VERBOSE (morep, WARNING, PRINTF ("R%sx SEQ=%d MSG=%d: expected msgtype %d\n", comm->etype, seqnum, rxmsgtype, msg->msgtype));
+            }
+
+            /* deserialize message */
+            int rc = -1;
+            switch (pdu) {
+            case channel_e:
+                rc = deserial_channel (rxpayload, rxlen, &msg_channel);
+                break;
+            case clear_data_e:
+                rc = deserial_clear_data (rxpayload, rxlen, &msg_clear_data);
+                break;
+            case encrypted_data_e:
+                rc = deserial_encrypted_data (rxpayload, rxlen, &msg_encrypted_data);
+                break;
+            case key_e:
+                rc = deserial_key (rxpayload, rxlen, &msg_key);
+                break;
+            case prng_param_e:
+                rc = deserial_prng_param (rxpayload, rxlen, &msg_prng_param);
+                break;
+            case raw_data_e:
+                rc = deserial_raw_data (rxpayload, rxlen, &msg_raw_data);
+                break;
+            case status_e:
+                rc = deserial_status (rxpayload, rxlen, &msg_status);
+                break;
+            }
+            if (rc != 0) {
+                VERBOSE (morep, WARNING, PRINTF ("can't deserialize message R%s[%02x]'\n", comm->etype, rxmsgtype));
+                continue;
             }
-            /* check payload */
-            else if ((rxlen != payload.data_len) ||
-                    ((memcmp (rxpayload, payload.data, rxlen) != 0))) {
-                VERBOSE (morep, WARNING, PRINTF ("R%s SEQ=%d MSG=%d: payloads differed %d/%d\n", comm->etype, seqnum, rxmsgtype, payload.data_len, rxlen));
+
+        }
+
+        /* log message */
+        if (log) {
+            fprintf (log, "%c%s[%s] SEG=%d MSG=%d LEN=%d %s ", mode ? 'T' : 'R', serv->name, comm->etype, seqnum, msg->msgtype, len, msg->name);
+            char * buffer[1496 * 3 + 256] = {0};
+            switch (serv->service_id) {
+            case channel_e:
+                rc = serial_channel (&msg_channel, buffer, sizeof (buffer));
+                break;
+            case clear_data_e:
+                rc = serial_clear_data (&msg_clear_data, buffer, sizeof (buffer));
+                break;
+            case encrypted_data_e:
+                rc = serial_encrypted_data (&msg_encrypted_data, buffer, sizeof (buffer));
+                break;
+            case key_e:
+                rc = serial_key (&msg_key, buffer, sizeof (buffer));
+                break;
+            case prng_param_e:
+                rc = serial_prng_param (&msg_prng_param, buffer, sizeof (buffer));
+                break;
+            case raw_data_e:
+                rc = serial_raw_data (&msg_raw_data, buffer, sizeof (buffer));
+                break;
+            case status_e:
+                rc = serial_status (&msg_status, buffer, sizeof (buffer));
+                break;
             }
-            if (log) {
-                print_message (log, comm->etype, 0, rxmsgtype, seqnum, rxpayload, rxlen);
-           }
+            fprintf (log, "%s\n", buffer);
         }
     }
 
@@ -436,11 +610,11 @@ int main (int argc, char **argv)
     return rc;
 }
 
-/* test: morep_valid.exe -h | grep usage */
-/* test: morep_valid.exe -r 2>&1 | grep 'url not specified' */
-/* test: morep_valid.exe -t 2>&1 | grep 'url not specified' */
-/* test: morep_valid.exe -l 2>&1 | grep 'log file not specified' */
-/* test: morep_valid.exe -l - -t lo://00:00:00:00:00:00/0808 -v 4 script-lo.eth */
-/* test: morep_valid.exe -l script.log -t lo://00:00:00:00:00:00/0808 -r lo://00:00:00:00:00:00/0808 script-lo.eth */
+/* test: morep_simulator.exe -h | grep usage */
+/* test: morep_simulator.exe -r 2>&1 | grep 'url not specified' */
+/* test: morep_simulator.exe -t 2>&1 | grep 'url not specified' */
+/* test: morep_simulator.exe -l 2>&1 | grep 'log file not specified' */
+/* test: morep_simulator.exe -l - -t lo://00:00:00:00:00:00/0808 -v 4 script-lo.eth */
+/* test: morep_simulator.exe -l script.log -t lo://00:00:00:00:00:00/0808 -r lo://00:00:00:00:00:00/0808 script-lo.eth */
 
 /* vim: set ts=4 sw=4 si et: */