diff options
Diffstat (limited to 'src/tools')
44 files changed, 1946 insertions, 577 deletions
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index b81e5439..7c40d9ae 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,5 +1,9 @@ add_subdirectory(irm) add_subdirectory(ocbr) add_subdirectory(oecho) +add_subdirectory(obc) add_subdirectory(oping) add_subdirectory(operf) +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_subdirectory(ovpn) +endif () diff --git a/src/tools/irm/CMakeLists.txt b/src/tools/irm/CMakeLists.txt index ca32e9c7..e5e5c466 100644 --- a/src/tools/irm/CMakeLists.txt +++ b/src/tools/irm/CMakeLists.txt @@ -23,8 +23,12 @@ set(SOURCE_FILES irm_unbind.c irm_bind.c irm_ipcp.c - irm_register.c - irm_unregister.c + irm_name.c + irm_name_create.c + irm_name_destroy.c + irm_name_reg.c + irm_name_unreg.c + irm_name_list.c irm_utils.c ) diff --git a/src/tools/irm/irm.c b/src/tools/irm/irm.c index bc4c2cd9..ba0f4713 100644 --- a/src/tools/irm/irm.c +++ b/src/tools/irm/irm.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * A tool to instruct the IRM daemon * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -49,8 +49,7 @@ static void usage(void) { printf("Usage: irm [OPERATION]\n\n" - "where OPERATION = {ipcp bind unbind\n" - " register unregister}\n"); + "where OPERATION in { ipcp bind unbind name }\n"); } static int do_help(int argc, @@ -70,8 +69,7 @@ static const struct cmd { { "ipcp", ipcp_cmd }, { "bind", bind_cmd }, { "unbind", unbind_cmd }, - { "register", do_register }, - { "unregister", do_unregister }, + { "name", name_cmd }, { "help", do_help }, { NULL, NULL } }; diff --git a/src/tools/irm/irm_bind.c b/src/tools/irm/irm_bind.c index 20a4e077..2e8b14ef 100644 --- a/src/tools/irm/irm_bind.c +++ b/src/tools/irm/irm_bind.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Bind names in the processing system * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -47,7 +47,7 @@ static void usage(void) { printf("Usage: irm bind [OPERATION]\n" "\n" - "where OPERATION = {program process ipcp help}\n"); + "where OPERATION in {program process ipcp help}\n"); } static int do_help(int argc, diff --git a/src/tools/irm/irm_bind_ipcp.c b/src/tools/irm/irm_bind_ipcp.c index a30b4192..7d5dd636 100644 --- a/src/tools/irm/irm_bind_ipcp.c +++ b/src/tools/irm/irm_bind_ipcp.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Bind IPCP Instance to a name * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,11 +55,11 @@ static void usage(void) int do_bind_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - char * name = NULL; - struct ipcp_info * ipcps; - ssize_t len; - ssize_t i; + char * ipcp = NULL; + char * name = NULL; + struct ipcp_list_info * ipcps; + ssize_t len; + ssize_t i; while (argc > 0) { if (matches(*argv, "name") == 0) { diff --git a/src/tools/irm/irm_bind_process.c b/src/tools/irm/irm_bind_process.c index dbab5c7f..fffd5fe9 100644 --- a/src/tools/irm/irm_bind_process.c +++ b/src/tools/irm/irm_bind_process.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Bind a process to a name * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/tools/irm/irm_bind_program.c b/src/tools/irm/irm_bind_program.c index a3d9e4ac..8a0dc33c 100644 --- a/src/tools/irm/irm_bind_program.c +++ b/src/tools/irm/irm_bind_program.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Bind programs to a name * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/tools/irm/irm_ipcp.c b/src/tools/irm/irm_ipcp.c index 72e32805..63e617d9 100644 --- a/src/tools/irm/irm_ipcp.c +++ b/src/tools/irm/irm_ipcp.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * A tool to instruct the IRM daemon * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,10 +44,11 @@ static void usage(void) { printf("Usage: irm ipcp [OPERATION]\n\n" - "where OPERATION = {create destroy\n" - " bootstrap enroll\n" - " connect disconnect\n" - " list help}\n"); + "where OPERATION in {create destroy\n" + " bootstrap enroll\n" + " connect disconnect\n" + " list\n" + " help}\n"); } static int do_help(int argc, char **argv) diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c index e1f75956..b8e5c54d 100644 --- a/src/tools/irm/irm_ipcp_bootstrap.c +++ b/src/tools/irm/irm_ipcp_bootstrap.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Bootstrap IPC Processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,12 +50,12 @@ #include <sys/socket.h> #endif -#define NORMAL "normal" +#define UNICAST "unicast" +#define BROADCAST "broadcast" #define UDP "udp" #define ETH_LLC "eth-llc" #define ETH_DIX "eth-dix" #define LOCAL "local" -#define RAPTOR "raptor" #define MD5 "MD5" #define SHA3_224 "SHA3_224" @@ -64,20 +64,22 @@ #define SHA3_512 "SHA3_512" #define DEFAULT_ADDR_SIZE 4 -#define DEFAULT_EID_SIZE 2 +#define DEFAULT_EID_SIZE 8 #define DEFAULT_DDNS 0 #define DEFAULT_TTL 60 #define DEFAULT_ADDR_AUTH ADDR_AUTH_FLAT_RANDOM #define DEFAULT_ROUTING ROUTING_LINK_STATE -#define DEFAULT_PFF PFF_SIMPLE +#define DEFAULT_CONG_AVOID CA_MB_ECN #define DEFAULT_HASH_ALGO DIR_HASH_SHA3_256 #define DEFAULT_ETHERTYPE 0xA000 +#define DEFAULT_UDP_PORT 0x0D6B /* 3435 */ #define FLAT_RANDOM_ADDR_AUTH "flat" #define LINK_STATE_ROUTING "link_state" #define LINK_STATE_LFA_ROUTING "lfa" -#define SIMPLE_PFF "simple" -#define ALTERNATE_PFF "alternate" +#define LINK_STATE_ECM_ROUTING "ecmp" +#define NONE_CA "none" +#define MB_ECN_CA "mb-ecn" static void usage(void) { @@ -86,76 +88,77 @@ static void usage(void) " name <ipcp name>\n" " layer <layer name>\n" " [type [TYPE]]\n" - "where TYPE = {" NORMAL " " LOCAL " " - UDP " " ETH_LLC " " ETH_DIX " " RAPTOR "},\n\n" - "if TYPE == " NORMAL "\n" + "where TYPE in {" UNICAST " " BROADCAST " " LOCAL " " + UDP " " ETH_LLC " " ETH_DIX "},\n\n" + "if TYPE == " UNICAST "\n" " [addr <address size> (default: %d)]\n" " [eid <eid size> (default: %d)]\n" " [ttl (max time-to-live value, default: %d)]\n" " [addr_auth <ADDRESS_POLICY> (default: %s)]\n" " [routing <ROUTING_POLICY> (default: %s)]\n" - " [pff [PFF_POLICY] (default: %s)]\n" + " [congestion <CONG_POLICY> (default: %s)]\n" " [hash [ALGORITHM] (default: %s)]\n" " [autobind]\n" - "where ADDRESS_POLICY = {"FLAT_RANDOM_ADDR_AUTH"}\n" - " ROUTING_POLICY = {"LINK_STATE_ROUTING " " - LINK_STATE_LFA_ROUTING "}\n" - " PFF_POLICY = {" SIMPLE_PFF " " ALTERNATE_PFF "}\n" - " ALGORITHM = {" SHA3_224 " " SHA3_256 " " + "where ADDRESS_POLICY in {" FLAT_RANDOM_ADDR_AUTH "}\n" + " ROUTING_POLICY in {" LINK_STATE_ROUTING " " + LINK_STATE_LFA_ROUTING " " LINK_STATE_ECM_ROUTING "}\n" + " CONG_POLICY in {" NONE_CA " " MB_ECN_CA "}\n" + " ALGORITHM in {" SHA3_224 " " SHA3_256 " " SHA3_384 " " SHA3_512 "}\n\n" "if TYPE == " UDP "\n" " ip <IP address in dotted notation>\n" + " [port <UDP port> (default: %d)]\n" " [dns <DDNS IP address in dotted notation>" " (default: none)]\n\n" "if TYPE == " ETH_LLC "\n" " dev <interface name>\n" " [hash [ALGORITHM] (default: %s)]\n" - "where ALGORITHM = {" SHA3_224 " " SHA3_256 " " + "where ALGORITHM in {" SHA3_224 " " SHA3_256 " " SHA3_384 " " SHA3_512 "}\n\n" "if TYPE == " ETH_DIX "\n" " dev <interface name>\n" " [ethertype <ethertype> (default: 0x%4X)]\n" " [hash [ALGORITHM] (default: %s)]\n" - "where ALGORITHM = {" SHA3_224 " " SHA3_256 " " + "where ALGORITHM in {" SHA3_224 " " SHA3_256 " " SHA3_384 " " SHA3_512 "}\n\n" "if TYPE == " LOCAL "\n" " [hash [ALGORITHM] (default: %s)]\n" - "where ALGORITHM = {" SHA3_224 " " SHA3_256 " " + "where ALGORITHM in {" SHA3_224 " " SHA3_256 " " SHA3_384 " " SHA3_512 "}\n\n" - "if TYPE == " RAPTOR "\n" - " [hash [ALGORITHM] (default: %s)]\n" - "where ALGORITHM = {" SHA3_224 " " SHA3_256 " " - SHA3_384 " " SHA3_512 "}\n\n", + "if TYPE == " BROADCAST "\n" + " [autobind]\n\n", DEFAULT_ADDR_SIZE, DEFAULT_EID_SIZE, DEFAULT_TTL, - FLAT_RANDOM_ADDR_AUTH, LINK_STATE_ROUTING, SIMPLE_PFF, - SHA3_256, SHA3_256, 0xA000, SHA3_256, SHA3_256, SHA3_256); + FLAT_RANDOM_ADDR_AUTH, LINK_STATE_ROUTING, MB_ECN_CA, + SHA3_256, DEFAULT_UDP_PORT, SHA3_256, 0xA000, SHA3_256, + SHA3_256); } int do_bootstrap_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - pid_t pid = -1; - struct ipcp_config conf; - uint8_t addr_size = DEFAULT_ADDR_SIZE; - uint8_t eid_size = DEFAULT_EID_SIZE; - uint8_t max_ttl = DEFAULT_TTL; - enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; - enum pol_routing routing_type = DEFAULT_ROUTING; - enum pol_pff pff_type = DEFAULT_PFF; - enum pol_dir_hash hash_algo = DEFAULT_HASH_ALGO; - uint32_t ip_addr = 0; - uint32_t dns_addr = DEFAULT_DDNS; - char * ipcp_type = NULL; - enum ipcp_type type = IPCP_INVALID; - char * layer = NULL; - char * dev = NULL; - uint16_t ethertype = DEFAULT_ETHERTYPE; - struct ipcp_info * ipcps; - ssize_t len = 0; - int i = 0; - bool autobind = false; - int cargs; + char * ipcp = NULL; + pid_t pid = -1; + struct ipcp_config conf; + uint8_t addr_size = DEFAULT_ADDR_SIZE; + uint8_t eid_size = DEFAULT_EID_SIZE; + uint8_t max_ttl = DEFAULT_TTL; + enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; + enum pol_routing routing_type = DEFAULT_ROUTING; + enum pol_dir_hash hash_algo = DEFAULT_HASH_ALGO; + enum pol_cong_avoid cong_avoid = DEFAULT_CONG_AVOID; + uint32_t ip_addr = 0; + uint32_t dns_addr = DEFAULT_DDNS; + char * ipcp_type = NULL; + enum ipcp_type type = IPCP_INVALID; + char * layer = NULL; + char * dev = NULL; + uint16_t ethertype = DEFAULT_ETHERTYPE; + struct ipcp_list_info * ipcps; + ssize_t len = 0; + int i = 0; + bool autobind = false; + int cargs; + int port = DEFAULT_UDP_PORT; while (argc > 0) { cargs = 2; @@ -190,7 +193,7 @@ int do_bootstrap_ipcp(int argc, ethertype = strtol(*(argv + 1), NULL, 0); else ethertype = strtol(*(argv + 1), NULL, 16); - if (ethertype < 0x0600 || ethertype == 0xFFFF) { + if (ethertype < 0x0600 || ethertype >= 0xFFFF) { printf("Invalid Ethertype: \"%s\".\n" "Recommended range: 0xA000-0xEFFF.\n", *(argv + 1)); @@ -202,6 +205,8 @@ int do_bootstrap_ipcp(int argc, eid_size = atoi(*(argv + 1)); } else if (matches(*argv, "ttl") == 0) { max_ttl = atoi(*(argv + 1)); + } else if (matches(*argv, "port") == 0) { + port = atoi(*(argv + 1)); } else if (matches(*argv, "autobind") == 0) { autobind = true; cargs = 1; @@ -216,13 +221,17 @@ int do_bootstrap_ipcp(int argc, else if (strcmp(LINK_STATE_LFA_ROUTING, *(argv + 1)) == 0) routing_type = ROUTING_LINK_STATE_LFA; + else if (strcmp(LINK_STATE_ECM_ROUTING, + *(argv + 1)) == 0) + routing_type = ROUTING_LINK_STATE_ECMP; else goto unknown_param; - } else if (matches(*argv, "pff") == 0) { - if (strcmp(SIMPLE_PFF, *(argv + 1)) == 0) - pff_type = PFF_SIMPLE; - else if (strcmp(ALTERNATE_PFF, *(argv + 1)) == 0) - pff_type = PFF_ALTERNATE; + } else if (matches(*argv, "congestion") == 0) { + if (strcmp(NONE_CA, *(argv + 1)) == 0) + cong_avoid = CA_NONE; + else if (strcmp(MB_ECN_CA, + *(argv + 1)) == 0) + cong_avoid = CA_MB_ECN; else goto unknown_param; } else { @@ -248,8 +257,10 @@ int do_bootstrap_ipcp(int argc, } if (ipcp_type != NULL) { - if (strcmp(ipcp_type, NORMAL) == 0) - type = IPCP_NORMAL; + if (strcmp(ipcp_type, UNICAST) == 0) + type = IPCP_UNICAST; + else if (strcmp(ipcp_type, BROADCAST) == 0) + type = IPCP_BROADCAST; else if (strcmp(ipcp_type, UDP) == 0) type = IPCP_UDP; else if (strcmp(ipcp_type, ETH_LLC) == 0) @@ -258,8 +269,6 @@ int do_bootstrap_ipcp(int argc, type = IPCP_ETH_DIX; else if (strcmp(ipcp_type, LOCAL) == 0) type = IPCP_LOCAL; - else if (strcmp(ipcp_type, RAPTOR) == 0) - type = IPCP_RAPTOR; else goto fail_usage; } @@ -283,47 +292,56 @@ int do_bootstrap_ipcp(int argc, printf("Types do not match.\n\n"); goto fail; } + conf.type = ipcps[i].type; - if (autobind && conf.type != IPCP_NORMAL) { - printf("Can only bind normal IPCPs, " - "autobind disabled.\n"); + if (autobind && (conf.type != IPCP_UNICAST && + conf.type != IPCP_BROADCAST)) { + printf("Can not bind this IPCP type," + "autobind disabled.\n\n"); autobind = false; } - strcpy(conf.layer_info.layer_name, layer); - if (conf.type != IPCP_UDP) - conf.layer_info.dir_hash_algo = hash_algo; + if (strlen(layer) > LAYER_NAME_SIZE) { + printf("Layer name too long.\n\n"); + goto fail_usage; + } + + strcpy(conf.layer_info.name, layer); + conf.layer_info.dir_hash_algo = hash_algo; switch (conf.type) { - case IPCP_NORMAL: - conf.addr_size = addr_size; - conf.eid_size = eid_size; - conf.max_ttl = max_ttl; - conf.addr_auth_type = addr_auth_type; - conf.routing_type = routing_type; - conf.pff_type = pff_type; + case IPCP_UNICAST: + conf.unicast.dt.addr_size = addr_size; + conf.unicast.dt.eid_size = eid_size; + conf.unicast.dt.max_ttl = max_ttl; + conf.unicast.dt.routing_type = routing_type; + conf.unicast.addr_auth_type = addr_auth_type; + conf.unicast.cong_avoid = cong_avoid; break; case IPCP_UDP: if (ip_addr == 0) goto fail_usage; - conf.ip_addr = ip_addr; - conf.dns_addr = dns_addr; + conf.udp.ip_addr = ip_addr; + conf.udp.dns_addr = dns_addr; + conf.udp.port = port; break; + case IPCP_ETH_DIX: + conf.eth.ethertype = ethertype; + /* FALLTHRU */ case IPCP_ETH_LLC: if (dev == NULL) goto fail_usage; - conf.dev = dev; - break; - case IPCP_ETH_DIX: - if (dev == NULL) + if (strlen(dev) > DEV_NAME_SIZE) { + printf("Device name too long.\n\n"); goto fail_usage; - conf.dev = dev; - conf.ethertype = ethertype; + } + + strcpy(conf.eth.dev, dev); break; - case IPCP_LOCAL: + case IPCP_BROADCAST: /* FALLTHRU */ - case IPCP_RAPTOR: + case IPCP_LOCAL: break; default: assert(false); diff --git a/src/tools/irm/irm_ipcp_connect.c b/src/tools/irm/irm_ipcp_connect.c index 42c07354..68e13bd0 100644 --- a/src/tools/irm/irm_ipcp_connect.c +++ b/src/tools/irm/irm_ipcp_connect.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * - * Connect components of normal IPC Processes + * Connect components of unicast or broadcast IPC processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ */ #include <ouroboros/irm.h> +#include <ouroboros/qos.h> #include "irm_ops.h" #include "irm_utils.h" @@ -45,28 +46,34 @@ #include <stdlib.h> #include <string.h> -#define DT "dt" -#define MGMT "mgmt" +#define DT "dt" +#define MGMT "mgmt" static void usage(void) { printf("Usage: irm ipcp connect\n" " name <ipcp name>\n" - " component [COMPONENT]\n" - " dst <name of destination IPCP>\n\n" - "where COMPONENT = {" DT " " MGMT "}\n"); + " dst <name of destination IPCP>\n" + " [component [COMPONENT]]\n" + "where COMPONENT in {" DT " " MGMT "}\n\n" + "if COMPONENT == " DT "\n" + " [qos [QOS]\n" + "where QOS in {raw, best, voice, video, data}\n"); } int do_connect_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - char * dst = NULL; - char * comp = NULL; - struct ipcp_info * ipcps; - ssize_t len = 0; - pid_t pid = -1; - ssize_t i; + char * ipcp = NULL; + char * dst = NULL; + char * comp = "*"; + char * component = NULL; + char * qos = NULL; + struct ipcp_list_info * ipcps; + ssize_t len = 0; + pid_t pid = -1; + ssize_t i; + qosspec_t qs = qos_raw; while (argc > 0) { if (matches(*argv, "name") == 0) { @@ -75,9 +82,11 @@ int do_connect_ipcp(int argc, dst = *(argv + 1); } else if (matches(*argv, "component") == 0) { comp = *(argv + 1); + } else if (matches(*argv, "qos") == 0) { + qos = *(argv + 1); } else { printf("\"%s\" is unknown, try \"irm " - "ipcpi connect\".\n", *argv); + "ipcp connect\".\n", *argv); return -1; } @@ -90,6 +99,21 @@ int do_connect_ipcp(int argc, return -1; } + if (qos != NULL) { + if (strcmp(qos, "best") == 0) + qs = qos_best_effort; + else if (strcmp(qos, "raw") == 0) + qs = qos_raw; + else if (strcmp(qos, "video") == 0) + qs = qos_video; + else if (strcmp(qos, "voice") == 0) + qs = qos_voice; + else if (strcmp(qos, "data") == 0) + qs = qos_data; + else + printf("Unknown QoS cube, defaulting to raw.\n"); + } + len = irm_list_ipcps(&ipcps); for (i = 0; i < len; i++) if (strcmp(ipcps[i].name, ipcp) == 0) @@ -100,14 +124,18 @@ int do_connect_ipcp(int argc, if (pid == -1) return -1; - if (!strcmp(comp, DT)) - comp = DT_COMP; - - if (!strcmp(comp , MGMT)) - comp = MGMT_COMP; + if (wildcard_match(comp, MGMT) == 0) { + component = MGMT_COMP; + /* FIXME: move to qos_data when stable */ + if (irm_connect_ipcp(pid, dst, component, qos_raw)) + return -1; + } - if (irm_connect_ipcp(pid, dst, comp)) - return -1; + if (wildcard_match(comp, DT) == 0) { + component = DT_COMP; + if (irm_connect_ipcp(pid, dst, component, qs)) + return -1; + } return 0; } diff --git a/src/tools/irm/irm_ipcp_create.c b/src/tools/irm/irm_ipcp_create.c index c8866962..35d33782 100644 --- a/src/tools/irm/irm_ipcp_create.c +++ b/src/tools/irm/irm_ipcp_create.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Create IPC Processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,29 +44,29 @@ #include "irm_ops.h" #include "irm_utils.h" -#define NORMAL "normal" -#define UDP "udp" -#define ETH_LLC "eth-llc" -#define ETH_DIX "eth-dix" -#define LOCAL "local" -#define RAPTOR "raptor" +#define UNICAST "unicast" +#define BROADCAST "broadcast" +#define UDP "udp" +#define ETH_LLC "eth-llc" +#define ETH_DIX "eth-dix" +#define LOCAL "local" static void usage(void) { printf("Usage: irm ipcp create\n" " name <ipcp name>\n" " type [TYPE]\n\n" - "where TYPE = {" NORMAL " " LOCAL " " - UDP " " ETH_LLC " " RAPTOR "}\n"); + "where TYPE in {" UNICAST " " BROADCAST " " LOCAL " " + UDP " " ETH_LLC " " ETH_DIX "}\n"); } int do_create_ipcp(int argc, char ** argv) { - char * ipcp_type = NULL; - char * ipcp_name = NULL; - enum ipcp_type type = 0; - pid_t pid; + char * ipcp_type = NULL; + char * ipcp_name = NULL; + enum ipcp_type type = 0; + pid_t pid; while (argc > 0) { if (matches(*argv, "type") == 0) { @@ -88,8 +88,10 @@ int do_create_ipcp(int argc, return -1; } - if (strcmp(ipcp_type, NORMAL) == 0) - type = IPCP_NORMAL; + if (strcmp(ipcp_type, UNICAST) == 0) + type = IPCP_UNICAST; + else if (strcmp(ipcp_type, BROADCAST) == 0) + type = IPCP_BROADCAST; else if (strcmp(ipcp_type, UDP) == 0) type = IPCP_UDP; else if (strcmp(ipcp_type, LOCAL) == 0) @@ -98,15 +100,14 @@ int do_create_ipcp(int argc, type = IPCP_ETH_LLC; else if (strcmp(ipcp_type, ETH_DIX) == 0) type = IPCP_ETH_DIX; - else if (strcmp(ipcp_type, RAPTOR) == 0) - type = IPCP_RAPTOR; else { + printf("IPCP type \"%s\" is unknown.\n", ipcp_type); usage(); return -1; } pid = irm_create_ipcp(ipcp_name, type); - if (pid <= 0) + if (pid < 0) return -1; return 0; diff --git a/src/tools/irm/irm_ipcp_destroy.c b/src/tools/irm/irm_ipcp_destroy.c index cb86b167..1a5e564e 100644 --- a/src/tools/irm/irm_ipcp_destroy.c +++ b/src/tools/irm/irm_ipcp_destroy.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Destroy IPC Processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,10 +55,10 @@ static void usage(void) int do_destroy_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - struct ipcp_info * ipcps; - ssize_t len; - int i; + char * ipcp = NULL; + struct ipcp_list_info * ipcps; + ssize_t len; + int i; while (argc > 0) { if (matches(*argv, "name") == 0) { @@ -89,6 +89,7 @@ int do_destroy_ipcp(int argc, break; } + free(ipcps); return 0; fail_destroy: diff --git a/src/tools/irm/irm_ipcp_disconnect.c b/src/tools/irm/irm_ipcp_disconnect.c index 73f1588d..7ce724e1 100644 --- a/src/tools/irm/irm_ipcp_disconnect.c +++ b/src/tools/irm/irm_ipcp_disconnect.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * - * Connect components of normal IPC Processes + * Connect components of unicast or broadcast IPC processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,28 +45,29 @@ #include <stdlib.h> #include <string.h> -#define DT "dt" -#define MGMT "mgmt" +#define DT "dt" +#define MGMT "mgmt" static void usage(void) { printf("Usage: irm ipcp disconnect\n" " name <ipcp name>\n" - " component [COMPONENT]\n" - " dst <name of destination IPCP>\n\n" - "where COMPONENT = {" DT " " MGMT "}\n"); + " dst <name of destination IPCP>\n" + " [component [COMPONENT]]\n\n" + "where COMPONENT in {" DT " " MGMT "}\n"); } int do_disconnect_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - char * dst = NULL; - char * comp = NULL; - struct ipcp_info * ipcps; - ssize_t len = 0; - pid_t pid = -1; - ssize_t i; + char * ipcp = NULL; + char * dst = NULL; + char * comp = "*"; + char * component = NULL; + struct ipcp_list_info * ipcps; + ssize_t len = 0; + pid_t pid = -1; + ssize_t i; while (argc > 0) { if (matches(*argv, "name") == 0) { @@ -77,7 +78,7 @@ int do_disconnect_ipcp(int argc, comp = *(argv + 1); } else { printf("\"%s\" is unknown, try \"irm " - "ipcpi connect\".\n", *argv); + "ipcp connect\".\n", *argv); return -1; } @@ -100,14 +101,17 @@ int do_disconnect_ipcp(int argc, if (pid == -1) return -1; - if (!strcmp(comp, DT)) - comp = DT_COMP; - - if (!strcmp(comp , MGMT)) - comp = MGMT_COMP; + if (wildcard_match(comp, DT) == 0) { + component = DT_COMP; + if (irm_disconnect_ipcp(pid, dst, component)) + return -1; + } - if (irm_disconnect_ipcp(pid, dst, comp)) - return -1; + if (wildcard_match(comp, MGMT) == 0) { + component = MGMT_COMP; + if (irm_disconnect_ipcp(pid, dst, component)) + return -1; + } return 0; } diff --git a/src/tools/irm/irm_ipcp_enroll.c b/src/tools/irm/irm_ipcp_enroll.c index c1628af6..86a22a71 100644 --- a/src/tools/irm/irm_ipcp_enroll.c +++ b/src/tools/irm/irm_ipcp_enroll.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Enroll IPC Processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -46,32 +46,65 @@ #include <string.h> +#define UNICAST "unicast" +#define BROADCAST "broadcast" + static void usage(void) { printf("Usage: irm ipcp enroll\n" " name <ipcp name>\n" - " layer <layer to enroll in>\n" - " [autobind]\n"); + " [layer <layer to enroll with>]\n" + " [dst <destination to enroll with>]\n" + " [type [TYPE], default = " UNICAST "]\n" + " [autobind]\n" + "where TYPE in {" UNICAST " " BROADCAST "}\n"); +} + +static int get_layer_name(const char * ipcp, + char * layer_name) +{ + struct ipcp_list_info * ipcps; + ssize_t len; + ssize_t i; + + len = irm_list_ipcps(&ipcps); + for (i = 0; i < len; i++) + if (strcmp(ipcps[i].name, ipcp) == 0) { + strcpy(layer_name, ipcps[i].layer); + free(ipcps); + return 0; + } + + free(ipcps); + + return -1; } int do_enroll_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - char * layer = NULL; - struct ipcp_info * ipcps; - pid_t pid = -1; - ssize_t len = 0; - int i = 0; - bool autobind = false; - int cargs; + char * ipcp = NULL; + char * layer = NULL; + char * dst = NULL; + struct ipcp_list_info * ipcps; + pid_t pid = -1; + ssize_t len = 0; + int i = 0; + bool autobind = false; + int cargs; + char * ipcp_type = UNICAST; + enum ipcp_type type = IPCP_INVALID; while (argc > 0) { cargs = 2; if (matches(*argv, "name") == 0) { ipcp = *(argv + 1); + } else if (matches(*argv, "type") == 0) { + ipcp_type = *(argv + 1); } else if (matches(*argv, "layer") == 0) { layer = *(argv + 1); + } else if (matches(*argv, "dst") == 0) { + dst = *(argv + 1); } else if (matches(*argv, "autobind") == 0) { autobind = true; cargs = 1; @@ -85,19 +118,27 @@ int do_enroll_ipcp(int argc, argv += cargs; } - if (layer == NULL || ipcp == NULL) { + if ((layer == NULL && dst == NULL) || ipcp == NULL) { usage(); return -1; } + if (dst == NULL) + dst = layer; + + if (strcmp(ipcp_type, UNICAST) == 0) + type = IPCP_UNICAST; + else if (strcmp(ipcp_type, BROADCAST) == 0) + type = IPCP_BROADCAST; + len = irm_list_ipcps(&ipcps); for (i = 0; i < len; i++) if (wildcard_match(ipcps[i].name, ipcp) == 0 && - ipcps[i].type == IPCP_NORMAL) + ipcps[i].type == type) pid = ipcps[i].pid; if (pid < 0) { - pid = irm_create_ipcp(ipcp, IPCP_NORMAL); + pid = irm_create_ipcp(ipcp, type); if (pid < 0) goto fail; free(ipcps); @@ -105,25 +146,39 @@ int do_enroll_ipcp(int argc, } for (i = 0; i < len; i++) { - if (ipcps[i].type != IPCP_NORMAL) + char enr_layer[LAYER_NAME_SIZE]; + if (ipcps[i].type != type) continue; - if (wildcard_match(ipcps[i].name, ipcp) == 0) { - pid = ipcps[i].pid; - if (autobind && irm_bind_process(pid, ipcp)) { - printf("Failed to bind %d to %s.\n", pid, ipcp); - goto fail; - } - - if (irm_enroll_ipcp(pid, layer)) { - if (autobind) - irm_unbind_process(pid, ipcp); - goto fail; - } - - if (autobind && irm_bind_process(pid, layer)) { - printf("Failed to bind %d to %s.\n", pid, layer); - goto fail; - } + + if (wildcard_match(ipcps[i].name, ipcp) != 0) + continue; + + pid = ipcps[i].pid; + + if (irm_enroll_ipcp(pid, dst)) { + printf("Failed to enroll IPCP.\n"); + goto fail; + } + + if (get_layer_name(ipcps[i].name, enr_layer)) { + printf("Could not get layer name.\n"); + goto fail; + } + + if (layer != NULL && strcmp(enr_layer, layer)) { + printf("Enrollment destination does not " + "match requested layer.\n"); + goto fail; + } + + if (autobind && irm_bind_process(pid, ipcp)) { + printf("Failed to bind %d to %s.\n", pid, ipcp); + goto fail; + } + + if (autobind && irm_bind_process(pid, enr_layer)) { + printf("Failed to bind %d to %s.\n", pid, enr_layer); + goto fail; } } diff --git a/src/tools/irm/irm_ipcp_list.c b/src/tools/irm/irm_ipcp_list.c index 5a9ecaff..dfa3099f 100644 --- a/src/tools/irm/irm_ipcp_list.c +++ b/src/tools/irm/irm_ipcp_list.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * - * Create IPC Processes + * List IPC Processes * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -46,12 +46,12 @@ #include <stdlib.h> #include <string.h> -#define NORMAL "normal" -#define UDP "udp" -#define ETH_LLC "eth-llc" -#define ETH_DIX "eth-dix" -#define LOCAL "local" -#define RAPTOR "raptor" +#define UNICAST "unicast" +#define BROADCAST "broadcast" +#define UDP "udp" +#define ETH_LLC "eth-llc" +#define ETH_DIX "eth-dix" +#define LOCAL "local" static void usage(void) { @@ -59,23 +59,23 @@ static void usage(void) " [name <ipcp name>]\n" " [layer <layer_name>]\n\n" " [type [TYPE]]\n\n" - "where TYPE = {" NORMAL " " LOCAL " " - UDP " " ETH_LLC " " ETH_DIX " " RAPTOR "}\n"); + "where TYPE = {" UNICAST " " LOCAL " " + UDP " " ETH_LLC " " ETH_DIX "}\n"); } static char * str_type(enum ipcp_type type) { switch(type) { - case IPCP_NORMAL: - return NORMAL; + case IPCP_UNICAST: + return UNICAST; + case IPCP_BROADCAST: + return BROADCAST; case IPCP_ETH_LLC: return ETH_LLC; case IPCP_ETH_DIX: return ETH_DIX; case IPCP_UDP: return UDP; - case IPCP_RAPTOR: - return RAPTOR; case IPCP_LOCAL: return LOCAL; default: @@ -86,12 +86,12 @@ static char * str_type(enum ipcp_type type) int do_list_ipcp(int argc, char ** argv) { - char * ipcp_type = NULL; - char * ipcp_name = NULL; - enum ipcp_type type = -1; - struct ipcp_info * ipcps; - ssize_t len; - ssize_t i; + char * ipcp_type = NULL; + char * ipcp_name = NULL; + enum ipcp_type type = -1; + struct ipcp_list_info * ipcps; + ssize_t len; + ssize_t i; while (argc > 0) { if (matches(*argv, "type") == 0) { @@ -109,8 +109,10 @@ int do_list_ipcp(int argc, } if (ipcp_type != NULL) { - if (strcmp(ipcp_type, NORMAL) == 0) - type = IPCP_NORMAL; + if (strcmp(ipcp_type, UNICAST) == 0) + type = IPCP_UNICAST; + else if (strcmp(ipcp_type, BROADCAST) == 0) + type = IPCP_BROADCAST; else if (strcmp(ipcp_type, UDP) == 0) type = IPCP_UDP; else if (strcmp(ipcp_type, LOCAL) == 0) @@ -119,8 +121,6 @@ int do_list_ipcp(int argc, type = IPCP_ETH_LLC; else if (strcmp(ipcp_type, ETH_DIX) == 0) type = IPCP_ETH_DIX; - else if (strcmp(ipcp_type, RAPTOR) == 0) - type = IPCP_RAPTOR; else { usage(); return -1; diff --git a/src/tools/irm/irm_name.c b/src/tools/irm/irm_name.c new file mode 100644 index 00000000..d60b6c78 --- /dev/null +++ b/src/tools/irm/irm_name.c @@ -0,0 +1,99 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * A tool to instruct the IRM daemon + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage(void) +{ + printf("Usage: irm name [OPERATION]\n\n" + "where OPERATION in {create destroy\n" + " register unregister\n" + " list\n" + " help}\n"); +} + +static int do_help(int argc, char **argv) +{ + (void) argc; + (void) argv; + + usage(); + return 0; +} + +static const struct cmd { + const char * cmd; + int (* func)(int argc, char ** argv); +} cmds[] = { + { "create", do_create_name }, + { "destroy", do_destroy_name }, + { "register", do_reg_name }, + { "unregister", do_unreg_name }, + { "list", do_list_name}, + { "help", do_help }, + { NULL, NULL } +}; + +static int do_cmd(const char * argv0, + int argc, + char ** argv) +{ + const struct cmd * c; + + for (c = cmds; c->cmd; ++c) { + if (matches(argv0, c->cmd) == 0) + return c->func(argc - 1, argv + 1); + } + + fprintf(stderr, "\"%s\" is unknown, try \"irm ipcp help\".\n", argv0); + + return -1; +} + +int name_cmd(int argc, char ** argv) +{ + if (argc < 1) { + usage(); + return -1; + } + + return do_cmd(argv[0], argc, argv); +} diff --git a/src/tools/irm/irm_name_create.c b/src/tools/irm/irm_name_create.c new file mode 100644 index 00000000..a0079cad --- /dev/null +++ b/src/tools/irm/irm_name_create.c @@ -0,0 +1,96 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * Create IPC Processes + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <ouroboros/irm.h> + +#include <stdio.h> +#include <string.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +#define RR "round-robin" +#define SPILL "spillover" + +static void usage(void) +{ + printf("Usage: irm name create\n" + " <name>\n" + " lb [LB_POLICY], default: %s\n\n" + "where LB_POLICY in {" RR " " SPILL "}\n", RR); +} + +int do_create_name(int argc, + char ** argv) +{ + char * name = NULL; + char * lb_pol = RR; + enum pol_balance pol_lb = LB_RR; + + name = *(argv++); + --argc; + + while (argc > 0) { + if (matches(*argv, "lb") == 0) { + lb_pol = *(argv + 1); + } else { + printf("\"%s\" is unknown, try \"irm " + "name create\".\n", *argv); + return -1; + } + + argc -= 2; + argv += 2; + } + + if (name == NULL) { + usage(); + return -1; + } + + if (strcmp(lb_pol, RR) == 0) + pol_lb = LB_RR; + else if (strcmp(lb_pol, SPILL) == 0) + pol_lb = LB_SPILL; + else { + usage(); + return -1; + } + + return irm_create_name(name, pol_lb); +} diff --git a/src/tools/irm/irm_name_destroy.c b/src/tools/irm/irm_name_destroy.c new file mode 100644 index 00000000..d4bd6c82 --- /dev/null +++ b/src/tools/irm/irm_name_destroy.c @@ -0,0 +1,72 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * Create IPC Processes + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <ouroboros/irm.h> + +#include <stdio.h> +#include <string.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage(void) +{ + printf("Usage: irm name destroy <name>\n"); +} + +int do_destroy_name(int argc, + char ** argv) +{ + char * name = NULL; + + name = *(argv++); + --argc; + + if (argc > 0) { + printf("\"%s\" is unknown, try \"irm " + "name destroy\".\n", *argv); + return -1; + } + + if (name == NULL) { + usage(); + return -1; + } + + return irm_destroy_name(name); +} diff --git a/src/tools/irm/irm_name_list.c b/src/tools/irm/irm_name_list.c new file mode 100644 index 00000000..a807008c --- /dev/null +++ b/src/tools/irm/irm_name_list.c @@ -0,0 +1,115 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * List names + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <ouroboros/irm.h> +#include <ouroboros/errno.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define RR "round-robin" +#define SPILL "spillover" + +static char * str_pol(enum pol_balance p) +{ + switch(p) { + case LB_RR: + return RR; + case LB_SPILL: + return SPILL; + default: + return "UNKNOWN"; + } +}; + +int do_list_name(int argc, + char ** argv) +{ + char * name = NULL; + struct name_info * names; + ssize_t len; + ssize_t i; + + while (argc > 0) { + if (matches(*argv, "list") == 0) { + name = *(argv + 1); + } else { + printf("\"%s\" is unknown, try \"irm " + "name list.\n", *argv); + return -1; + } + + argc -= 2; + argv += 2; + } + + len = irm_list_names(&names); + if (len == 0) { + printf("No names in system.\n\n"); + return 0; + } else if (len == -EIRMD) { + printf("Failed to communicate with the " + "Ouroboros IPC Resource Manager daemon.\n"); + return -1; + } else if (len < 0) + return len; + + printf("+----------------------------------------------------" + "+----------------------+\n"); + printf("| %50s | %20s |\n", "name", "load-balance policy"); + printf("+----------------------------------------------------" + "+----------------------+\n"); + + for (i = 0; i < len; i++) { + if (name != NULL && matches(names[i].name, name)) + continue; + printf("| %50s | %20s |\n", + names[i].name, + str_pol(names[i].pol_lb)); + } + printf("+----------------------------------------------------" + "+----------------------+\n"); + + free(names); + + return 0; +} diff --git a/src/tools/irm/irm_register.c b/src/tools/irm/irm_name_reg.c index 23c65f7d..061ed8be 100644 --- a/src/tools/irm/irm_register.c +++ b/src/tools/irm/irm_name_reg.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * - * Register names in IPCPs + * Register names with IPCPs * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,7 +38,6 @@ #include <ouroboros/irm.h> - #include "irm_ops.h" #include "irm_utils.h" @@ -51,8 +50,7 @@ static void usage(void) { - printf("Usage: irm register\n" - " name <name>\n" + printf("Usage: irm name register <name>\n" " ipcp <ipcp to register with>\n" " [ipcp <ipcp to register with>]\n" " [... (maximum %d ipcps)]\n" @@ -63,23 +61,26 @@ static void usage(void) } -int do_register(int argc, +int do_reg_name(int argc, char ** argv) { - char * name = NULL; - char * layers[MAX_LAYERS]; - size_t layers_len = 0; - char * ipcp[MAX_IPCPS]; - size_t ipcp_len = 0; - struct ipcp_info * ipcps; - ssize_t len; - ssize_t i; - + char * name = NULL; + char * layers[MAX_LAYERS]; + size_t layers_len = 0; + char * ipcp[MAX_IPCPS]; + size_t ipcp_len = 0; + struct ipcp_list_info * ipcps; + ssize_t ipcps_len; + struct name_info * names; + ssize_t names_len; + bool name_create = true; + ssize_t i; + + name = *(argv++); + --argc; while (argc > 0) { - if (matches(*argv, "name") == 0) { - name = *(argv + 1); - } else if (matches(*argv, "layer") == 0) { + if (matches(*argv, "layer") == 0) { layers[layers_len++] = *(argv + 1); if (layers_len > MAX_LAYERS) { printf("Too many layers specified.\n"); @@ -92,7 +93,7 @@ int do_register(int argc, return -1; } } else { - printf("\"%s\" is unknown, try \"irm " + printf("\"%s\" is unknown, try \"irm name " "register\".\n", *argv); return -1; } @@ -106,33 +107,54 @@ int do_register(int argc, return -1; } - len = irm_list_ipcps(&ipcps); - if (len < 0) - return len; + ipcps_len = irm_list_ipcps(&ipcps); + if (ipcps_len < 0) + return ipcps_len; + + names_len = irm_list_names(&names); + if (names_len < 0) { + free(ipcps); + return names_len; + } + + for (i = 0; i < names_len; ++i) { + if (strcmp(names[i].name, name) == 0) { + name_create = false; + break; + } + } + + if (name_create && irm_create_name(name, LB_SPILL)) { + printf("Error creating name."); + free(ipcps); + free(name); + return -1; + } - for (i = 0; i < len; ++i) { + for (i = 0; i < ipcps_len; ++i) { size_t j; for (j = 0; j < layers_len; j++) { - if (wildcard_match(ipcps[i].layer, layers[j]) == 0) { - if (irm_reg(ipcps[i].pid, name)) { + if (wildcard_match(layers[j], ipcps[i].layer) == 0) { + if (irm_reg_name(name, ipcps[i].pid)) { free(ipcps); + free(names); return -1; } - break; } } for (j = 0; j < ipcp_len; j++) { - if (wildcard_match(ipcps[i].name, ipcp[j]) == 0) { - if (irm_reg(ipcps[i].pid, name)) { + if (wildcard_match(ipcp[j], ipcps[i].name) == 0) { + if (irm_reg_name(name, ipcps[i].pid)) { free(ipcps); + free(names); return -1; } - break; } } } free(ipcps); + free(names); return 0; } diff --git a/src/tools/irm/irm_unregister.c b/src/tools/irm/irm_name_unreg.c index 52491b42..6e579f04 100644 --- a/src/tools/irm/irm_unregister.c +++ b/src/tools/irm/irm_name_unreg.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Unregister names from IPCPs * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,8 +50,7 @@ static void usage(void) { - printf("Usage: irm unregister\n" - " name <name>\n" + printf("Usage: irm name unregister <name>\n" " ipcp <ipcp to register with>\n" " [ipcp <ipcp to register with>]\n" " [... (maximum %d ipcps)]\n" @@ -61,21 +60,23 @@ static void usage(void) , MAX_IPCPS, MAX_LAYERS); } -int do_unregister(int argc, char ** argv) +int do_unreg_name(int argc, + char ** argv) { - char * name = NULL; - char * layers[MAX_LAYERS]; - size_t layers_len = 0; - char * ipcp[MAX_IPCPS]; - size_t ipcp_len = 0; - struct ipcp_info * ipcps; - size_t len; - size_t i; + char * name = NULL; + char * layers[MAX_LAYERS]; + size_t layers_len = 0; + char * ipcp[MAX_IPCPS]; + size_t ipcp_len = 0; + struct ipcp_list_info * ipcps; + ssize_t len; + size_t i; + + name = *(argv++); + --argc; while (argc > 0) { - if (matches(*argv, "name") == 0) { - name = *(argv + 1); - } else if (matches(*argv, "layer") == 0) { + if (matches(*argv, "layer") == 0) { layers[layers_len++] = *(argv + 1); if (layers_len > MAX_LAYERS) { printf("Too many layers specified.\n"); @@ -103,11 +104,14 @@ int do_unregister(int argc, char ** argv) } len = irm_list_ipcps(&ipcps); - for (i = 0; i < len; ++i) { + if (len < 0) + return -1; + + for (i = 0; i < (size_t) len; ++i) { size_t j; for (j = 0; j < layers_len; j++) { if (wildcard_match(ipcps[i].layer, layers[j]) == 0) { - if (irm_unreg(ipcps[i].pid, name)) { + if (irm_unreg_name(name, ipcps[i].pid)) { free(ipcps); return -1; } @@ -116,7 +120,7 @@ int do_unregister(int argc, char ** argv) } for (j = 0; j < ipcp_len; j++) { if (wildcard_match(ipcps[i].name, ipcp[j]) == 0) { - if (irm_unreg(ipcps[i].pid, name)) { + if (irm_unreg_name(name, ipcps[i].pid)) { free(ipcps); return -1; } diff --git a/src/tools/irm/irm_ops.h b/src/tools/irm/irm_ops.h index 74035434..e04ffc02 100644 --- a/src/tools/irm/irm_ops.h +++ b/src/tools/irm/irm_ops.h @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Functions of the IRM tool that are one level deep * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -84,8 +84,20 @@ int do_unbind_process(int argc, int do_unbind_ipcp(int argc, char ** argv); -int do_register(int argc, +int name_cmd(int argc, + char ** argv); + +int do_create_name(int argc, + char ** argv); + +int do_destroy_name(int argc, + char ** argv); + +int do_reg_name(int argc, char ** argv); -int do_unregister(int argc, +int do_unreg_name(int argc, char ** argv); + +int do_list_name(int argc, + char ** argv); diff --git a/src/tools/irm/irm_unbind.c b/src/tools/irm/irm_unbind.c index f7b078f8..d6594d01 100644 --- a/src/tools/irm/irm_unbind.c +++ b/src/tools/irm/irm_unbind.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Unbind names in the processing system * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -47,7 +47,7 @@ static void usage(void) { printf("Usage: irm unbind [OPERATION]\n" "\n" - "where OPERATION = {program process ipcp help}\n"); + "where OPERATION in {program process ipcp help}\n"); } static int do_help(int argc, diff --git a/src/tools/irm/irm_unbind_ipcp.c b/src/tools/irm/irm_unbind_ipcp.c index 9b2a930a..53a2d16c 100644 --- a/src/tools/irm/irm_unbind_ipcp.c +++ b/src/tools/irm/irm_unbind_ipcp.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Unbind name from IPCP Instance * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,11 +57,11 @@ static void usage(void) int do_unbind_ipcp(int argc, char ** argv) { - char * ipcp = NULL; - char * name = NULL; - struct ipcp_info * ipcps; - ssize_t len; - ssize_t i; + char * ipcp = NULL; + char * name = NULL; + struct ipcp_list_info * ipcps; + ssize_t len; + ssize_t i; while (argc > 0) { if (matches(*argv, "name") == 0) { diff --git a/src/tools/irm/irm_unbind_process.c b/src/tools/irm/irm_unbind_process.c index 7a1c495d..264ed538 100644 --- a/src/tools/irm/irm_unbind_process.c +++ b/src/tools/irm/irm_unbind_process.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Unbind process names * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/tools/irm/irm_unbind_program.c b/src/tools/irm/irm_unbind_program.c index 47cf9255..0c751e80 100644 --- a/src/tools/irm/irm_unbind_program.c +++ b/src/tools/irm/irm_unbind_program.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Unbind programs * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/tools/irm/irm_utils.c b/src/tools/irm/irm_utils.c index c5ea9246..9694d647 100644 --- a/src/tools/irm/irm_utils.c +++ b/src/tools/irm/irm_utils.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Handy helper functions for the IRM tool * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -109,7 +109,7 @@ int wildcard_match(const char * pattern, return 0; /* General case, use recursion. */ - while ((c = *string) != '\0') { + while (*string != '\0') { if (!wildcard_match(pattern, string)) return 0; ++string; diff --git a/src/tools/irm/irm_utils.h b/src/tools/irm/irm_utils.h index 03113f12..27a0b941 100644 --- a/src/tools/irm/irm_utils.h +++ b/src/tools/irm/irm_utils.h @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Handy helper functions for the IRM tool * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/tools/obc/CMakeLists.txt b/src/tools/obc/CMakeLists.txt new file mode 100644 index 00000000..db5e999b --- /dev/null +++ b/src/tools/obc/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_BINARY_DIR}/include) + +set(SOURCE_FILES + # Add source files here + obc.c + ) + +add_executable(obc ${SOURCE_FILES}) + +target_link_libraries(obc LINK_PUBLIC ouroboros-dev) + +install(TARGETS obc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/tools/obc/obc.c b/src/tools/obc/obc.c new file mode 100644 index 00000000..462cbea9 --- /dev/null +++ b/src/tools/obc/obc.c @@ -0,0 +1,155 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * A simple broadcast application + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _POSIX_C_SOURCE 199309L + +#include <ouroboros/dev.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define BUF_SIZE 256 + +static void usage(void) +{ + printf("Usage: obc [OPTION]...\n" + "Sends a message to a broadcast network\n\n" + " -n --name Name of the broadcast layer\n" + " -m --message A message to send\n" + " [-l, --listen Listen mode]\n" + " --help Display this help text and exit\n"); +} + +static int reader_main(const char * dst) +{ + int fd; + char buf[BUF_SIZE]; + + printf("Starting a reader.\n"); + + fd = flow_join(dst, NULL, NULL); + if (fd < 0) { + printf("Failed to join broadcast.\n"); + return -1; + } + + printf("New flow.\n"); + + while (true) { + ssize_t count = flow_read(fd, &buf, BUF_SIZE); + if (count < 0) { + printf("Failed to read.\n"); + flow_dealloc(fd); + break; + } + + printf("Message is %.*s.\n", (int) count, buf); + } + + return 0; +} + +static int writer_main(const char * dst, + const char * message) +{ + int fd = 0; + size_t len = strlen(message) + 1; + + fd = flow_join(dst, NULL, NULL); + if (fd < 0) { + printf("Failed to join broadcast.\n"); + return -1; + } + + if (flow_write(fd, message, len) < 0) { + printf("Failed to write packet.\n"); + flow_dealloc(fd); + return -1; + } + + flow_dealloc(fd); + + return 0; +} + +int main(int argc, + char ** argv) +{ + int ret = -1; + bool reader = false; + char * name = NULL; + char * msg = "Ouroboros multicast rocks!"; + + argc--; + argv++; + while (argc > 0) { + if (strcmp(*argv, "-l") == 0 || + strcmp(*argv, "--listen") == 0) { + reader = true; + } else if (strcmp(*argv, "-n") == 0 || + strcmp(*argv, "--name") == 0) { + name = *(argv + 1); + argc--; + argv++; + } else if (strcmp(*argv, "-m") == 0 || + strcmp(*argv, "--message") == 0) { + msg = *(argv + 1); + argc--; + argv++; + } else { + usage(); + return 0; + } + argc--; + argv++; + } + + if (name == NULL) { + printf("Please specify a name.\n\n"); + usage(); + exit(EXIT_FAILURE); + } + + if (reader) + ret = reader_main(name); + else + ret = writer_main(name, msg); + + return ret; +} diff --git a/src/tools/ocbr/CMakeLists.txt b/src/tools/ocbr/CMakeLists.txt index 5dac3e63..f7ba66cd 100644 --- a/src/tools/ocbr/CMakeLists.txt +++ b/src/tools/ocbr/CMakeLists.txt @@ -4,6 +4,11 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) +get_filename_component(CURRENT_SOURCE_PARENT_DIR + ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + +include_directories(${CURRENT_SOURCE_PARENT_DIR}) + set(SOURCE_FILES # Add source files here ocbr.c diff --git a/src/tools/ocbr/ocbr.c b/src/tools/ocbr/ocbr.c index e2bd84af..775bcaac 100644 --- a/src/tools/ocbr/ocbr.c +++ b/src/tools/ocbr/ocbr.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * CBR traffic generator * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,6 +39,8 @@ #define _POSIX_C_SOURCE 199506L #define __XSI_VISIBLE 500 +#include "time_utils.h" + #include <stdio.h> #include <string.h> #include <sys/time.h> @@ -60,7 +62,7 @@ struct s { static void usage(void) { printf("Usage: cbr [OPTION]...\n" - "Sends SDUs from client to server at a constant bit rate.\n\n" + "Sends packets from client to server at a constant bit rate.\n\n" " -l, --listen Run in server mode\n" "\n" "Server options:\n" @@ -70,10 +72,11 @@ static void usage(void) "Client options:\n" " -n, --server_apn Specify the name of the server.\n" " -d, --duration Duration for sending (s)\n" - " -f, --flood Send SDUs as fast as possible\n" - " -s, --size SDU size (B, max %ld B)\n" + " -f, --flood Send packets as fast as possible\n" + " -s, --size packet size (B, max %ld B)\n" " -r, --rate Rate (b/s)\n" - " --sleep Sleep in between sending SDUs\n" + " --sleep Sleep in between sending packets\n" + " --spin Spin CPU between sending packets\n" "\n\n" " --help Display this help text and exit\n", BUF_SIZE); @@ -82,10 +85,10 @@ static void usage(void) int main(int argc, char ** argv) { int duration = 60; /* One minute test */ - int size = 1000; /* 1000 byte SDUs */ + int size = 1000; /* 1000 byte packets */ long rate = 1000000; /* 1 Mb/s */ bool flood = false; - bool sleep = false; + bool sleep = true; int ret = 0; char * rem = NULL; char * s_apn = NULL; @@ -136,6 +139,8 @@ int main(int argc, char ** argv) flood = true; } else if (strcmp(*argv, "--sleep") == 0) { sleep = true; + } else if (strcmp(*argv, "--spin") == 0) { + sleep = false; } else { usage(); return 0; @@ -150,17 +155,22 @@ int main(int argc, char ** argv) if (s_apn == NULL) { printf("No server specified.\n"); usage(); - return 0; + return 1; } if (size > BUF_SIZE) { printf("Maximum size: %ld.\n", BUF_SIZE); - return 0; + return 1; } if (size < 0) { printf("Size overflow.\n"); - return 0; + return 1; + } + + if (rate <= 0) { + printf("Invalid rate.\n"); + return 1; } ret = client_main(s_apn, duration, size, rate, flood, sleep); diff --git a/src/tools/ocbr/ocbr_client.c b/src/tools/ocbr/ocbr_client.c index 026ab001..ba7b41f4 100644 --- a/src/tools/ocbr/ocbr_client.c +++ b/src/tools/ocbr/ocbr_client.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * A simple CBR generator * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,6 @@ */ #include <ouroboros/dev.h> -#include <ouroboros/time_utils.h> #include <signal.h> @@ -136,7 +135,7 @@ int client_main(char * server, } else { /* flood */ while (!stop) { clock_gettime(CLOCK_REALTIME, &end); - if (flow_write(fd, buf, (size_t) size) < 0) { + if (flow_write(fd, buf, size) < 0) { stop = true; continue; } @@ -155,7 +154,7 @@ int client_main(char * server, ms = ts_diff_ms(&start, &end); printf("sent statistics: " - "%9ld SDUs, %12ld bytes in %9d ms, %4.4f Mb/s\n", + "%9ld packets, %12ld bytes in %9d ms, %4.4f Mb/s\n", seqnr, seqnr * size, ms, (seqnr / (ms * 1000.0)) * size * 8.0); flow_dealloc(fd); diff --git a/src/tools/ocbr/ocbr_server.c b/src/tools/ocbr/ocbr_server.c index 4f080eff..a4bbadd4 100644 --- a/src/tools/ocbr/ocbr_server.c +++ b/src/tools/ocbr/ocbr_server.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * A simple CBR generator * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,6 @@ */ #include <ouroboros/dev.h> -#include <ouroboros/time_utils.h> #include <ouroboros/fccntl.h> #include <stdbool.h> @@ -84,14 +83,15 @@ static void handle_flow(int fd) struct timespec now; struct timespec alive; struct timespec intv = {server_settings.interval, 0}; + struct timespec tic = {0, 100 * MILLION}; struct timespec iv_start; struct timespec iv_end; bool stop = false; - long sdus = 0; - long sdus_intv = 0; + long packets = 0; + long packets_intv = 0; long bytes_read = 0; long bytes_read_intv = 0; @@ -100,7 +100,8 @@ static void handle_flow(int fd) alive = iv_start; ts_add(&iv_start, &intv, &iv_end); - fccntl(fd, FLOWSFLAGS, FLOWFRNOBLOCK | FLOWFRDWR | FLOWFRNOPART); + fccntl(fd, FLOWSFLAGS, FLOWFRDWR | FLOWFRNOPART); + fccntl(fd, FLOWSRCVTIMEO, &tic); while (!stop) { clock_gettime(CLOCK_REALTIME, &now); @@ -109,7 +110,7 @@ static void handle_flow(int fd) if (count > 0) { clock_gettime(CLOCK_REALTIME, &alive); - sdus++; + packets++; bytes_read += count; } @@ -121,17 +122,18 @@ static void handle_flow(int fd) if (stop || ts_diff_ms(&now, &iv_end) < 0) { long us = ts_diff_us(&iv_start, &now); - printf("Flow %4d: %9ld SDUs (%12ld bytes) in %9ld ms" - " => %9.4f p/s, %9.4f Mb/s\n", + printf("Flow %4d: %9ld packets (%12ld bytes) in %9ld ms" + " => %9.4f pps, %9.4f Mbps\n", fd, - sdus - sdus_intv, + packets - packets_intv, bytes_read - bytes_read_intv, us / 1000, - ((sdus - sdus_intv) / (double) us) * MILLION, + ((packets - packets_intv) / (double) us) + * MILLION, 8 * ((bytes_read - bytes_read_intv) / (double)(us))); iv_start = iv_end; - sdus_intv = sdus; + packets_intv = packets; bytes_read_intv = bytes_read; ts_add(&iv_start, &intv, &iv_end); } @@ -140,6 +142,11 @@ static void handle_flow(int fd) flow_dealloc(fd); } +static void __cleanup_mutex_unlock(void * mutex) +{ + pthread_mutex_unlock((pthread_mutex_t *) mutex); +} + static void * worker(void * o) { int cli_fd; @@ -148,8 +155,7 @@ static void * worker(void * o) while (true) { pthread_mutex_lock(&fds_lock); - pthread_cleanup_push((void(*)(void *)) pthread_mutex_unlock, - (void *) &fds_lock); + pthread_cleanup_push(__cleanup_mutex_unlock, &fds_lock); while (fds[fds_index] == -1) pthread_cond_wait(&fds_signal, &fds_lock); @@ -182,8 +188,7 @@ static void * listener(void * o) while (true) { pthread_mutex_lock(&fds_lock); - pthread_cleanup_push((void(*)(void *)) pthread_mutex_unlock, - (void *) &fds_lock); + pthread_cleanup_push(__cleanup_mutex_unlock, &fds_lock); while (fds_count == THREADS_SIZE) { printf("Can't accept any more flows, waiting.\n"); diff --git a/src/tools/oecho/oecho.c b/src/tools/oecho/oecho.c index cc173988..d5d03027 100644 --- a/src/tools/oecho/oecho.c +++ b/src/tools/oecho/oecho.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * A simple echo application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -72,15 +72,15 @@ static int server_main(void) count = flow_read(fd, &buf, BUF_SIZE); if (count < 0) { - printf("Failed to read SDU.\n"); + printf("Failed to read packet.\n"); flow_dealloc(fd); continue; } printf("Message from client is %.*s.\n", (int) count, buf); - if (flow_write(fd, buf, count) == -1) { - printf("Failed to write SDU.\n"); + if (flow_write(fd, buf, count) < 0) { + printf("Failed to write packet.\n"); flow_dealloc(fd); continue; } @@ -93,10 +93,10 @@ static int server_main(void) static int client_main(void) { - int fd = 0; + int fd; char buf[BUF_SIZE]; char * message = "Client says hi!"; - ssize_t count = 0; + ssize_t count; fd = flow_alloc("oecho", NULL, NULL); if (fd < 0) { @@ -105,14 +105,14 @@ static int client_main(void) } if (flow_write(fd, message, strlen(message) + 1) < 0) { - printf("Failed to write SDU.\n"); + printf("Failed to write packet.\n"); flow_dealloc(fd); return -1; } count = flow_read(fd, buf, BUF_SIZE); if (count < 0) { - printf("Failed to read SDU.\n"); + printf("Failed to read packet.\n"); flow_dealloc(fd); return -1; } diff --git a/src/tools/operf/operf.c b/src/tools/operf/operf.c index fe387724..10896bd5 100644 --- a/src/tools/operf/operf.c +++ b/src/tools/operf/operf.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros perf application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,19 +62,32 @@ #define OPERF_MAX_FLOWS 256 +#define TEST_TYPE_UNI 0 +#define TEST_TYPE_BI 1 + +struct conf { + uint32_t test_type; +} __attribute__((packed)); + +struct msg { + uint32_t id; +} __attribute__((packed)); + struct c { - char * s_apn; - int size; + char * server_name; long rate; bool flood; bool sleep; int duration; + int size; unsigned long sent; unsigned long rcvd; pthread_t reader_pt; pthread_t writer_pt; + + struct conf conf; } client; struct s { @@ -82,6 +95,7 @@ struct s { fset_t * flows; fqueue_t * fq; pthread_mutex_t lock; + struct conf conf[OPERF_MAX_FLOWS]; uint8_t buffer[OPERF_BUF_SIZE]; ssize_t timeout; @@ -99,26 +113,62 @@ static void usage(void) printf("Usage: operf [OPTION]...\n" "Measures bandwidth between a client and a server\n" " -l, --listen Run in server mode\n" - "\n" - " -n, --server-apn Name of the operf server\n" - " -d, --duration Test duration (s, default 60)\n" + " -t, --test The type of test [uni, bi]" + " (default uni)\n" + " -n, --server-name Name of the operf server\n" + " -d, --duration Test duration (default 60s)\n" " -r, --rate Rate (b/s)\n" " -s, --size Payload size (B, default 1500)\n" - " -f, --flood Send SDUs as fast as possible\n" - " --sleep Sleep in between sending SDUs\n" + " -f, --flood Send packets as fast as possible\n" + " --sleep Sleep in between sending packets\n" + "\n" " --help Display this help text and exit\n"); } +/* Times are in ms. */ +static int time_mul(const char * rem) +{ + if (strcmp(rem, "ms") == 0 || strcmp(rem, "") == 0) + return 1; + else if(strcmp(rem, "s") == 0) + return 1000; + else if (strcmp(rem, "m") == 0) + return 60 * 1000; + else if (strcmp(rem, "h") == 0) + return 60 * 60 * 1000; + else if (strcmp(rem, "d") == 0) + return 60 * 60 * 24 * 1000; + + printf("Unknown time unit: %s.\n", rem); + + exit(EXIT_FAILURE); +} + +static int rate_mul(const char * rem) +{ + if (strcmp(rem, "k") == 0 || strcmp(rem, "") == 0) + return 1000; + else if(strcmp(rem, "M") == 0) + return MILLION; + else if (strcmp(rem, "G") == 0) + return BILLION; + + printf("Unknown rate unit: %s.\n", rem); + + exit(EXIT_FAILURE); +} + int main(int argc, char ** argv) { - int ret = -1; - char * rem = NULL; - bool serv = false; + int ret = -1; + char * rem = NULL; + bool serv = false; + char * type = "uni"; argc--; argv++; - client.s_apn = NULL; + client.server_name = NULL; client.size = 1500; client.duration = 60000; server.timeout = 1000; /* ms */ @@ -128,8 +178,8 @@ int main(int argc, char ** argv) while (argc > 0) { if (strcmp(*argv, "-n") == 0 || - strcmp(*argv, "--server_apn") == 0) { - client.s_apn = *(++argv); + strcmp(*argv, "--server-name") == 0) { + client.server_name = *(++argv); --argc; } else if (strcmp(*argv, "-s") == 0 || strcmp(*argv, "--size") == 0) { @@ -137,17 +187,13 @@ int main(int argc, char ** argv) --argc; } else if (strcmp(*argv, "-d") == 0 || strcmp(*argv, "--duration") == 0) { - client.duration = strtol(*(++argv), &rem, 10) * 1000; + client.duration = strtol(*(++argv), &rem, 10); + client.duration *= time_mul(rem); --argc; } else if (strcmp(*argv, "-r") == 0 || strcmp(*argv, "--rate") == 0) { client.rate = strtol(*(++argv), &rem, 10); - if (*rem == 'k') - client.rate *= 1000; - if (*rem == 'M') - client.rate *= MILLION; - if (*rem == 'G') - client.rate *= BILLION; + client.rate *= rate_mul(rem); --argc; } else if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--flood") == 0) { @@ -157,6 +203,10 @@ int main(int argc, char ** argv) } else if (strcmp(*argv, "-l") == 0 || strcmp(*argv, "--listen") == 0) { serv = true; + } else if (strcmp(*argv, "-t") == 0 || + strcmp(*argv, "--test") == 0) { + type = *(++argv); + --argc; } else { usage(); exit(EXIT_SUCCESS); @@ -168,11 +218,20 @@ int main(int argc, char ** argv) if (serv) { ret = server_main(); } else { - if (client.s_apn == NULL) { + if (client.server_name == NULL) { printf("No server specified.\n"); - usage(); - exit(EXIT_SUCCESS); + exit(EXIT_FAILURE); } + + if (strcmp(type, "uni") == 0) + client.conf.test_type = TEST_TYPE_UNI; + else if (strcmp(type, "bi") == 0) + client.conf.test_type = TEST_TYPE_BI; + else { + printf("Invalid test type.\n"); + exit(EXIT_FAILURE); + } + if (client.size > OPERF_BUF_SIZE) { printf("Packet size truncated to %d bytes.\n", OPERF_BUF_SIZE); diff --git a/src/tools/operf/operf_client.c b/src/tools/operf/operf_client.c index 1518bdf5..63f98299 100644 --- a/src/tools/operf/operf_client.c +++ b/src/tools/operf/operf_client.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros ping application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +bool stop; + static void busy_wait_until(const struct timespec * deadline) { struct timespec now; @@ -45,7 +47,6 @@ static void busy_wait_until(const struct timespec * deadline) while (now.tv_sec == deadline->tv_sec && now.tv_nsec < deadline->tv_nsec) clock_gettime(CLOCK_REALTIME, &now); - pthread_testcancel(); } void shutdown_client(int signo, siginfo_t * info, void * c) @@ -57,8 +58,7 @@ void shutdown_client(int signo, siginfo_t * info, void * c) case SIGINT: case SIGTERM: case SIGHUP: - pthread_cancel(client.reader_pt); - pthread_cancel(client.writer_pt); + stop = true; default: return; } @@ -74,7 +74,14 @@ void * reader(void * o) fccntl(fd, FLOWSRCVTIMEO, &timeout); - while ((msg_len = flow_read(fd, buf, OPERF_BUF_SIZE)) != -ETIMEDOUT) { + while (!stop) { + msg_len = flow_read(fd, buf, OPERF_BUF_SIZE); + if (msg_len == -ETIMEDOUT) { + printf("Server timed out.\n"); + stop = true; + break; + } + if (msg_len != client.size) { printf("Invalid message on fd %d.\n", fd); continue; @@ -96,62 +103,64 @@ void * writer(void * o) struct timespec intv = {(gap / BILLION), gap % BILLION}; struct timespec end = {0, 0}; - char * buf = malloc(client.size); + char * buf; + struct msg * msg; + + buf = malloc(client.size); if (buf == NULL) return (void *) -ENOMEM; - if (fdp == NULL) + if (fdp == NULL) { + free(buf); return (void *) -EINVAL; + } memset(buf, 0, client.size); + msg = (struct msg *) buf; + if (client.flood) - printf("Flooding %s with %d byte SDUs for %d seconds.\n\n", - client.s_apn, client.size, client.duration / 1000); + printf("Flooding %s with %d byte packets for %d seconds.\n\n", + client.server_name, client.size, + client.duration / 1000); else - printf("Sending %d byte SDUs for %d s to %s at %.3lf Mb/s.\n\n", - client.size, client.duration / 1000, client.s_apn, + printf("Sending %d byte packets for %d s to %s " + "at %.3lf Mb/s.\n\n", + client.size, client.duration / 1000, + client.server_name, client.rate / (double) MILLION); clock_gettime(CLOCK_REALTIME, &start); clock_gettime(CLOCK_REALTIME, &now); - pthread_cleanup_push((void (*) (void *)) free, buf); - - if (client.flood) { - while (ts_diff_ms(&start, &now) < client.duration) { - if (flow_write(*fdp, buf, client.size) == -1) { - printf("Failed to send SDU.\n"); - flow_dealloc(*fdp); - free(buf); - return (void *) -1; - } + while (!stop && ts_diff_ms(&start, &now) < client.duration) { + if (!client.flood) { + clock_gettime(CLOCK_REALTIME, &now); + ts_add(&now, &intv, &end); + } - ++client.sent; + msg->id = client.sent; - clock_gettime(CLOCK_REALTIME, &now); + if (flow_write(*fdp, buf, client.size) < 0) { + printf("Failed to send packet.\n"); + flow_dealloc(*fdp); + free(buf); + return (void *) -1; } - } else { - while (ts_diff_ms(&start, &now) < client.duration) { - clock_gettime(CLOCK_REALTIME, &now); - ts_add(&now, &intv, &end); - if (flow_write(*fdp, buf, client.size) == -1) { - printf("Failed to send SDU.\n"); - flow_dealloc(*fdp); - free(buf); - return (void *) -1; - } + ++client.sent; - ++client.sent; + if (!client.flood) { if (client.sleep) nanosleep(&intv, NULL); else busy_wait_until(&end); + } else { + clock_gettime(CLOCK_REALTIME, &now); } } - pthread_cleanup_pop(true); + free(buf); printf("Test finished.\n"); @@ -181,34 +190,51 @@ int client_main(void) client.sent = 0; client.rcvd = 0; + stop = false; - fd = flow_alloc(client.s_apn, NULL, NULL); + /* FIXME: Allow selecting QoS. */ + fd = flow_alloc(client.server_name, NULL, NULL); if (fd < 0) { printf("Failed to allocate flow.\n"); return -1; } - clock_gettime(CLOCK_REALTIME, &tic); + if (client.conf.test_type == TEST_TYPE_BI) + printf("Doing a bidirectional test.\n"); + else + printf("Doing a unidirectional test.\n"); - pthread_create(&client.reader_pt, NULL, reader, &fd); - pthread_create(&client.writer_pt, NULL, writer, &fd); + if (flow_write(fd, &client.conf, sizeof(client.conf)) < 0) { + printf("Failed to send configuration.\n"); + flow_dealloc(fd); + return -1; + } - pthread_join(client.writer_pt, NULL); + sleep(1); + + clock_gettime(CLOCK_REALTIME, &tic); - clock_gettime(CLOCK_REALTIME, &toc); + if (client.conf.test_type == TEST_TYPE_BI) + pthread_create(&client.reader_pt, NULL, reader, &fd); - pthread_join(client.reader_pt, NULL); + pthread_create(&client.writer_pt, NULL, writer, &fd); + pthread_join(client.writer_pt, NULL); - printf("\n"); - printf("--- %s perf statistics ---\n", client.s_apn); - printf("%ld SDUs transmitted, ", client.sent); - printf("%ld received, ", client.rcvd); - printf("%ld%% packet loss, ", client.sent == 0 ? 0 : - 100 - ((100 * client.rcvd) / client.sent)); - printf("time: %.3f ms, ", ts_diff_us(&tic, &toc) / 1000.0); - printf("bandwidth: %.3lf Mb/s.\n", - (client.rcvd * client.size * 8) - / (double) ts_diff_us(&tic, &toc)); + if (client.conf.test_type == TEST_TYPE_BI){ + clock_gettime(CLOCK_REALTIME, &toc); + pthread_join(client.reader_pt, NULL); + + printf("\n"); + printf("--- %s perf statistics ---\n", client.server_name); + printf("%ld packets transmitted, ", client.sent); + printf("%ld received, ", client.rcvd); + printf("%ld%% packet loss, ", client.sent == 0 ? 0 : + 100 - ((100 * client.rcvd) / client.sent)); + printf("time: %.3f ms, ", ts_diff_us(&tic, &toc) / 1000.0); + printf("bandwidth: %.3lf Mb/s.\n", + (client.rcvd * client.size * 8) + / (double) ts_diff_us(&tic, &toc)); + } flow_dealloc(fd); diff --git a/src/tools/operf/operf_server.c b/src/tools/operf/operf_server.c index 11eb92fc..d11f3486 100644 --- a/src/tools/operf/operf_server.c +++ b/src/tools/operf/operf_server.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros perf application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +bool stop; + void shutdown_server(int signo, siginfo_t * info, void * c) { (void) info; @@ -46,6 +48,7 @@ void shutdown_server(int signo, siginfo_t * info, void * c) case SIGTERM: case SIGHUP: pthread_cancel(server.accept_pt); + stop = true; default: return; } @@ -58,7 +61,7 @@ void * cleaner_thread(void * o) (void) o; - while (true) { + while (!stop) { clock_gettime(CLOCK_REALTIME, &now); pthread_mutex_lock(&server.lock); for (i = 0; i < OPERF_MAX_FLOWS; ++i) @@ -73,18 +76,21 @@ void * cleaner_thread(void * o) pthread_mutex_unlock(&server.lock); sleep(1); } + + return (void *) 0; } -void * server_thread(void *o) +void * server_thread(void * o) { - int msg_len = 0; + int msg_len = 0; struct timespec timeout = {0, 100 * MILLION}; - struct timespec now = {0, 0}; - int fd; + struct timespec now = {0, 0}; + int fd; + struct msg * msg; (void) o; - while (fevent(server.flows, server.fq, &timeout)) + while (!stop && fevent(server.flows, server.fq, &timeout)) while ((fd = fqueue_next(server.fq)) >= 0) { msg_len = flow_read(fd, server.buffer, OPERF_BUF_SIZE); if (msg_len < 0) @@ -96,9 +102,21 @@ void * server_thread(void *o) server.times[fd] = now; pthread_mutex_unlock(&server.lock); - if (flow_write(fd, server.buffer, msg_len) < 0) { - printf("Error writing to flow (fd %d).\n", fd); - flow_dealloc(fd); + msg = (struct msg *) server.buffer; + + if (server.conf[fd].test_type == TEST_TYPE_UNI) + printf("Seqno %d from fd %d: %zd.%06zu\n", + msg->id, fd, + (ssize_t) now.tv_sec, + (size_t) now.tv_nsec / 1000); + + if (server.conf[fd].test_type == TEST_TYPE_BI) { + if (flow_write(fd, server.buffer, + msg_len) < 0) { + printf("Error writing to flow " + "(fd %d).\n", fd); + flow_dealloc(fd); + } } } @@ -110,12 +128,13 @@ void * accept_thread(void * o) int fd = 0; struct timespec now = {0, 0}; qosspec_t qs; + int len = 0; (void) o; printf("Ouroboros perf server started.\n"); - while (true) { + while (!stop) { fd = flow_accept(&qs, NULL); if (fd < 0) { printf("Failed to accept flow.\n"); @@ -124,6 +143,27 @@ void * accept_thread(void * o) printf("New flow %d.\n", fd); + /* Read test type. */ + len = flow_read(fd, &(server.conf[fd]), + sizeof(server.conf[fd])); + if (len == -ETIMEDOUT) { + printf("Failed to read config message.\n"); + flow_dealloc(fd); + break; + } + + /* Check if length was correct. */ + if (flow_read(fd, NULL, 0) != 0) { + printf("Invalid config message.\n"); + flow_dealloc(fd); + break; + } + + if (server.conf[fd].test_type == TEST_TYPE_BI) + printf("Doing a bidirectional test.\n"); + else + printf("Doing a unidirectional test.\n"); + clock_gettime(CLOCK_REALTIME, &now); pthread_mutex_lock(&server.lock); @@ -161,20 +201,19 @@ int server_main(void) return -1; } + stop = false; + pthread_create(&server.cleaner_pt, NULL, cleaner_thread, NULL); pthread_create(&server.accept_pt, NULL, accept_thread, NULL); pthread_create(&server.server_pt, NULL, server_thread, NULL); pthread_join(server.accept_pt, NULL); - pthread_cancel(server.server_pt); - pthread_cancel(server.cleaner_pt); + pthread_join(server.server_pt, NULL); + pthread_join(server.cleaner_pt, NULL); fset_destroy(server.flows); fqueue_destroy(server.fq); - pthread_join(server.server_pt, NULL); - pthread_join(server.cleaner_pt, NULL); - return 0; } diff --git a/src/tools/oping/oping.c b/src/tools/oping/oping.c index 3c1d4fe9..ed3529e5 100644 --- a/src/tools/oping/oping.c +++ b/src/tools/oping/oping.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros ping application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,9 +42,11 @@ #include <ouroboros/dev.h> #include <ouroboros/fccntl.h> #include <ouroboros/fqueue.h> +#include <ouroboros/qos.h> #include "time_utils.h" +#include <limits.h> #include <stdio.h> #include <string.h> #include <pthread.h> @@ -58,22 +60,43 @@ #include <errno.h> #include <float.h> -#define OPING_BUF_SIZE 1500 - -#define ECHO_REQUEST 0 -#define ECHO_REPLY 1 - +#define OPING_BUF_SIZE 1500 +#define ECHO_REQUEST 0 +#define ECHO_REPLY 1 #define OPING_MAX_FLOWS 256 -struct c { - char * s_apn; - int interval; - uint32_t count; - int size; +#define USAGE_STRING \ +"Usage: oping [OPTION]...\n" \ +"\n" \ +"Checks liveness between a client and a server\n" \ +"and reports the Round Trip Time (RTT)\n" \ +"\n" \ +" -l, --listen Run in server mode\n" \ +"\n" \ +" -c, --count Number of packets\n" \ +" -d, --duration Duration of the test (default 1s)\n" \ +" -i, --interval Interval (default 1000ms)\n" \ +" -n, --server-name Name of the oping server\n" \ +" -q, --qos QoS (raw, raw_crypt, best, video, voice, data)\n" \ +" -s, --size Payload size (B, default 64)\n" \ +" -Q, --quiet Only print final statistics\n" \ +" -D, --timeofday Print time of day before each line\n" \ +"\n" \ +" --help Display this help text and exit\n" \ + +struct { + char * s_apn; + int interval; + uint32_t count; + int size; + bool timestamp; + qosspec_t qs; /* stats */ uint32_t sent; uint32_t rcvd; + size_t ooo; + bool quiet; double rtt_min; double rtt_max; @@ -84,12 +107,14 @@ struct c { pthread_t writer_pt; } client; -struct s { +struct { struct timespec times[OPING_MAX_FLOWS]; fset_t * flows; fqueue_t * fq; pthread_mutex_t lock; + bool quiet; + pthread_t cleaner_pt; pthread_t accept_pt; pthread_t server_pt; @@ -108,67 +133,130 @@ struct oping_msg { static void usage(void) { - printf("Usage: oping [OPTION]...\n" - "Checks liveness between a client and a server\n" - "and reports the Round Trip Time (RTT)\n\n" - " -l, --listen Run in server mode\n" - "\n" - " -c, --count Number of packets (default 1000)\n" - " -i, --interval Interval (ms, default 1000)\n" - " -n, --server-apn Name of the oping server\n" - " -s, --size Payload size (B, default 64)\n" - " --help Display this help text and exit\n"); + printf(USAGE_STRING); +} + +/* Times are in ms. */ +static int time_mul(const char * rem) +{ + if (strcmp(rem, "ms") == 0 || strcmp(rem, "") == 0) + return 1; + else if(strcmp(rem, "s") == 0) + return 1000; + else if (strcmp(rem, "m") == 0) + return 60 * 1000; + else if (strcmp(rem, "h") == 0) + return 60 * 60 * 1000; + else if (strcmp(rem, "d") == 0) + return 60 * 60 * 24 * 1000; + + printf("Unknown time unit: %s.\n", rem); + + exit(EXIT_FAILURE); } -int main(int argc, char ** argv) +int main(int argc, + char ** argv) { - int ret = -1; - char * rem = NULL; - bool serv = false; + int ret = -1; + char * rem = NULL; + bool serv = false; + long duration = 0; + char * qos = NULL; argc--; argv++; - client.s_apn = NULL; - client.interval = 1000; - client.size = 64; - client.count = 1000; + client.s_apn = NULL; + client.interval = 1000; + client.size = 64; + client.count = INT_MAX; + client.timestamp = false; + client.qs = qos_raw; + client.quiet = false; + server.quiet = false; while (argc > 0) { - if (strcmp(*argv, "-i") == 0 || - strcmp(*argv, "--interval") == 0) { + if ((strcmp(*argv, "-i") == 0 || + strcmp(*argv, "--interval") == 0) && + argc > 1) { client.interval = strtol(*(++argv), &rem, 10); + client.interval *= time_mul(rem); --argc; - } else if (strcmp(*argv, "-n") == 0 || - strcmp(*argv, "--server_apn") == 0) { + } else if ((strcmp(*argv, "-n") == 0 || + strcmp(*argv, "--server-name") == 0) && + argc > 1) { client.s_apn = *(++argv); --argc; - } else if (strcmp(*argv, "-c") == 0 || - strcmp(*argv, "--count") == 0) { + } else if ((strcmp(*argv, "-c") == 0 || + strcmp(*argv, "--count") == 0) && + argc > 1) { client.count = strtol(*(++argv), &rem, 10); --argc; - } else if (strcmp(*argv, "-s") == 0 || - strcmp(*argv, "--size") == 0) { + } else if ((strcmp(*argv, "-d") == 0 || + strcmp(*argv, "--duration") == 0) && + argc > 1) { + duration = strtol(*(++argv), &rem, 10); + duration *= time_mul(rem); + --argc; + } else if ((strcmp(*argv, "-s") == 0 || + strcmp(*argv, "--size") == 0) && + argc > 1) { client.size = strtol(*(++argv), &rem, 10); --argc; + } else if ((strcmp(*argv, "-q") == 0 || + strcmp(*argv, "--qos") == 0) && + argc > 1) { + qos = *(++argv); + --argc; } else if (strcmp(*argv, "-l") == 0 || strcmp(*argv, "--listen") == 0) { serv = true; + } else if (strcmp(*argv, "-D") == 0 || + strcmp(*argv, "--timeofday") == 0) { + client.timestamp = true; + } else if (strcmp(*argv, "-Q") == 0 || + strcmp(*argv, "--quiet") == 0) { + client.quiet = true; + server.quiet = true; } else { - usage(); - exit(EXIT_SUCCESS); + goto fail; } argc--; argv++; } + if (duration > 0) { + if (client.interval == 0) + client.count = duration * 10; + else + client.count = duration / client.interval; + } + + if (qos != NULL) { + if (strcmp(qos, "best") == 0) + client.qs = qos_best_effort; + else if (strcmp(qos, "raw") == 0) + client.qs = qos_raw; + else if (strcmp(qos, "video") == 0) + client.qs = qos_video; + else if (strcmp(qos, "voice") == 0) + client.qs = qos_voice; + else if (strcmp(qos, "data") == 0) + client.qs = qos_data; + else if (strcmp(qos, "raw_crypt") == 0) + client.qs = qos_raw_crypt; + else + printf("Unknown QoS cube, defaulting to raw.\n"); + } + if (serv) { ret = server_main(); } else { if (client.s_apn == NULL) { printf("No server specified.\n"); usage(); - exit(EXIT_SUCCESS); + exit(EXIT_FAILURE); } if (client.interval > 10000) { printf("Ping interval truncated to 10s.\n"); @@ -179,7 +267,6 @@ int main(int argc, char ** argv) OPING_BUF_SIZE); client.size = OPING_BUF_SIZE; } - if (client.size < 64) { printf("Packet size set to 64 bytes.\n"); client.size = 64; @@ -192,4 +279,8 @@ int main(int argc, char ** argv) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); + + fail: + usage(); + exit(EXIT_FAILURE); } diff --git a/src/tools/oping/oping_client.c b/src/tools/oping/oping_client.c index 6f874dd9..7b03c83d 100644 --- a/src/tools/oping/oping_client.c +++ b/src/tools/oping/oping_client.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros ping application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -65,10 +65,13 @@ void * reader(void * o) int msg_len = 0; double ms = 0; double d = 0; + uint32_t exp_id = 0; fccntl(fd, FLOWSRCVTIMEO, &timeout); while (!stop && client.rcvd != client.count) { + uint32_t id; + msg_len = flow_read(fd, buf, OPING_BUF_SIZE); if (msg_len == -ETIMEDOUT) { printf("Server timed out.\n"); @@ -84,7 +87,8 @@ void * reader(void * o) continue; } - if ((uint32_t) ntohl(msg->id) >= client.count) { + id = (uint32_t) ntohl(msg->id); + if (id >= client.count) { printf("Invalid id.\n"); continue; } @@ -98,11 +102,25 @@ void * reader(void * o) ms = ts_diff_us(&sent, &now) / 1000.0; - printf("%d bytes from %s: seq=%d time=%.3f ms\n", - msg_len, - client.s_apn, - ntohl(msg->id), - ms); + if (id < exp_id) + ++client.ooo; + + if (!client.quiet) { + if (client.timestamp) { + struct timespec rtc; + clock_gettime(CLOCK_REALTIME, &rtc); + printf("[%zd.%06zu] ", + (ssize_t) rtc.tv_sec, + (size_t) rtc.tv_nsec / 1000); + } + + printf("%d bytes from %s: seq=%d time=%.3f ms%s\n", + msg_len, + client.s_apn, + ntohl(msg->id), + ms, + id < exp_id ? " [out-of-order]" : ""); + } if (ms < client.rtt_min) client.rtt_min = ms; @@ -112,6 +130,9 @@ void * reader(void * o) d = (ms - client.rtt_avg); client.rtt_avg += d / client.rcvd; client.rtt_m2 += d * (ms - client.rtt_avg); + + if (id >= exp_id) + exp_id = id + 1; } return (void *) 0; @@ -129,17 +150,20 @@ void * writer(void * o) if (buf == NULL) return (void *) -ENOMEM; - if (fdp == NULL) + if (fdp == NULL) { + free(buf); return (void *) -EINVAL; + } memset(buf, 0, client.size); msg = (struct oping_msg *) buf; - printf("Pinging %s with %d bytes of data:\n\n", - client.s_apn, client.size); + if (!client.quiet) + printf("Pinging %s with %d bytes of data (%u packets):\n\n", + client.s_apn, client.size, client.count); - pthread_cleanup_push((void (*) (void *)) free, buf); + pthread_cleanup_push(free, buf); while (!stop && client.sent < client.count) { nanosleep(&wait, NULL); @@ -151,11 +175,9 @@ void * writer(void * o) msg->tv_sec = now.tv_sec; msg->tv_nsec = now.tv_nsec; - if (flow_write(*fdp, buf, client.size) == -1) { - printf("Failed to send SDU.\n"); - flow_dealloc(*fdp); - free(buf); - return (void *) -1; + if (flow_write(*fdp, buf, client.size) < 0) { + printf("Failed to send packet.\n"); + stop = true; } } @@ -208,13 +230,15 @@ static int client_main(void) return -1; } - fd = flow_alloc(client.s_apn, NULL, NULL); + fd = flow_alloc(client.s_apn, &client.qs, NULL); if (fd < 0) { - printf("Failed to allocate flow.\n"); + printf("Failed to allocate flow: %d.\n", fd); client_fini(); return -1; } + fccntl(fd, FLOWSFLAGS, FLOWFRDWR | FLOWFRNOPART); + clock_gettime(CLOCK_REALTIME, &tic); pthread_create(&client.reader_pt, NULL, reader, &fd); @@ -227,8 +251,9 @@ static int client_main(void) printf("\n"); printf("--- %s ping statistics ---\n", client.s_apn); - printf("%d SDUs transmitted, ", client.sent); + printf("%d packets transmitted, ", client.sent); printf("%d received, ", client.rcvd); + printf("%zd out-of-order, ", client.ooo); printf("%.0lf%% packet loss, ", client.sent == 0 ? 0 : ceil(100 - (100 * (client.rcvd / (float) client.sent)))); printf("time: %.3f ms\n", ts_diff_us(&tic, &toc) / 1000.0); diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c index 391da197..6f76869c 100644 --- a/src/tools/oping/oping_server.c +++ b/src/tools/oping/oping_server.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Ouroboros ping application * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -61,16 +61,21 @@ void * cleaner_thread(void * o) while (true) { clock_gettime(CLOCK_REALTIME, &now); - pthread_mutex_lock(&server.lock); + for (i = 0; i < OPING_MAX_FLOWS; ++i) - if (fset_has(server.flows, i) && - ts_diff_ms(&server.times[i], &now) > deadline_ms) { - printf("Flow %d timed out.\n", i); - fset_del(server.flows, i); - flow_dealloc(i); + if (fset_has(server.flows, i)) { + time_t diff; + + pthread_mutex_lock(&server.lock); + diff = ts_diff_ms(&server.times[i], &now); + pthread_mutex_unlock(&server.lock); + + if (diff > deadline_ms) { + printf("Flow %d timed out.\n", i); + fset_del(server.flows, i); + flow_dealloc(i); + } } - - pthread_mutex_unlock(&server.lock); sleep(1); } } @@ -96,10 +101,13 @@ void * server_thread(void *o) continue; if (ntohl(msg->type) != ECHO_REQUEST) { - printf("Invalid message on fd %d.", fd); + printf("Invalid message on fd %d.\n", fd); continue; } + if (!server.quiet) + printf("Received %d bytes on fd %d.\n", msg_len, fd); + clock_gettime(CLOCK_REALTIME, &now); pthread_mutex_lock(&server.lock); @@ -118,9 +126,9 @@ void * server_thread(void *o) void * accept_thread(void * o) { - int fd; + int fd; struct timespec now; - qosspec_t qs; + qosspec_t qs; (void) o; @@ -137,12 +145,14 @@ void * accept_thread(void * o) clock_gettime(CLOCK_REALTIME, &now); - pthread_mutex_lock(&server.lock); fset_add(server.flows, fd); + + pthread_mutex_lock(&server.lock); server.times[fd] = now; pthread_mutex_unlock(&server.lock); - fccntl(fd, FLOWSFLAGS, FLOWFRNOBLOCK | FLOWFRDWR); + fccntl(fd, FLOWSFLAGS, + FLOWFRNOBLOCK | FLOWFRDWR | FLOWFRNOPART); } return (void *) 0; diff --git a/src/tools/ovpn/CMakeLists.txt b/src/tools/ovpn/CMakeLists.txt new file mode 100644 index 00000000..f3a2cac8 --- /dev/null +++ b/src/tools/ovpn/CMakeLists.txt @@ -0,0 +1,21 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_BINARY_DIR}/include) + +get_filename_component(CURRENT_SOURCE_PARENT_DIR + ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + +include_directories(${CURRENT_SOURCE_PARENT_DIR}) + +set(SOURCE_FILES + # Add source files here + ovpn.c + ) + +add_executable(ovpn ${SOURCE_FILES}) + +target_link_libraries(ovpn LINK_PUBLIC ouroboros-dev) + +install(TARGETS ovpn RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/tools/ovpn/ovpn.c b/src/tools/ovpn/ovpn.c new file mode 100644 index 00000000..5333ff40 --- /dev/null +++ b/src/tools/ovpn/ovpn.c @@ -0,0 +1,335 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * Ouroboros VPN + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _POSIX_C_SOURCE 200109L + +#include <ouroboros/dev.h> + +#include <stdio.h> +#include <pthread.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <arpa/inet.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <signal.h> +#include <getopt.h> + +#define BUF_SIZE 65536 + +int t_fd; +int o_fd; + +static void usage(void) +{ + printf("Usage: ovpn [OPTION]...\n" + "Sends TCP/IP traffic over Ouroboros\n\n" + " -n, --name Run as client, name of ovpn " + "server to connect to\n" + " -i, --ip IP address to give to TUN device\n" + " -m, --mask Subnet mask to give to TUN device\n" + " -C, --crypt AES encryption (default: off)\n" + "\n" + " --help Display this help text and exit\n"); +} + +static int tun_open(char * dev, + uint32_t ip, + uint32_t mask) +{ + struct ifreq ifr; + int fd; + int s; + int ret; + char * clonedev = "/dev/net/tun"; + struct sockaddr_in * addr; + + fd = open(clonedev, O_RDWR); + if (fd < 0) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + + ret = ioctl(fd, TUNSETIFF, (void *) &ifr); + if (ret < 0) + goto fail; + + strcpy(dev, ifr.ifr_name); + + /* Now get the i/f up and running. */ + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + goto fail; + + /* Set IP address. */ + ifr.ifr_addr.sa_family = AF_INET; + addr = (struct sockaddr_in *) &ifr.ifr_addr; + addr->sin_addr.s_addr = ip; + + if (ioctl(s, SIOCSIFADDR, &ifr)) + goto fail_ioctl; + + /* Set subnet mask. */ + addr->sin_addr.s_addr = mask; + if (ioctl(s, SIOCSIFNETMASK, &ifr)) + goto fail_ioctl; + + /* Bring interface up. */ + if (ioctl(s, SIOCGIFFLAGS, &ifr)) + goto fail_ioctl; + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + if (ioctl(s, SIOCSIFFLAGS, &ifr)) + goto fail_ioctl; + + close(s); + + return fd; + + fail_ioctl: + close(s); + fail: + close(fd); + return -1; +} + +void * o_reader(void * o) +{ + char buf[BUF_SIZE]; + int len = 0; + + (void) o; + + while (true) { + len = flow_read(o_fd, buf, BUF_SIZE); + if (len <= 0) + continue; + + if (write(t_fd, buf, len)) + continue; + } +} + +void * t_reader(void * o) +{ + char buf[BUF_SIZE]; + int len = 0; + + (void) o; + + while (true) { + len = read(t_fd, buf, BUF_SIZE); + if (len <= 0) + continue; + + if (flow_write(o_fd, buf, len) < 0) + continue; + } +} + +static int check_mask(uint32_t mask) +{ + if (mask == 0) + return 0; + + return ((~mask & (~mask + 1)) != 0); +} + +int main(int argc, + char ** argv) +{ + char * name = NULL; + uint32_t ip = 0; + int32_t mask = -1; + char dev[IFNAMSIZ]; + pthread_t t_thr; + pthread_t o_thr; + sigset_t sigset; + int sig; + int c; + qosspec_t qs; + + static struct option long_options[] = + {{"ip", required_argument, NULL, 'i'}, + {"mask", required_argument, NULL, 'm'}, + {"name", required_argument, NULL, 'n'}, + {"crypt", no_argument, NULL, 'C'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + sigaddset(&sigset, SIGQUIT); + sigaddset(&sigset, SIGHUP); + sigaddset(&sigset, SIGTERM); + + if (geteuid() != 0) { + printf("ovpn must be run as root.\n"); + exit(EXIT_FAILURE); + } + + qs = qos_raw; + + while ((c = getopt_long(argc, argv, "i:m:n:Ch", + long_options, NULL)) != -1) { + switch (c) { + case 'i': + if (inet_pton(AF_INET, optarg, &ip) != 1) { + printf("Invalid IP address: %s.\n\n", optarg); + goto fail_usage; + } + break; + case 'm': + if (inet_pton(AF_INET, optarg, &mask) != 1 || + check_mask(htonl(mask))) { + printf("Invalid subnet mask: %s.\n\n", optarg); + goto fail_usage; + } + break; + case 'n': + name = optarg; + break; + case 'C': + qs = qos_raw_crypt; + break; + case 'h': + usage(); + exit(EXIT_SUCCESS); + default: + exit(EXIT_FAILURE); + } + } + + if (optind < argc) { + printf("Unknown arguments specified: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n\n"); + goto fail_usage; + } + + if (ip == 0) { + printf("Please specify an IP address.\n\n"); + goto fail_usage; + } + + if (mask == -1) { + printf("Please specify a subnetmask.\n\n"); + goto fail_usage; + } + + if (name != NULL) { + printf("Allocating a flow to %s.\n", name); + + o_fd = flow_alloc(name, &qs, NULL); + if (o_fd < 0) { + printf("Failed to allocate flow.\n"); + goto fail_alloc; + } + } else { + printf("Waiting for a new flow...\n"); + + o_fd = flow_accept(NULL, NULL); + if (o_fd < 0) { + printf("Failed to accept flow.\n"); + goto fail_alloc; + } + } + + printf("Flow allocated.\n"); + + t_fd = tun_open(dev, ip, mask); + if (t_fd < 0) { + printf("Failed to open tunnel device.\n"); + goto fail_tun; + } + + printf("Tunnel device name is %s.\n", dev); + + pthread_sigmask(SIG_BLOCK, &sigset, NULL); + + printf("Starting read/write threads.\n"); + + if (pthread_create(&o_thr, NULL, o_reader, NULL)) + goto fail_thread; + + if (pthread_create(&t_thr, NULL, t_reader, NULL)) + goto fail_thread2; + + while (true) { + if (sigwait(&sigset, &sig) != 0) { + printf("Bad signal.\n"); + continue; + } + + printf("Shutting down...\n"); + break; + } + + pthread_cancel(o_thr); + pthread_cancel(t_thr); + + pthread_join(o_thr, NULL); + pthread_join(t_thr, NULL); + + close(t_fd); + flow_dealloc(o_fd); + + pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); + + exit(EXIT_SUCCESS); + fail_usage: + usage(); + exit(EXIT_FAILURE); + fail_thread2: + pthread_cancel(o_thr); + pthread_join(o_thr, NULL); + fail_thread: + close(t_fd); + fail_tun: + flow_dealloc(o_fd); + fail_alloc: + exit(EXIT_FAILURE); +} diff --git a/src/tools/time_utils.h b/src/tools/time_utils.h index c9760a8b..c17282dc 100644 --- a/src/tools/time_utils.h +++ b/src/tools/time_utils.h @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2018 + * Ouroboros - Copyright (C) 2016 - 2024 * * Time utilities * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef OUROBOROS_TOOLS_TIME_UTILS_H #define OUROBOROS_TOOLS_TIME_UTILS_H @@ -52,7 +51,6 @@ #include <time.h> #include <sys/time.h> -#include <limits.h> /* LONG_MAX */ /* functions for timespecs */ #define ts_diff_ns(t0, tx) (((tx)->tv_sec - (t0)->tv_sec) * BILLION \ @@ -69,29 +67,70 @@ + ((tx)->tv_usec - (t0)->tv_usec) / MILLION) /* functions for timespecs */ -int ts_add(const struct timespec * t, - const struct timespec * intv, - struct timespec * res); -int ts_diff(const struct timespec * t, - const struct timespec * intv, - struct timespec * res); +#define ts_add(t, intv, res) \ + do { \ + time_t nanos = 0; \ + nanos = (t)->tv_nsec + (intv)->tv_nsec; \ + (res)->tv_sec = (t)->tv_sec + (intv)->tv_sec; \ + while (nanos >= BILLION) { \ + nanos -= BILLION; \ + ++((res)->tv_sec); \ + } \ + (res)->tv_nsec = nanos; \ + } while (0); + +#define ts_diff(t, intv, res) \ + do { \ + time_t nanos = 0; \ + nanos = (t)->tv_nsec - (intv)->tv_nsec; \ + (res)->tv_sec = (t)->tv_sec - (intv)->tv_sec; \ + while (nanos < 0) { \ + nanos += BILLION; \ + --((res)->tv_sec); \ + } \ + (res)->tv_nsec = nanos; \ + } while (0); /* functions for timevals */ -int tv_add(const struct timeval * t, - const struct timeval * intv, - struct timeval * res); -int tv_diff(const struct timeval * t, - const struct timeval * intv, - struct timeval * res); +#define tv_add(t, intv, res) \ + do { \ + time_t micros = 0; \ + nanos = (t)->tv_usec + (intv)->tv_usec; \ + (res)->tv_sec = (t)->tv_sec + (intv)->tv_sec; \ + while (micros >= MILLION) { \ + micros -= MILLION; \ + ++((res)->tv_sec); \ + } \ + (res)->tv_nsec = nanos; \ + } while (0); + +#define tv_diff(t, intv, res) \ + do { \ + time_t micros = 0; \ + micros = (t)->tv_usec - (intv)->tv_usec; \ + (res)->tv_sec = (t)->tv_sec - (intv)->tv_sec; \ + while (micros < 0) { \ + micros += MILLION; \ + --((res)->tv_sec); \ + } \ + (res)->tv_usec = micros; \ + } while (0); + /* copying a timeval into a timespec */ -int tv_to_ts(const struct timeval * src, - struct timespec * dst); +#define tv_to_ts(tv, ts) \ + do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000L; \ + } while (0); /* copying a timespec into a timeval (loss of resolution) */ -int ts_to_tv(const struct timespec * src, - struct timeval * dst); +#define ts_to_tv(ts, tv) \ + do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000L; \ + } while (0); #endif /* OUROBOROS_TOOLS_TIME_UTILS_H */ |
