diff options
Diffstat (limited to 'src/irmd')
| -rw-r--r-- | src/irmd/config.h.in | 6 | ||||
| -rw-r--r-- | src/irmd/configfile.c | 553 | ||||
| -rw-r--r-- | src/irmd/ipcp.c | 129 | ||||
| -rw-r--r-- | src/irmd/ipcp.h | 71 | ||||
| -rw-r--r-- | src/irmd/irmd.h | 53 | ||||
| -rw-r--r-- | src/irmd/main.c | 610 | ||||
| -rw-r--r-- | src/irmd/oap.h | 29 | ||||
| -rw-r--r-- | src/irmd/oap/cli.c | 38 | ||||
| -rw-r--r-- | src/irmd/oap/tests/common.c | 19 | ||||
| -rw-r--r-- | src/irmd/reg/flow.c | 3 | ||||
| -rw-r--r-- | src/irmd/reg/flow.h | 2 | ||||
| -rw-r--r-- | src/irmd/reg/name.c | 1 | ||||
| -rw-r--r-- | src/irmd/reg/reg.c | 73 | ||||
| -rw-r--r-- | src/irmd/reg/reg.h | 251 | ||||
| -rw-r--r-- | src/irmd/reg/tests/reg_test.c | 2 |
15 files changed, 1423 insertions, 417 deletions
diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in index 53f80ca4..2440e180 100644 --- a/src/irmd/config.h.in +++ b/src/irmd/config.h.in @@ -21,10 +21,6 @@ */ -#define IPCP_UDP4_EXEC "@IPCP_UDP4_TARGET@" -#define IPCP_UDP6_EXEC "@IPCP_UDP6_TARGET@" -#define IPCP_ETH_LLC_EXEC "@IPCP_ETH_LLC_TARGET@" -#define IPCP_ETH_DIX_EXEC "@IPCP_ETH_DIX_TARGET@" #define IPCP_UNICAST_EXEC "@IPCP_UNICAST_TARGET@" #define IPCP_BROADCAST_EXEC "@IPCP_BROADCAST_TARGET@" #define IPCP_LOCAL_EXEC "@IPCP_LOCAL_TARGET@" @@ -75,6 +71,8 @@ #define OUROBOROS_CLI_CRT_DIR "@OUROBOROS_CLI_CRT_DIR@" #define OUROBOROS_CHAIN_DIR "@OUROBOROS_UNTRUSTED_DIR@" +/* Endpoint peers are keyed on their address, not on a service name. */ + #define IRMD_PKILL_TIMEOUT @IRMD_PKILL_TIMEOUT@ #cmakedefine DISABLE_DIRECT_IPC diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index e2e1e554..de02242f 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -43,6 +43,7 @@ #include <assert.h> #include <errno.h> #include <inttypes.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <toml.h> @@ -92,171 +93,173 @@ static int toml_local(toml_table_t * table, return toml_hash(table, &conf->layer_info); } -static int toml_eth_dev(toml_table_t * table, - struct eth_config * conf) -{ - toml_datum_t dev; - dev = toml_string_in(table, "dev"); - if (!dev.ok) { - log_err("Missing device."); - return -1; - } +/* Defined with the peer helpers below; shared grammar for both paths. */ +static int toml_udp_str(const char * str, + char * host, + int * port); - if (strlen(dev.u.s) > DEV_NAME_SIZE) { - log_err("Device name too long: %s", dev.u.s); - free(dev.u.s); +/* Attach the PoAs an IPCP is given; one call per PoA. */ +static int poa_eth_set(struct poa_spec * poa, + const char * dev, + uint16_t ethertype) +{ + if (strlen(dev) > DEV_NAME_SIZE) { + log_err("Invalid device name %s.", dev); return -1; } - strcpy(conf->dev, dev.u.s); - free(dev.u.s); + memset(poa, 0, sizeof(*poa)); + + poa->type = POA_ETH; + poa->eth.ethertype = ethertype; + + strcpy(poa->eth.dev, dev); return 0; } -static int toml_eth_llc(toml_table_t * table, - struct ipcp_config * conf) +static int toml_poa_eth(toml_table_t * tbl, + struct poa_spec * poa) { - *conf = eth_llc_default_conf; - - if (toml_hash(table, &conf->layer_info) < 0) - return -1; - - return toml_eth_dev(table, &conf->eth); -} + toml_datum_t dev; + toml_datum_t et; + uint16_t ethertype = POA_ETHERTYPE; + int ret = -1; + dev = toml_string_in(tbl, "dev"); + if (!dev.ok) { + log_err("An eth PoA needs a device."); + goto fail; + } -static int toml_ethertype(toml_table_t * table, - struct eth_config * conf) -{ - toml_datum_t ethertype; + et = toml_int_in(tbl, "ethertype"); + if (et.ok) { + if (et.u.i < 0 || et.u.i > 0xFFFF) { + log_err("Invalid ethertype."); + goto fail; + } - ethertype = toml_int_in(table, "ethertype"); - if (ethertype.ok) - conf->ethertype = ethertype.u.i; + ethertype = et.u.i; + } - if (conf->ethertype < 0x0600 || conf->ethertype == 0xFFFF) - return -1; + ret = poa_eth_set(poa, dev.u.s, ethertype); + fail: + if (dev.ok) + free(dev.u.s); - return 0; + return ret; } -static int toml_eth_dix(toml_table_t * table, - struct ipcp_config * conf) +/* A PoA is bound locally: only literal addresses are accepted here. */ +static int toml_poa_udp(const char * str, + struct poa_spec * poa) { - *conf = eth_dix_default_conf; + char host[POA_HOST_STRLEN + 1]; + int port; - if (toml_hash(table, &conf->layer_info) < 0) + if (toml_udp_str(str, host, &port) < 0) return -1; - if (toml_eth_dev(table, &conf->eth) < 0) - return -1; + memset(poa, 0, sizeof(*poa)); - if (toml_ethertype(table, &conf->eth) < 0) { - log_err("Ethertype not in valid range."); - return -1; + if (inet_pton(AF_INET, host, &poa->udp4.ip_addr.s_addr) == 1) { + poa->type = POA_UDP4; + poa->udp4.port = port; + return 0; } - return 0; -} - -static int toml_udp4(toml_table_t * table, - struct ipcp_config * conf) -{ - struct udp4_config * udp4; - toml_datum_t ip; - toml_datum_t port; - toml_datum_t dns; - - *conf = udp4_default_conf; - udp4 = &conf->udp4; - - ip = toml_string_in(table, "ip"); - if (!ip.ok) { - log_err("No IP address specified!"); - goto fail_ip; + if (inet_pton(AF_INET6, host, &poa->udp6.ip_addr) == 1) { + poa->type = POA_UDP6; + poa->udp6.port = port; + return 0; } - if (inet_pton (AF_INET, ip.u.s, &udp4->ip_addr.s_addr) != 1) { - log_err("Failed to parse IPv4 address %s.", ip.u.s); - goto fail_addr; - } + log_err("Invalid IP address %s.", host); - port = toml_int_in(table, "port"); - if (port.ok) - udp4->port = port.u.i; + return -1; +} - dns = toml_string_in(table, "dns"); - if (dns.ok) { - if (inet_pton(AF_INET, dns.u.s, &udp4->dns_addr.s_addr) < 0) { - log_err("Failed to parse DNS address %s.", ip.u.s); - goto fail_dns; +/* Attaches every PoA in the "udp" or "eth" array; string or table. */ +static int toml_poa_array(toml_table_t * table, + pid_t pid, + const char * key) +{ + struct poa_spec poa; + toml_array_t * arr; + int n; + int i; + bool is_eth; + + arr = toml_array_in(table, key); + if (arr == NULL) { + /* A table here would otherwise attach nothing, silently. */ + if (toml_table_in(table, key) != NULL) { + log_err("A %s PoA is an array: %s = [...] " + "or [[%s]].", key, key, key); + return -1; } - free(dns.u.s); + return 0; } - free(ip.u.s); + is_eth = strcmp(key, "eth") == 0; - return 0; + n = toml_array_nelem(arr); - fail_dns: - free(dns.u.s); - fail_addr: - free(ip.u.s); - fail_ip: - return -1; -} + for (i = 0; i < n; i++) { + toml_datum_t s; + int ret; -static int toml_udp6(toml_table_t * table, - struct ipcp_config * conf) -{ - struct in6_addr ip6; - struct in6_addr dns6; - toml_datum_t ip; - toml_datum_t port; - toml_datum_t dns; - - *conf = udp6_default_conf; - ip6 = conf->udp6.ip_addr; - dns6 = conf->udp6.dns_addr; - - ip = toml_string_in(table, "ip"); - if (!ip.ok) { - log_err("No IP address specified!"); - goto fail_ip; - } + s = toml_string_at(arr, i); + if (s.ok) { + if (is_eth) + ret = poa_eth_set(&poa, s.u.s, + POA_ETHERTYPE); + else + ret = toml_poa_udp(s.u.s, &poa); - if (inet_pton (AF_INET6, ip.u.s, &ip6.s6_addr) != 1) { - log_err("Failed to parse IPv4 address %s.", ip.u.s); - goto fail_addr; - } + free(s.u.s); + } else { + toml_table_t * d = toml_table_at(arr, i); - port = toml_int_in(table, "port"); - if (port.ok) - conf->udp6.port = port.u.i; + if (d == NULL) { + log_err("Invalid %s PoA entry.", key); + return -1; + } + + if (is_eth) { + ret = toml_poa_eth(d, &poa); + } else { + toml_datum_t addr = toml_string_in(d, "addr"); + + if (!addr.ok) { + log_err("No addr for udp PoA."); + return -1; + } - dns = toml_string_in(table, "dns"); - if (dns.ok) { - if (inet_pton(AF_INET6, dns.u.s, &dns6.s6_addr) < 0) { - log_err("Failed to parse DNS address %s.", ip.u.s); - goto fail_dns; + ret = toml_poa_udp(addr.u.s, &poa); + free(addr.u.s); + } } - free(dns.u.s); - } + if (ret < 0) + return -1; - free(ip.u.s); + if (attach_ipcp(pid, &poa, true) < 0) + return -1; + } return 0; +} - fail_dns: - free(dns.u.s); - fail_addr: - free(ip.u.s); - fail_ip: - return -1; +static int toml_attach(toml_table_t * table, + pid_t pid) +{ + if (toml_poa_array(table, pid, "udp") < 0) + return -1; + + return toml_poa_array(table, pid, "eth"); } static int toml_broadcast(toml_table_t * table, @@ -265,15 +268,13 @@ static int toml_broadcast(toml_table_t * table, (void) table; (void) conf; - /* Nothing to do here. */ - return 0; } #define BETWEEN(a, b, c) ((a) >= (b) && (a) <= (c)) #define DHT(conf, x) (conf)->dht.params.x static int toml_dir(toml_table_t * table, - struct dir_config * conf) + struct dir_config * conf) { toml_datum_t dir; toml_datum_t alpha; @@ -594,6 +595,207 @@ static int toml_register(toml_table_t * table, return ret; } +/* Fills in a peer's eth PoA; dst MAC stays zero, the resolve marker. */ +static int toml_peer_eth(toml_table_t * tbl, + struct poa_addr * addr) +{ + toml_datum_t dev; + toml_datum_t et; + int ret = -1; + + dev = toml_string_in(tbl, "dev"); + + memset(addr, 0, sizeof(*addr)); + + addr->type = POA_ETH; + addr->eth.src.ethertype = POA_ETHERTYPE; + addr->eth.dst.ethertype = POA_ETHERTYPE; + + et = toml_int_in(tbl, "ethertype"); + if (et.ok) { + if (et.u.i < 0 || et.u.i > 0xFFFF) { + log_err("Invalid ethertype."); + goto fail; + } + + addr->eth.src.ethertype = et.u.i; + addr->eth.dst.ethertype = et.u.i; + } + + if (dev.ok) { + if (strlen(dev.u.s) > DEV_NAME_SIZE) { + log_err("Invalid device name %s.", dev.u.s); + goto fail; + } + + strcpy(addr->eth.src.dev, dev.u.s); + } + + ret = 0; + fail: + if (dev.ok) + free(dev.u.s); + + return ret; +} + +/* Same grammar as the CLI's udp keyword; see irm_utils.c parse_udp_str. */ +static int toml_udp_str(const char * str, + char * host, + int * port) +{ + struct in6_addr v6; + char buf[POA_HOST_STRLEN + 1]; + char * p; + char * end; + long n; + + *port = POA_UDP_PORT; + + if (strlen(str) > POA_HOST_STRLEN) + goto fail; + + strcpy(buf, str); + + if (buf[0] == '[') { + p = strchr(buf, ']'); + if (p == NULL) + goto fail; + + *p++ = '\0'; + + strcpy(host, buf + 1); + + if (*p == '\0') + return 0; + + if (*p != ':') + goto fail; + + ++p; + } else if (inet_pton(AF_INET6, buf, &v6) == 1) { + strcpy(host, buf); + return 0; + } else { + p = strrchr(buf, ':'); + if (p == NULL) { + strcpy(host, buf); + return 0; + } + + *p++ = '\0'; + + strcpy(host, buf); + } + + n = strtol(p, &end, 10); + if (*p == '\0' || *end != '\0' || n < 1 || n > 65535) + goto fail; + + *port = (int) n; + + return 0; + fail: + log_err("Invalid UDP address: %s.", str); + return -1; +} + +/* Fills in a peer's udp PoA; an unresolved name is left for the IRMd. */ +static int toml_peer_udp(const char * str, + struct poa_addr * addr) +{ + char host[POA_HOST_STRLEN + 1]; + int port; + + if (toml_udp_str(str, host, &port) < 0) + return -1; + + memset(addr, 0, sizeof(*addr)); + + if (inet_pton(AF_INET, host, &addr->udp4.ip_addr) == 1) { + addr->type = POA_UDP4; + addr->udp4.port = port; + return 0; + } + + if (inet_pton(AF_INET6, host, &addr->udp6.ip_addr) == 1) { + addr->type = POA_UDP6; + addr->udp6.port = port; + return 0; + } + + addr->type = POA_UDP; + addr->udp4.port = port; + + strcpy(addr->hostname, host); + + return 0; +} + +/* + * An entry is a name, or a table naming a PoA to reach it over. + * On entry, *paddr already points at the caller's struct poa_addr to + * fill in. Set to NULL wherever there is no PoA to dial: a bare + * dst-only table (recursive lookup) or any parse failure. + */ +static int toml_peer(toml_table_t * tbl, + char * dst, + struct poa_addr ** paddr) +{ + struct poa_addr * addr = *paddr; + toml_table_t * eth; + toml_datum_t name; + toml_datum_t udp; + int ret = -1; + + name = toml_string_in(tbl, "dst"); + if (!name.ok) { + log_err("PoA table entry has no dst."); + + *paddr = NULL; + return -1; + } + + if (strlen(name.u.s) > LAYER_NAME_SIZE) { + log_err("Destination name too long: %s.", name.u.s); + free(name.u.s); + + *paddr = NULL; + return -1; + } + + strcpy(dst, name.u.s); + free(name.u.s); + + eth = toml_table_in(tbl, "eth"); + udp = toml_string_in(tbl, "udp"); + if (eth != NULL && udp.ok) { + log_err("A PoA is eth or udp, not both."); + + *paddr = NULL; + goto fail; + } + + if (eth == NULL && !udp.ok) { + *paddr = NULL; + ret = 0; + goto fail; + } + + if (eth != NULL) + ret = toml_peer_eth(eth, addr); + else + ret = toml_peer_udp(udp.u.s, addr); + + if (ret < 0) + *paddr = NULL; + fail: + if (udp.ok) + free(udp.u.s); + + return ret; +} + static int toml_connect(toml_table_t * table, pid_t pid) { @@ -605,21 +807,40 @@ static int toml_connect(toml_table_t * table, if (conn == NULL) return 0; - for (i=0; ret == 0; i++) { - toml_datum_t dst; - qosspec_t qs = qos_raw; + for (i = 0; ret == 0; i++) { + toml_datum_t dst; + toml_table_t * tbl; + struct poa_addr addr; + struct poa_addr * paddr = &addr; + char buf[LAYER_NAME_SIZE + 1]; + const char * d; + qosspec_t qs = qos_raw; dst = toml_string_at(conn, i); - if (!dst.ok) - break; + if (dst.ok) { + d = dst.u.s; + paddr = NULL; + } else { + tbl = toml_table_at(conn, i); + if (tbl == NULL) + break; + + ret = toml_peer(tbl, buf, &paddr); + if (ret < 0) + break; + + d = buf; + } + + log_dbg("Connecting %d to %s", pid, d); - log_dbg("Connecting %d to %s", pid, dst.u.s); + ret = connect_ipcp_resolve(pid, d, MGMT_COMP, qs, paddr); - ret = connect_ipcp(pid, dst.u.s, MGMT_COMP, qs); if (ret == 0) - ret = connect_ipcp(pid, dst.u.s, DT_COMP, qs); + ret = connect_ipcp_resolve(pid, d, DT_COMP, qs, paddr); - free(dst.u.s); + if (dst.ok) + free(dst.u.s); } return ret; @@ -629,9 +850,11 @@ static int toml_ipcp(toml_table_t * table, struct ipcp_info * info, struct ipcp_config * conf) { - toml_datum_t bootstrap; - toml_datum_t enrol; - int ret; + toml_datum_t bootstrap; + toml_datum_t enrol; + toml_table_t * enrol_tbl; + bool have_enrol; + int ret; log_dbg("Found IPCP %s in configuration file.", info->name); @@ -643,21 +866,49 @@ static int toml_ipcp(toml_table_t * table, bootstrap = toml_string_in(table, "bootstrap"); enrol = toml_string_in(table, "enrol"); - if (bootstrap.ok && enrol.ok) { + enrol_tbl = enrol.ok ? NULL : toml_table_in(table, "enrol"); + + have_enrol = enrol.ok || enrol_tbl != NULL; + if (bootstrap.ok && have_enrol) { log_err("Ignoring bootstrap for IPCP %s.", info->name); free(bootstrap.u.s); bootstrap.ok = false; } - if (!bootstrap.ok && !enrol.ok) { + if (!bootstrap.ok && !have_enrol) { log_dbg("Nothing more to do for %s.", info->name); return 0; } - if (enrol.ok) { + /* Endpoints come first: enrolment reaches the peer over one. */ + if (toml_attach(table, info->pid) < 0) { + log_err("Failed to attach PoAs for %s.", info->name); + return -1; + } + + if (have_enrol) { struct layer_info layer; - ret = enroll_ipcp(info->pid, enrol.u.s); - free(enrol.u.s); + struct poa_addr addr; + struct poa_addr * paddr = &addr; + char buf[LAYER_NAME_SIZE + 1]; + const char * dst; + + if (enrol.ok) { + dst = enrol.u.s; + paddr = NULL; + } else { + if (toml_peer(enrol_tbl, buf, &paddr) < 0) { + log_err("Invalid enrol table for %s.", + info->name); + return -1; + } + dst = buf; + } + + ret = enroll_ipcp_resolve(info->pid, dst, paddr); + + if (enrol.ok) + free(enrol.u.s); if (ret < 0) { log_err("Failed to enrol %s.", info->name); return -1; @@ -694,18 +945,6 @@ static int toml_ipcp(toml_table_t * table, case IPCP_LOCAL: ret = toml_local(table, conf); break; - case IPCP_ETH_DIX: - ret = toml_eth_dix(table, conf); - break; - case IPCP_ETH_LLC: - ret = toml_eth_llc(table, conf); - break; - case IPCP_UDP4: - ret = toml_udp4(table, conf); - break; - case IPCP_UDP6: - ret = toml_udp6(table, conf); - break; case IPCP_BROADCAST: ret = toml_broadcast(table, conf); break; @@ -1031,14 +1270,6 @@ static int toml_toplevel(toml_table_t * table, return toml_name_list(subtable); else if (strcmp(key, "local") == 0) return toml_ipcp_list(subtable, IPCP_LOCAL); - else if (strcmp(key, "eth-dix") == 0) - return toml_ipcp_list(subtable, IPCP_ETH_DIX); - else if (strcmp(key, "eth-llc") == 0) - return toml_ipcp_list(subtable, IPCP_ETH_LLC); - else if (strcmp(key, "udp4") == 0) - return toml_ipcp_list(subtable, IPCP_UDP4); - else if (strcmp(key, "udp6") == 0) - return toml_ipcp_list(subtable, IPCP_UDP6); else if (strcmp(key, "broadcast") == 0) return toml_ipcp_list(subtable, IPCP_BROADCAST); else if (strcmp(key, "unicast") == 0) diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c index 7eccfc80..cd662221 100644 --- a/src/irmd/ipcp.c +++ b/src/irmd/ipcp.c @@ -34,6 +34,7 @@ #include <ouroboros/utils.h> #include "ipcp.h" +#include "reg/reg.h" #include <fcntl.h> #include <pthread.h> @@ -72,6 +73,10 @@ static char * str_ipcp_cmd(int code) return "alloc_resp"; case IPCP_MSG_CODE__IPCP_FLOW_DEALLOC: return "dealloc"; + case IPCP_MSG_CODE__IPCP_FLOW_UPDATE: + return "flow_update"; + case IPCP_MSG_CODE__IPCP_REPLY: + return "reply"; default: assert(false); return "unknown"; @@ -196,7 +201,9 @@ int ipcp_bootstrap(pid_t pid, msg.conf = ipcp_config_s_to_msg(conf); recv_msg = send_recv_ipcp_msg(pid, &msg); + ipcp_config_msg__free_unpacked(msg.conf, NULL); + if (recv_msg == NULL) return -EIPCP; @@ -225,9 +232,88 @@ int ipcp_bootstrap(pid_t pid, return ret; } -int ipcp_enroll(pid_t pid, - const char * dst, - struct layer_info * info) +ssize_t ipcp_list_poas(pid_t pid, + struct poa_spec ** eps) +{ + ipcp_msg_t msg = IPCP_MSG__INIT; + ipcp_msg_t * recv_msg; + size_t nr; + size_t i; + + if (eps == NULL) + return -EINVAL; + + *eps = NULL; + + msg.code = IPCP_MSG_CODE__IPCP_LIST_POAS; + + recv_msg = send_recv_ipcp_msg(pid, &msg); + if (recv_msg == NULL) + return -EIPCP; + + nr = recv_msg->n_poas; + if (nr == 0) { + ipcp_msg__free_unpacked(recv_msg, NULL); + return 0; + } + + *eps = malloc(nr * sizeof(**eps)); + if (*eps == NULL) { + ipcp_msg__free_unpacked(recv_msg, NULL); + return -ENOMEM; + } + + for (i = 0; i < nr; i++) + (*eps)[i] = poa_spec_msg_to_s(recv_msg->poas[i]); + + ipcp_msg__free_unpacked(recv_msg, NULL); + + return (ssize_t) nr; +} + +int ipcp_attach(pid_t pid, + const struct poa_spec * poa, + bool attach) +{ + ipcp_msg_t msg = IPCP_MSG__INIT; + ipcp_msg_t * recv_msg; + int ret; + + if (poa == NULL) + return -EINVAL; + + if (attach) + msg.code = IPCP_MSG_CODE__IPCP_ATTACH; + else + msg.code = IPCP_MSG_CODE__IPCP_DETACH; + + msg.poa = poa_spec_s_to_msg(poa); + if (msg.poa == NULL) + return -EINVAL; + + recv_msg = send_recv_ipcp_msg(pid, &msg); + + poa_spec_msg__free_unpacked(msg.poa, NULL); + + if (recv_msg == NULL) + return -EIPCP; + + if (!recv_msg->has_result) { + ipcp_msg__free_unpacked(recv_msg, NULL); + return -EIPCP; + } + + ret = recv_msg->result; + + ipcp_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + +int ipcp_enroll(pid_t pid, + const char * dst, + const struct poa_addr * addr, + struct layer_info * info) { ipcp_msg_t msg = IPCP_MSG__INIT; ipcp_msg_t * recv_msg; @@ -239,7 +325,16 @@ int ipcp_enroll(pid_t pid, msg.code = IPCP_MSG_CODE__IPCP_ENROLL; msg.dst = (char *) dst; + if (addr != NULL) { + msg.peer = poa_addr_s_to_msg(addr); + if (msg.peer == NULL) + return -ENOMEM; + } + recv_msg = send_recv_ipcp_msg(pid, &msg); + + if (msg.peer != NULL) + poa_addr_msg__free_unpacked(msg.peer, NULL); if (recv_msg == NULL) return -EIPCP; @@ -267,10 +362,11 @@ int ipcp_enroll(pid_t pid, return 0; } -int ipcp_connect(pid_t pid, - const char * dst, - const char * component, - qosspec_t qs) +int ipcp_connect(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + const struct poa_addr * addr) { ipcp_msg_t msg = IPCP_MSG__INIT; ipcp_msg_t * recv_msg; @@ -283,8 +379,21 @@ int ipcp_connect(pid_t pid, msg.pid = pid; msg.qosspec = qos_spec_s_to_msg(&qs); + if (addr != NULL) { + msg.peer = poa_addr_s_to_msg(addr); + if (msg.peer == NULL) { + free(msg.qosspec); + return -ENOMEM; + } + } + recv_msg = send_recv_ipcp_msg(pid, &msg); + + if (msg.peer != NULL) + poa_addr_msg__free_unpacked(msg.peer, NULL); + free(msg.qosspec); + if (recv_msg == NULL) return -EIPCP; @@ -457,6 +566,8 @@ int ipcp_flow_update(const struct flow_info * flow, msg.has_pk = true; msg.pk.data = data.data; msg.pk.len = data.len; + msg.has_is_poa = true; + msg.is_poa = reg_flow_is_poa(flow->id); recv_msg = send_recv_ipcp_msg(flow->n_1_pid, &msg); if (recv_msg == NULL) { @@ -538,6 +649,8 @@ int ipcp_flow_alloc_resp(const struct flow_info * flow, msg.has_pk = response == 0; msg.pk.data = data.data; msg.pk.len = data.len; + msg.has_is_poa = true; + msg.is_poa = reg_flow_is_poa(flow->id); recv_msg = send_recv_ipcp_msg(flow->n_1_pid, &msg); if (recv_msg == NULL) @@ -567,6 +680,8 @@ int ipcp_flow_dealloc(pid_t pid, msg.flow_id = flow_id; msg.has_timeo_sec = true; msg.timeo_sec = timeo; + msg.has_is_poa = true; + msg.is_poa = reg_flow_is_poa(flow_id); recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) diff --git a/src/irmd/ipcp.h b/src/irmd/ipcp.h index 8d06623c..1f257e7d 100644 --- a/src/irmd/ipcp.h +++ b/src/irmd/ipcp.h @@ -27,48 +27,57 @@ #ifndef OUROBOROS_IRMD_IPCP_H #define OUROBOROS_IRMD_IPCP_H -int ipcp_enroll(pid_t pid, - const char * dst, - struct layer_info * info); +int ipcp_enroll(pid_t pid, + const char * dst, + const struct poa_addr * addr, + struct layer_info * info); -int ipcp_bootstrap(pid_t pid, - struct ipcp_config * conf, - struct layer_info * info); +int ipcp_attach(pid_t pid, + const struct poa_spec * poa, + bool attach); -int ipcp_connect(pid_t pid, - const char * dst, - const char * component, - qosspec_t qs); +ssize_t ipcp_list_poas(pid_t pid, + struct poa_spec ** eps); -int ipcp_disconnect(pid_t pid, - const char * dst, - const char * component); +int ipcp_bootstrap(pid_t pid, + struct ipcp_config * conf, + struct layer_info * info); -int ipcp_reg(pid_t pid, - const buffer_t hash); +int ipcp_connect(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + const struct poa_addr * addr); -int ipcp_unreg(pid_t pid, +int ipcp_disconnect(pid_t pid, + const char * dst, + const char * component); + +int ipcp_reg(pid_t pid, const buffer_t hash); -int ipcp_query(pid_t pid, - const buffer_t dst); +int ipcp_unreg(pid_t pid, + const buffer_t hash); + +int ipcp_query(pid_t pid, + const buffer_t dst); -int ipcp_flow_alloc(const struct flow_info * flow, - const buffer_t hash, - const buffer_t data); +int ipcp_flow_alloc(const struct flow_info * flow, + const buffer_t hash, + const buffer_t data); -int ipcp_flow_join(const struct flow_info * flow, - const buffer_t dst); +int ipcp_flow_join(const struct flow_info * flow, + const buffer_t dst); -int ipcp_flow_alloc_resp(const struct flow_info * flow, - int response, - const buffer_t data); +int ipcp_flow_alloc_resp(const struct flow_info * flow, + int response, + const buffer_t data); -int ipcp_flow_dealloc(pid_t pid, - int flow_id, - time_t timeo); +int ipcp_flow_dealloc(pid_t pid, + int flow_id, + time_t timeo); -int ipcp_flow_update(const struct flow_info * flow, - const buffer_t data); +int ipcp_flow_update(const struct flow_info * flow, + const buffer_t data); #endif /* OUROBOROS_IRMD_IPCP_H */ diff --git a/src/irmd/irmd.h b/src/irmd/irmd.h index f88378ad..9d42e248 100644 --- a/src/irmd/irmd.h +++ b/src/irmd/irmd.h @@ -26,29 +26,48 @@ #include <ouroboros/ipcp.h> #include <ouroboros/irm.h> -int create_ipcp(struct ipcp_info * info); +int create_ipcp(struct ipcp_info * info); -int bootstrap_ipcp(pid_t pid, - struct ipcp_config * conf); +int bootstrap_ipcp(pid_t pid, + struct ipcp_config * conf); -int enroll_ipcp(pid_t pid, - const char * dst); +int enroll_ipcp(pid_t pid, + const char * dst, + const struct poa_addr * addr); -int connect_ipcp(pid_t pid, - const char * dst, - const char * component, - qosspec_t qs); +int enroll_ipcp_resolve(pid_t pid, + const char * dst, + struct poa_addr * addr); -int name_create(struct name_info * info); +int attach_ipcp(pid_t pid, + const struct poa_spec * poa, + bool attach); -int name_reg(const char * name, - pid_t pid); +ssize_t list_poas(pid_t pid, + struct poa_spec ** eps); -int bind_process(pid_t pid, - const char * name); +int connect_ipcp(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + const struct poa_addr * addr); -int bind_program(char ** exec, - const char * name, - uint8_t flags); +int connect_ipcp_resolve(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + struct poa_addr * addr); + +int name_create(struct name_info * info); + +int name_reg(const char * name, + pid_t pid); + +int bind_process(pid_t pid, + const char * name); + +int bind_program(char ** exec, + const char * name, + uint8_t flags); #endif /* OUROBOROS_IRMD_H*/ diff --git a/src/irmd/main.c b/src/irmd/main.c index 19be4ab9..e587a552 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -61,6 +61,7 @@ #include <dirent.h> #include <grp.h> +#include <netdb.h> #include <pwd.h> #include <signal.h> #include <spawn.h> @@ -225,18 +226,6 @@ static pid_t spawn_ipcp(struct ipcp_info * info) case IPCP_BROADCAST: exec_name = IPCP_BROADCAST_EXEC; break; - case IPCP_UDP4: - exec_name = IPCP_UDP4_EXEC; - break; - case IPCP_UDP6: - exec_name = IPCP_UDP6_EXEC; - break; - case IPCP_ETH_LLC: - exec_name = IPCP_ETH_LLC_EXEC; - break; - case IPCP_ETH_DIX: - exec_name = IPCP_ETH_DIX_EXEC; - break; case IPCP_LOCAL: exec_name = IPCP_LOCAL_EXEC; break; @@ -367,9 +356,6 @@ int bootstrap_ipcp(pid_t pid, goto fail; } - if (conf->type == IPCP_UDP4 || conf->type == IPCP_UDP6) - conf->layer_info.dir_hash_algo = (enum pol_dir_hash) HASH_MD5; - if (ipcp_bootstrap(pid, conf, &layer)) { log_err("Could not bootstrap IPCP."); goto fail; @@ -389,8 +375,55 @@ int bootstrap_ipcp(pid_t pid, return -1; } -int enroll_ipcp(pid_t pid, - const char * dst) +ssize_t list_poas(pid_t pid, + struct poa_spec ** eps) +{ + struct ipcp_info info; + + info.pid = pid; + if (reg_get_ipcp(&info, NULL) < 0) { + log_err("Could not find IPCP %d.", pid); + return -1; + } + + if (info.type != IPCP_UNICAST && info.type != IPCP_BROADCAST) + return 0; /* nothing it could be attached to */ + + return ipcp_list_poas(pid, eps); +} + +/* Only the types that can carry a PoA may take one. */ +int attach_ipcp(pid_t pid, + const struct poa_spec * poa, + bool attach) +{ + struct ipcp_info info; + + info.pid = pid; + if (reg_get_ipcp(&info, NULL) < 0) { + log_err("Could not find IPCP %d.", pid); + return -1; + } + + if (info.type != IPCP_UNICAST && info.type != IPCP_BROADCAST) { + log_err("IPCP %d does not support PoAs.", pid); + return -1; + } + + if (ipcp_attach(pid, poa, attach) < 0) { + log_err("Could not %s IPCP %d.", + attach ? "attach" : "detach", pid); + return -1; + } + + log_info("%s IPCP %d.", attach ? "Attached" : "Detached", pid); + + return 0; +} + +int enroll_ipcp(pid_t pid, + const char * dst, + const struct poa_addr * addr) { struct layer_info layer; struct ipcp_info info; @@ -402,7 +435,7 @@ int enroll_ipcp(pid_t pid, goto fail; } - if (ipcp_enroll(pid, dst, &layer) < 0) { + if (ipcp_enroll(pid, dst, addr, &layer) < 0) { log_err("Could not enroll IPCP %d.", pid); goto fail; } @@ -421,10 +454,11 @@ int enroll_ipcp(pid_t pid, return -1; } -int connect_ipcp(pid_t pid, - const char * dst, - const char * component, - qosspec_t qs) +int connect_ipcp(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + const struct poa_addr * addr) { struct ipcp_info info; @@ -442,7 +476,7 @@ int connect_ipcp(pid_t pid, log_dbg("Connecting %s to %s.", component, dst); - if (ipcp_connect(pid, dst, component, qs)) { + if (ipcp_connect(pid, dst, component, qs, addr) < 0) { log_err("Could not connect IPCP %d to %s.", pid, dst); return -EPERM; } @@ -453,6 +487,172 @@ int connect_ipcp(pid_t pid, return 0; } +/* Resolve the dial name, if any, and fill in one record. */ +static int poa_addr_resolve(struct poa_addr * addr, + struct addrinfo ** res) +{ + struct addrinfo hints; + + *res = NULL; + + if (addr == NULL) + return 0; + + if (addr->hostname[0] == '\0') + return addr->type == POA_UDP ? -EINVAL : 0; + + if (addr->type != POA_UDP) + return -EINVAL; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + if (getaddrinfo(addr->hostname, NULL, &hints, res) != 0) { + log_err("Failed to resolve %s.", addr->hostname); + return -EADDRNOTAVAIL; + } + + return 0; +} + +static void poa_addr_from_ai(struct poa_addr * addr, + const struct addrinfo * ai, + uint16_t port) +{ + struct sockaddr_in * in; + struct sockaddr_in6 * in6; + + if (ai->ai_family == AF_INET) { + in = (struct sockaddr_in *) ai->ai_addr; + addr->type = POA_UDP4; + addr->udp4.ip_addr = in->sin_addr; + addr->udp4.port = port; + } else { + in6 = (struct sockaddr_in6 *) ai->ai_addr; + addr->type = POA_UDP6; + addr->udp6.ip_addr = in6->sin6_addr; + addr->udp6.port = port; + } +} + +/* Skip families without an attached PoA; keep all if none reported. */ +static void poa_families(pid_t pid, + bool * v4, + bool * v6) +{ + struct poa_spec * eps; + ssize_t n; + ssize_t i; + + eps = NULL; + + *v4 = false; + *v6 = false; + + n = list_poas(pid, &eps); + for (i = 0; i < n; i++) { + if (eps[i].type == POA_UDP4) + *v4 = true; + + if (eps[i].type == POA_UDP6) + *v6 = true; + } + + free(eps); + + if (!*v4 && !*v6) { + *v4 = true; + *v6 = true; + } +} + +/* Try each resolved record in order until an enrolment succeeds. */ +int enroll_ipcp_resolve(pid_t pid, + const char * dst, + struct poa_addr * addr) +{ + struct addrinfo * res; + struct addrinfo * ai; + uint16_t port; + bool v4; + bool v6; + int ret; + + ret = poa_addr_resolve(addr, &res); + if (ret < 0) + return ret; + + if (res == NULL) + return enroll_ipcp(pid, dst, addr); + + port = addr->udp4.port; /* POA_UDP parks it there */ + + poa_families(pid, &v4, &v6); + + ret = -EADDRNOTAVAIL; + + for (ai = res; ai != NULL; ai = ai->ai_next) { + if ((ai->ai_family == AF_INET && !v4) + || (ai->ai_family == AF_INET6 && !v6)) + continue; + + poa_addr_from_ai(addr, ai, port); + + ret = enroll_ipcp(pid, dst, addr); + if (ret == 0) + break; + } + + freeaddrinfo(res); + + return ret; +} + +/* Try each resolved record in order until a connect succeeds. */ +int connect_ipcp_resolve(pid_t pid, + const char * dst, + const char * component, + qosspec_t qs, + struct poa_addr * addr) +{ + struct addrinfo * res; + struct addrinfo * ai; + uint16_t port; + bool v4; + bool v6; + int ret; + + ret = poa_addr_resolve(addr, &res); + if (ret < 0) + return ret; + + if (res == NULL) + return connect_ipcp(pid, dst, component, qs, addr); + + port = addr->udp4.port; /* POA_UDP parks it there */ + + poa_families(pid, &v4, &v6); + + ret = -EADDRNOTAVAIL; + + for (ai = res; ai != NULL; ai = ai->ai_next) { + if ((ai->ai_family == AF_INET && !v4) + || (ai->ai_family == AF_INET6 && !v6)) + continue; + + poa_addr_from_ai(addr, ai, port); + + ret = connect_ipcp(pid, dst, component, qs, addr); + if (ret == 0) + break; + } + + freeaddrinfo(res); + + return ret; +} + static int disconnect_ipcp(pid_t pid, const char * dst, const char * component) @@ -882,6 +1082,22 @@ static void __cleanup_flow(void * flow) reg_destroy_flow(((struct flow_info *) flow)->id); } +/* + * A PoA flow is secured as the IPCP that owns it: trust is in the + * peer itself. Without a security config for that name the flow + * stays in the clear. + */ +static void poa_name_info(const char * name, + struct name_info * info) +{ + if (reg_get_name_info(name, info) == 0) + return; + + memset(info, 0, sizeof(*info)); + + strcpy(info->name, name); +} + static int flow_accept(struct flow_info * flow, buffer_t * data, struct timespec * abstime, @@ -942,7 +1158,9 @@ static int flow_accept(struct flow_info * flow, goto fail_oap; } - if (reg_get_name_info(name, &info) < 0) { + if (reg_flow_is_poa(flow->id)) { + poa_name_info(name, &info); + } else if (reg_get_name_info(name, &info) < 0) { log_err("Failed to get name info for %s.", name); err = -ENAME; goto fail_oap; @@ -1262,7 +1480,7 @@ static int flow_alloc_direct(const char * dst, return -EAGAIN; } - if (oap_cli_prepare(&ctx, info, &req_hdr, *data, false) < 0) { + if (oap_cli_prepare(&ctx, info, NULL, &req_hdr, *data, false) < 0) { log_err("Failed to prepare OAP for %s.", dst); return -EBADF; } @@ -1295,7 +1513,7 @@ static int flow_alloc_direct(const char * dst, return -ETIMEDOUT; } - err = oap_cli_complete(ctx, info, resp_hdr, data, sk, NULL, NULL); + err = oap_cli_complete(ctx, resp_hdr, data, sk, NULL, NULL); if (err < 0) { log_err("OAP completion failed for %s.", dst); freebuf(resp_hdr); @@ -1378,7 +1596,7 @@ static int flow_alloc(const char * dst, goto fail_prepare; } - if (oap_cli_prepare(&ctx, &info, &req_hdr, *data, false) < 0) { + if (oap_cli_prepare(&ctx, &info, NULL, &req_hdr, *data, false) < 0) { log_err("Failed to prepare OAP request for %s.", dst); err = -EBADF; goto fail_prepare; @@ -1410,7 +1628,7 @@ static int flow_alloc(const char * dst, goto fail_peer; } - err = oap_cli_complete(ctx, &info, resp_hdr, data, sk, NULL, &peer_crt); + err = oap_cli_complete(ctx, resp_hdr, data, sk, NULL, &peer_crt); if (err < 0) { log_err("OAP completion failed for %s.", dst); goto fail_complete; @@ -1444,6 +1662,199 @@ static int flow_alloc(const char * dst, return err; } +/* Creates the flow and prepares the key exchange the IPCP will carry. */ +/* The N-1 is only known once the flow exists. */ +static int poa_alloc(struct flow_info * flow, + const char * dst, + buffer_t * data) +{ + struct ipcp_info ipcp; + struct layer_info layer; + struct name_info info; + buffer_t req_hdr = BUF_INIT; + void * ctx; + int err; + + ipcp.pid = flow->n_pid; + if (reg_get_ipcp(&ipcp, &layer) < 0) { + log_err("No IPCP with pid %d.", flow->n_pid); + + err = -EIPCP; + goto fail_flow; + } + + flow->n_1_pid = 0; + if (reg_create_flow(flow) < 0) { + log_err("Failed to create PoA flow."); + + err = -EBADF; + goto fail_flow; + } + + reg_set_name_for_flow_id(ipcp.name, flow->id); + + if (reg_flow_set_poa(flow->id) < 0) { + err = -EBADF; + goto fail_prepare; + } + + flow->uid = reg_get_proc_uid(flow->n_pid); + flow->n_1_pid = flow->n_pid; /* the IPCP is its own N-1 */ + if (reg_prepare_flow_alloc(flow) < 0) { + log_err("Failed to prepare PoA flow allocation."); + + err = -EBADF; + goto fail_prepare; + } + + poa_name_info(ipcp.name, &info); + + if (oap_cli_prepare(&ctx, &info, dst, &req_hdr, *data, false) < 0) { + log_err("Failed to prepare OAP request for %s.", ipcp.name); + + err = -EBADF; + goto fail_prepare; + } + + if (reg_flow_set_oap_ctx(flow->id, ctx) < 0) { + err = -EBADF; + goto fail_ctx; + } + + log_info("Allocating PoA flow %d for %d as %s.", + flow->id, flow->n_pid, ipcp.name); + + *data = req_hdr; + + return 0; + + fail_ctx: + freebuf(req_hdr); + oap_ctx_free(ctx); + fail_prepare: + reg_destroy_flow(flow->id); + fail_flow: + return err; +} + +/* Completes the key exchange once the IPCP has the peer's response. */ +/* + * We present the PoA's own credentials and expect the peer to present + * dst's: the address only says how to reach it. oap_cli_complete + * frees the ctx on every path. + */ +static int poa_complete(struct flow_info * flow, + int response, + buffer_t * data, + struct crypt_sk * sk) +{ + struct name_info info; + buffer_t peer_crt = BUF_INIT; + buffer_t out = BUF_INIT; + buffer_t empty = BUF_INIT; + char name[NAME_SIZE + 1]; + void * ctx; + int err; + + ctx = reg_flow_take_oap_ctx(flow->id); + if (ctx == NULL) { + log_err("No pending PoA flow %d.", flow->id); + return -EBADF; + } + + if (response < 0) { + log_dbg("PoA flow %d refused: %d.", flow->id, response); + + err = response; + goto fail; + } + + if (reg_get_name_for_flow_id(name, flow->id) < 0) { + err = -EBADF; + goto fail; + } + + poa_name_info(name, &info); + + err = oap_cli_complete(ctx, *data, &out, sk, NULL, &peer_crt); + if (err < 0) { + log_err("OAP completion failed for %s.", name); + + ctx = NULL; + goto fail; + } + + if (sk->nid != NID_undef) + reg_flow_set_rekey(flow->id, true, peer_crt); + + flow->state = FLOW_ALLOCATED; + if (reg_respond_alloc(flow, &empty, 0) < 0) { + log_err("Failed to update PoA flow %d.", flow->id); + + err = -EBADF; + goto fail_crt; + } + + log_info("PoA flow %d allocated to %s.", flow->id, name); + + freebuf(peer_crt); + freebuf(out); + + return 0; + + fail_crt: + freebuf(peer_crt); + freebuf(out); + fail: + oap_ctx_free(ctx); + reg_destroy_flow(flow->id); + return err; +} + +/* A peer requested a flow on a PoA of this IPCP. */ +static int poa_req_arr(struct flow_info * flow, + buffer_t * data) +{ + struct ipcp_info ipcp; + struct layer_info layer; + int ret; + + ipcp.pid = flow->n_1_pid; + if (reg_get_ipcp(&ipcp, &layer) < 0) { + log_err("No IPCP with pid %d.", flow->n_1_pid); + + ret = -EIPCP; + goto fail; + } + + log_info("PoA flow request arrived for %s.", ipcp.name); + + ret = wait_for_accept(ipcp.name); + if (ret < 0) { + log_err("No active process for %s.", ipcp.name); + goto fail; + } + + flow->id = ret; + flow->state = FLOW_ALLOCATED; + if (reg_flow_set_poa(flow->id) < 0) { + ret = -EBADF; + goto fail; + } + + reg_set_name_for_flow_id(ipcp.name, flow->id); + + ret = reg_respond_accept(flow, data); + if (ret < 0) { + log_err("Failed to respond to PoA flow %d.", flow->id); + goto fail; + } + + return 0; + fail: + return ret; +} + static int flow_alloc_reply(struct flow_info * flow, int response, buffer_t * data) @@ -1596,6 +2007,11 @@ static int rekey_name_info(int flow_id, if (reg_get_name_for_flow_id(name, flow_id) < 0) return -1; + if (reg_flow_is_poa(flow_id)) { + poa_name_info(name, info); + return 0; + } + return reg_get_name_info(name, info); } @@ -1667,7 +2083,7 @@ static void rekey_do_initiate(struct list_head * tbl, goto fail; } - if (oap_cli_prepare(&ctx, &name, &req, data, true) < 0) { + if (oap_cli_prepare(&ctx, &name, NULL, &req, data, true) < 0) { log_err("Failed to prepare re-key for flow %d.", flow_id); goto fail; } @@ -1758,7 +2174,7 @@ static void rekey_do_complete(struct list_head * tbl, reg_flow_get_peer_crt(flow_id, &crt); /* oap_cli_complete frees the ctx on every path. */ - if (oap_cli_complete(e->ctx, &info, buf, &data, &sk, &crt, NULL) < 0) { + if (oap_cli_complete(e->ctx, buf, &data, &sk, &crt, NULL) < 0) { log_warn("Failed to complete re-key for flow %d.", flow_id); e->ctx = NULL; goto finish_clear; @@ -1933,7 +2349,7 @@ static void rekey_do_direct(int flow_id) return; } - if (oap_cli_prepare(&ctx, &info, &req, data, true) < 0) { + if (oap_cli_prepare(&ctx, &info, NULL, &req, data, true) < 0) { log_err("Failed to prepare re-key for flow %d.", flow_id); reg_flow_clear_in_flight(flow_id); return; @@ -2307,6 +2723,10 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg, pid_t cpid; irm_msg_t * ret_msg; buffer_t data; + struct poa_addr poa_addr; + struct poa_addr * pa; + struct poa_spec poa_spec; + struct poa_spec * eps = NULL; memset(&flow, 0, sizeof(flow)); @@ -2350,11 +2770,74 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg, res = bootstrap_ipcp(msg->pid, &conf); break; case IRM_MSG_CODE__IRM_ENROLL_IPCP: - res = enroll_ipcp(msg->pid, msg->dst); + if (msg->peer != NULL) { + poa_addr = poa_addr_msg_to_s(msg->peer); + if (poa_addr.type == POA_INVALID) { + res = -EINVAL; + break; + } + } + + if (msg->conf != NULL) + conf = ipcp_config_msg_to_s(msg->conf); + res = enroll_ipcp_resolve(msg->pid, msg->dst, + msg->peer != NULL ? &poa_addr : NULL); + break; + case IRM_MSG_CODE__IRM_ATTACH_IPCP: + poa_spec = poa_spec_msg_to_s(msg->poa); + if (poa_spec.type == POA_INVALID) { + res = -EINVAL; + break; + } + + res = attach_ipcp(msg->pid, &poa_spec, true); + break; + case IRM_MSG_CODE__IRM_DETACH_IPCP: + poa_spec = poa_spec_msg_to_s(msg->poa); + if (poa_spec.type == POA_INVALID) { + res = -EINVAL; + break; + } + + res = attach_ipcp(msg->pid, &poa_spec, false); + break; + case IRM_MSG_CODE__IRM_LIST_POAS: + res = list_poas(msg->pid, &eps); + if (res > 0) { + ssize_t i; + ret_msg->poas = malloc(res * sizeof(*ret_msg->poas)); + if (ret_msg->poas == NULL) { + free(eps); + + res = -ENOMEM; + break; + } + for (i = 0; i < res; i++) { + ret_msg->poas[i] = poa_spec_s_to_msg(&eps[i]); + if (ret_msg->poas[i] == NULL) + break; + ret_msg->n_poas++; + } + res = i == res ? 0 : -ENOMEM; + } + free(eps); break; case IRM_MSG_CODE__IRM_CONNECT_IPCP: flow.qs = qos_spec_msg_to_s(msg->qosspec); - res = connect_ipcp(msg->pid, msg->dst, msg->comp, flow.qs); + + pa = NULL; + + if (msg->peer != NULL) { + poa_addr = poa_addr_msg_to_s(msg->peer); + if (poa_addr.type == POA_INVALID) { + res = -EINVAL; + break; + } + pa = &poa_addr; + } + + res = connect_ipcp_resolve(msg->pid, msg->dst, msg->comp, + flow.qs, pa); break; case IRM_MSG_CODE__IRM_DISCONNECT_IPCP: res = disconnect_ipcp(msg->pid, msg->dst, msg->comp); @@ -2499,6 +2982,67 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg, if (res == 0) ret_msg->flow_info = flow_info_s_to_msg(&flow); break; + case IRM_MSG_CODE__IRM_POA_FLOW_ALLOC: + flow = flow_info_msg_to_s(msg->flow_info); + + clrbuf(data); + + res = poa_alloc(&flow, msg->dst, &data); + if (res == 0) { + ret_msg->flow_info = flow_info_s_to_msg(&flow); + ret_msg->has_pk = true; + ret_msg->pk.len = data.len; + ret_msg->pk.data = data.data; + + clrbuf(data); + } + break; + case IRM_MSG_CODE__IRM_POA_FLOW_ALLOC_R: + data.len = msg->pk.len; + data.data = msg->pk.data; + msg->pk.data = NULL; /* pass data */ + msg->pk.len = 0; + flow = flow_info_msg_to_s(msg->flow_info); + sk.key = kbuf; + res = poa_complete(&flow, msg->response, &data, &sk); + + freebuf(data); + + if (res != 0) + break; + + ret_msg->flow_info = flow_info_s_to_msg(&flow); + ret_msg->has_cipher_nid = true; + ret_msg->cipher_nid = sk.nid; + + if (sk.nid == NID_undef) + break; + + hbuf = malloc(SYMMKEYSZ); + if (hbuf == NULL) { + log_err("Failed to malloc key buf"); + + res = -ENOMEM; + break; + } + + memcpy(hbuf, kbuf, SYMMKEYSZ); + + ret_msg->sym_key.data = hbuf; + ret_msg->sym_key.len = SYMMKEYSZ; + ret_msg->has_sym_key = true; + break; + case IRM_MSG_CODE__IPCP_POA_FLOW_REQ_ARR: + data.len = msg->pk.len; + data.data = msg->pk.data; + msg->pk.data = NULL; /* pass data */ + msg->pk.len = 0; + flow = flow_info_msg_to_s(msg->flow_info); + + res = poa_req_arr(&flow, &data); + if (res == 0) + ret_msg->flow_info = flow_info_s_to_msg(&flow); + break; case IRM_MSG_CODE__IPCP_FLOW_ALLOC_REPLY: data.len = msg->pk.len; data.data = msg->pk.data; diff --git a/src/irmd/oap.h b/src/irmd/oap.h index 86f11e21..e9d7511b 100644 --- a/src/irmd/oap.h +++ b/src/irmd/oap.h @@ -40,21 +40,21 @@ int oap_auth_add_ca_crt(void * crt); int oap_auth_add_chain_crt(void * crt); /* -* Prepare OAP request header for server, returns context -* Passes client data for srv, returns srv data for client -* rekey forces ephemeral server-encap KEX (no client-encap; preserves FS/PCS) -*/ + * Prepares the request header and returns the context. info holds the + * credentials we present, peer the name the server certificate must + * carry (NULL expects info->name); rekey forces an ephemeral KEX. + */ int oap_cli_prepare(void ** ctx, const struct name_info * info, + const char * peer, buffer_t * req_buf, buffer_t data, bool rekey); /* - * Server processes header, creates response header, returns secret key. - * data is in/out: input=srv data to send, output=cli data received. - * rekey drops the cert and verifies against cached_crt; peer_crt (or NULL) - * receives a copy of the peer cert to cache at the initial handshake. + * Answers the request header and returns the secret key. data is + * in/out; rekey verifies against cached_crt, and peer_crt takes a copy + * of the peer cert to cache at the initial handshake. */ int oap_srv_process(const struct name_info * info, buffer_t req_buf, @@ -70,13 +70,12 @@ int oap_srv_process(const struct name_info * info, * cached_crt verifies a cert-less re-key; peer_crt (or NULL) receives a * copy of the peer cert to cache at the initial handshake. */ -int oap_cli_complete(void * ctx, - const struct name_info * info, - buffer_t rsp_buf, - buffer_t * data, - struct crypt_sk * sk, - const buffer_t * cached_crt, - buffer_t * peer_crt); +int oap_cli_complete(void * ctx, + buffer_t rsp_buf, + buffer_t * data, + struct crypt_sk * sk, + const buffer_t * cached_crt, + buffer_t * peer_crt); /* Free OAP state (on failure before complete) */ void oap_ctx_free(void * ctx); diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c index ebfcd71f..2203596f 100644 --- a/src/irmd/oap/cli.c +++ b/src/irmd/oap/cli.c @@ -50,6 +50,7 @@ struct oap_cli_ctx { uint8_t __id[OAP_ID_SIZE]; buffer_t id; + char peer[NAME_SIZE + 1]; /* expected server name */ uint8_t kex_buf[CRYPT_KEY_BUFSZ]; uint8_t req_hash[MAX_HASH_SIZE]; size_t req_hash_len; @@ -241,6 +242,7 @@ static int do_client_kex_prepare(const char * server_name, int oap_cli_prepare(void ** ctx, const struct name_info * info, + const char * peer, buffer_t * req_buf, buffer_t data, bool rekey) @@ -259,6 +261,11 @@ int oap_cli_prepare(void ** ctx, clrbuf(*req_buf); *ctx = NULL; + if (peer != NULL && strlen(peer) > NAME_SIZE) { + log_err("Peer name too long."); + return -EINVAL; + } + /* Allocate ctx to carry between prepare and complete */ s = malloc(sizeof(*s)); if (s == NULL) { @@ -269,13 +276,15 @@ int oap_cli_prepare(void ** ctx, memset(s, 0, sizeof(*s)); OAP_CLI_CTX_INIT(s); + strcpy(s->peer, peer != NULL ? peer : info->name); + /* Generate session ID */ if (random_buffer(s->__id, OAP_ID_SIZE) < 0) { log_err("Failed to generate OAP session ID."); goto fail_id; } - log_dbg_id(s->id.data, "Preparing OAP request for %s.", info->name); + log_dbg_id(s->id.data, "Preparing OAP request for %s.", s->peer); /* Load client credentials */ if (load_cli_credentials(info, &pkp, &crt) < 0) { @@ -315,7 +324,7 @@ int oap_cli_prepare(void ** ctx, oap_hdr_init(&s->local_hdr, s->id, s->kex_buf, data, s->scfg.c.nid); - if (do_client_kex_prepare(info->name, s) < 0) { + if (do_client_kex_prepare(s->peer, s) < 0) { log_err_id(s->id.data, "Failed to prepare client KEX."); goto fail_kex; } @@ -482,7 +491,8 @@ static int do_client_kex_complete(struct oap_cli_ctx * s, } SET_KEX_CIPHER(scfg, peer_hdr->cipher_str); - if (crypt_validate_nid(scfg->c.nid) < 0) { + + if (crypt_cipher_rank(scfg->c.nid) < 0) { log_err_id(id, "Server cipher '%s' not supported.", peer_hdr->cipher_str); return -ENOTSUP; @@ -518,13 +528,12 @@ static int do_client_kex_complete(struct oap_cli_ctx * s, return do_client_kex_complete_dhe(s, peer_hdr, sk); } -int oap_cli_complete(void * ctx, - const struct name_info * info, - buffer_t rsp_buf, - buffer_t * data, - struct crypt_sk * sk, - const buffer_t * cached_crt, - buffer_t * peer_crt) +int oap_cli_complete(void * ctx, + buffer_t rsp_buf, + buffer_t * data, + struct crypt_sk * sk, + const buffer_t * cached_crt, + buffer_t * peer_crt) { struct oap_cli_ctx * s = ctx; struct oap_hdr peer_hdr; @@ -538,7 +547,6 @@ int oap_cli_complete(void * ctx, int rc; assert(ctx != NULL); - assert(info != NULL); assert(data != NULL); assert(sk != NULL); @@ -550,7 +558,7 @@ int oap_cli_complete(void * ctx, id = s->id.data; - log_dbg_id(id, "Completing OAP for %s.", info->name); + log_dbg_id(id, "Completing OAP for %s.", s->peer); /* Decode response header using client's md_nid for hash length */ if (oap_hdr_decode(&peer_hdr, rsp_buf, s->req_md_nid, false) < 0) { @@ -616,9 +624,9 @@ int oap_cli_complete(void * ctx, } /* Verify peer certificate name matches expected destination */ - if (peer_hdr.crt.len > 0 && strcmp(peer, info->name) != 0) { + if (peer_hdr.crt.len > 0 && strcmp(peer, s->peer) != 0) { log_err_id(id, "Peer crt for '%s' does not match '%s'.", - peer, info->name); + peer, s->peer); goto fail_oap; } @@ -667,7 +675,7 @@ int oap_cli_complete(void * ctx, goto fail_oap; } - log_info_id(id, "OAP completed for %s.", info->name); + log_info_id(id, "OAP completed for %s.", s->peer); freebuf(peer_hdr.sealed_pt); diff --git a/src/irmd/oap/tests/common.c b/src/irmd/oap/tests/common.c index 16d52c63..b65f3997 100644 --- a/src/irmd/oap/tests/common.c +++ b/src/irmd/oap/tests/common.c @@ -159,7 +159,7 @@ void oap_test_teardown(struct oap_test_ctx * ctx) if (ctx->cli.state != NULL) { res.key = ctx->cli.key; - oap_cli_complete(ctx->cli.state, &ctx->cli.info, dummy, + oap_cli_complete(ctx->cli.state, dummy, &ctx->data, &res, NULL, NULL); ctx->cli.state = NULL; } @@ -179,8 +179,8 @@ void oap_test_teardown(struct oap_test_ctx * ctx) int oap_cli_prepare_ctx(struct oap_test_ctx * ctx) { - return oap_cli_prepare(&ctx->cli.state, &ctx->cli.info, &ctx->req_hdr, - ctx->data, ctx->rekey); + return oap_cli_prepare(&ctx->cli.state, &ctx->cli.info, NULL, + &ctx->req_hdr, ctx->data, ctx->rekey); } int oap_srv_process_ctx(struct oap_test_ctx * ctx) @@ -203,8 +203,7 @@ int oap_cli_complete_ctx(struct oap_test_ctx * ctx) struct crypt_sk res = { .nid = NID_undef, .key = ctx->cli.key }; int ret; - ret = oap_cli_complete(ctx->cli.state, &ctx->cli.info, ctx->resp_hdr, - &ctx->data, &res, + ret = oap_cli_complete(ctx->cli.state, ctx->resp_hdr, &ctx->data, &res, ctx->rekey ? &ctx->cli_crt : NULL, ctx->rekey ? NULL : &ctx->cli_crt); ctx->cli.state = NULL; @@ -527,7 +526,7 @@ int roundtrip_kex_only(void) goto fail; } - if (oap_cli_prepare(&cli_state, &cli_info, &req_hdr, + if (oap_cli_prepare(&cli_state, &cli_info, NULL, &req_hdr, data, false) < 0) { printf("Client prepare failed.\n"); goto fail_cleanup; @@ -545,7 +544,7 @@ int roundtrip_kex_only(void) res.key = cli_key; - if (oap_cli_complete(cli_state, &cli_info, resp_hdr, &data, &res, + if (oap_cli_complete(cli_state, resp_hdr, &data, &res, NULL, NULL) < 0) { printf("Client complete failed.\n"); cli_state = NULL; @@ -575,8 +574,8 @@ int roundtrip_kex_only(void) fail_cleanup: if (cli_state != NULL) { res.key = cli_key; - oap_cli_complete(cli_state, &cli_info, resp_hdr, &data, - &res, NULL, NULL); + + oap_cli_complete(cli_state, resp_hdr, &data, &res, NULL, NULL); } freebuf(resp_hdr); freebuf(req_hdr); @@ -655,7 +654,7 @@ int corrupted_response(const char * root_ca, res.key = ctx.cli.key; - if (oap_cli_complete(ctx.cli.state, &ctx.cli.info, ctx.resp_hdr, + if (oap_cli_complete(ctx.cli.state, ctx.resp_hdr, &ctx.data, &res, NULL, NULL) == 0) { printf("Client should reject corrupted response.\n"); ctx.cli.state = NULL; diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c index 8be2dfc7..63c9199b 100644 --- a/src/irmd/reg/flow.c +++ b/src/irmd/reg/flow.c @@ -126,6 +126,9 @@ static int create_rbuffs(struct reg_flow * flow, assert(flow->n_1_rb == NULL); flow->info.n_1_pid = info->n_1_pid; + if (flow->poa) + return 0; + flow->n_1_rb = ssm_rbuff_create(info->n_1_pid, info->id); if (flow->n_1_rb == NULL) goto fail_n_1_rb; diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h index 166bed61..c7021a0f 100644 --- a/src/irmd/reg/flow.h +++ b/src/irmd/reg/flow.h @@ -48,6 +48,8 @@ struct reg_flow { char name[NAME_SIZE + 1]; bool direct; + bool poa; /* transport is a point of attachment */ + void * oap_ctx; /* key exchange, prepare -> complete */ /* Tier-2 re-key state (encrypted flows only) */ struct { diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c index a3621fc3..08426033 100644 --- a/src/irmd/reg/name.c +++ b/src/irmd/reg/name.c @@ -1,4 +1,3 @@ - /* * Ouroboros - Copyright (C) 2016 - 2026 * diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index ebf3959d..a302fa15 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -2119,6 +2119,77 @@ bool reg_flow_is_direct(int flow_id) return ret; } +bool reg_flow_is_poa(int flow_id) +{ + struct reg_flow * flow; + bool ret; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + + ret = flow != NULL && flow->poa; + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +int reg_flow_set_poa(int flow_id) +{ + struct reg_flow * flow; + int ret = -1; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + flow->poa = true; + ret = 0; + } + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +int reg_flow_set_oap_ctx(int flow_id, + void * ctx) +{ + struct reg_flow * flow; + int ret = -1; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + flow->oap_ctx = ctx; + ret = 0; + } + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +void * reg_flow_take_oap_ctx(int flow_id) +{ + struct reg_flow * flow; + void * ctx = NULL; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + ctx = flow->oap_ctx; + flow->oap_ctx = NULL; + } + + pthread_mutex_unlock(®.mtx); + + return ctx; +} + void reg_flow_set_rekey(int flow_id, bool initiator, buffer_t peer_crt) @@ -2607,7 +2678,7 @@ void reg_notify_flow(int flow_id, pthread_mutex_unlock(®.mtx); } -/* Wake both endpoints of a direct flow (acceptor and allocator). */ +/* Wake both PoAs of a direct flow (acceptor and allocator). */ void reg_notify_flow_peers(int flow_id, int event) { diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h index 8a313d46..6882532c 100644 --- a/src/irmd/reg/reg.h +++ b/src/irmd/reg/reg.h @@ -33,138 +33,147 @@ #include "pool.h" -int reg_init(void); +int reg_init(void); -void reg_clear(void); +void reg_clear(void); -void reg_fini(void); +void reg_fini(void); -int reg_create_flow(struct flow_info * info); +int reg_create_flow(struct flow_info * info); -int reg_destroy_flow(int flow_id); +int reg_destroy_flow(int flow_id); -bool reg_has_flow(int flow_id); +bool reg_has_flow(int flow_id); -int reg_create_proc(const struct proc_info * info); +int reg_create_proc(const struct proc_info * info); /* Use this for all processes, including ipcps */ -int reg_destroy_proc(pid_t pid); +int reg_destroy_proc(pid_t pid); -bool reg_has_proc(pid_t pid); +bool reg_has_proc(pid_t pid); -bool reg_is_proc_privileged(pid_t pid); +bool reg_is_proc_privileged(pid_t pid); -int reg_prepare_pool(uid_t uid, - gid_t gid); +int reg_prepare_pool(uid_t uid, + gid_t gid); -uid_t reg_get_proc_uid(pid_t pid); +uid_t reg_get_proc_uid(pid_t pid); -void reg_kill_all_proc(int signal); +void reg_kill_all_proc(int signal); -pid_t reg_get_dead_proc(void); +pid_t reg_get_dead_proc(void); -int reg_create_spawned(pid_t pid); +int reg_create_spawned(pid_t pid); -bool reg_has_spawned(pid_t pid); +bool reg_has_spawned(pid_t pid); -void reg_kill_all_spawned(int signal); +void reg_kill_all_spawned(int signal); -int reg_first_spawned(void); +int reg_first_spawned(void); -int reg_bind_proc(const char * name, - pid_t proc); +int reg_bind_proc(const char * name, + pid_t proc); -int reg_unbind_proc(const char * name, - pid_t proc); +int reg_unbind_proc(const char * name, + pid_t proc); -int reg_create_ipcp(const struct ipcp_info * info); +int reg_create_ipcp(const struct ipcp_info * info); -bool reg_has_ipcp(pid_t pid); +bool reg_has_ipcp(pid_t pid); -int reg_set_layer_for_ipcp(struct ipcp_info * info, - const struct layer_info * layer); +int reg_set_layer_for_ipcp(struct ipcp_info * info, + const struct layer_info * layer); -int reg_get_ipcp(struct ipcp_info * info, - struct layer_info * layer); +int reg_get_ipcp(struct ipcp_info * info, + struct layer_info * layer); -int reg_get_ipcp_by_layer(struct ipcp_info * info, - struct layer_info * layer); +int reg_get_ipcp_by_layer(struct ipcp_info * info, + struct layer_info * layer); /* TODO don't rely on protobuf here */ -int reg_list_ipcps(ipcp_list_msg_t *** msg); +int reg_list_ipcps(ipcp_list_msg_t *** msg); -int reg_create_name(const struct name_info * info); +int reg_create_name(const struct name_info * info); -int reg_destroy_name(const char * name); +int reg_destroy_name(const char * name); -bool reg_has_name(const char * name); +bool reg_has_name(const char * name); -int reg_get_name_info(const char * name, - struct name_info * info); +int reg_get_name_info(const char * name, + struct name_info * info); -int reg_get_name_for_hash(char * buf, - enum hash_algo algo, - const uint8_t * hash); +int reg_get_name_for_hash(char * buf, + enum hash_algo algo, + const uint8_t * hash); -int reg_get_name_for_flow_id(char * buf, - int flow_id); +int reg_get_name_for_flow_id(char * buf, + int flow_id); -void reg_set_name_for_flow_id(const char * name, - int flow_id); +void reg_set_name_for_flow_id(const char * name, + int flow_id); /* TODO don't rely on protobuf here */ -int reg_list_names(name_info_msg_t *** names); +int reg_list_names(name_info_msg_t *** names); -int reg_create_prog(const struct prog_info * info); +int reg_create_prog(const struct prog_info * info); -int reg_destroy_prog(const char * name); +int reg_destroy_prog(const char * name); -bool reg_has_prog(const char * name); +bool reg_has_prog(const char * name); -int reg_get_exec(const char * name, - char *** exec); +int reg_get_exec(const char * name, + char *** exec); -int reg_bind_prog(const char * name, - char ** exec, - uint8_t flags); +int reg_bind_prog(const char * name, + char ** exec, + uint8_t flags); -int reg_unbind_prog(const char * name, - const char * prog); +int reg_unbind_prog(const char * name, + const char * prog); -int reg_prepare_flow_alloc(struct flow_info * info); +int reg_prepare_flow_alloc(struct flow_info * info); -int reg_wait_flow_allocated(struct flow_info * info, +int reg_wait_flow_allocated(struct flow_info * info, + buffer_t * pbuf, + const struct timespec * abstime); + +int reg_respond_alloc(struct flow_info * info, + buffer_t * pbuf, + int response); + +int reg_prepare_flow_accept(struct flow_info * info); + +int reg_wait_flow_accepted(struct flow_info * info, buffer_t * pbuf, const struct timespec * abstime); -int reg_respond_alloc(struct flow_info * info, - buffer_t * pbuf, - int response); +int reg_wait_flow_accepting(const char * name, + const struct timespec * abstime); -int reg_prepare_flow_accept(struct flow_info * info); +int reg_respond_accept(struct flow_info * info, + buffer_t * pbuf); -int reg_wait_flow_accepted(struct flow_info * info, - buffer_t * pbuf, - const struct timespec * abstime); +int reg_prepare_flow_direct(struct flow_info * info, + buffer_t * pbuf, + uid_t alloc_uid); -int reg_wait_flow_accepting(const char * name, - const struct timespec * abstime); +int reg_respond_flow_direct(int flow_id, + buffer_t * pbuf); + +int reg_wait_flow_direct(int flow_id, + buffer_t * pbuf, + const struct timespec * abstime); -int reg_respond_accept(struct flow_info * info, - buffer_t * pbuf); +bool reg_flow_is_direct(int flow_id); -int reg_prepare_flow_direct(struct flow_info * info, - buffer_t * pbuf, - uid_t alloc_uid); +bool reg_flow_is_poa(int flow_id); -int reg_respond_flow_direct(int flow_id, - buffer_t * pbuf); +int reg_flow_set_poa(int flow_id); -int reg_wait_flow_direct(int flow_id, - buffer_t * pbuf, - const struct timespec * abstime); +int reg_flow_set_oap_ctx(int flow_id, + void * ctx); -bool reg_flow_is_direct(int flow_id); +void * reg_flow_take_oap_ctx(int flow_id); /* Per-flow snapshot for the re-key timer */ struct rekey_info { @@ -176,70 +185,70 @@ struct rekey_info { bool direct; }; -void reg_flow_set_rekey(int flow_id, - bool initiator, - buffer_t peer_crt); +void reg_flow_set_rekey(int flow_id, + bool initiator, + buffer_t peer_crt); -int reg_flow_get_peer_crt(int flow_id, - buffer_t * crt); +int reg_flow_get_peer_crt(int flow_id, + buffer_t * crt); -int reg_flow_get_epoch(int flow_id); +int reg_flow_get_epoch(int flow_id); -bool reg_flow_rekey_pending(int flow_id); +bool reg_flow_rekey_pending(int flow_id); -pid_t reg_flow_get_n_1_pid(int flow_id); +pid_t reg_flow_get_n_1_pid(int flow_id); -int reg_flow_snapshot_rekey_due(struct rekey_info * snap, - int max); +int reg_flow_snapshot_rekey_due(struct rekey_info * snap, + int max); -void reg_flow_clear_in_flight(int flow_id); +void reg_flow_clear_in_flight(int flow_id); -bool reg_flow_rekey_begin(int flow_id); +bool reg_flow_rekey_begin(int flow_id); -bool reg_flow_rekey_should_yield(int flow_id); +bool reg_flow_rekey_should_yield(int flow_id); -int reg_flow_store_pending(int flow_id, - const uint8_t * seed, - uint8_t epoch, - bool initiator); +int reg_flow_store_pending(int flow_id, + const uint8_t * seed, + uint8_t epoch, + bool initiator); -int reg_flow_store_pending_direct(int flow_id, - const uint8_t * seed, - uint8_t epoch); +int reg_flow_store_pending_direct(int flow_id, + const uint8_t * seed, + uint8_t epoch); -int reg_flow_take_pending(int flow_id, - uid_t uid, - pid_t cpid, - uint8_t * seed, - uint8_t * epoch, - bool * initiator); +int reg_flow_take_pending(int flow_id, + uid_t uid, + pid_t cpid, + uint8_t * seed, + uint8_t * epoch, + bool * initiator); -bool reg_flow_rekey_arr_admit(int flow_id, - pid_t n_1_pid, - bool is_req); +bool reg_flow_rekey_arr_admit(int flow_id, + pid_t n_1_pid, + bool is_req); -void reg_flow_rekey_arr_done(int flow_id, - bool is_req); +void reg_flow_rekey_arr_done(int flow_id, + bool is_req); -bool reg_flow_owned_by(int flow_id, - uid_t uid); +bool reg_flow_owned_by(int flow_id, + uid_t uid); -void reg_notify_flow(int flow_id, - int event); +void reg_notify_flow(int flow_id, + int event); -void reg_notify_flow_peers(int flow_id, - int event); +void reg_notify_flow_peers(int flow_id, + int event); -void reg_dealloc_flow(struct flow_info * info); +void reg_dealloc_flow(struct flow_info * info); -void reg_dealloc_flow_resp(struct flow_info * info); +void reg_dealloc_flow_resp(struct flow_info * info); -int reg_wait_proc(pid_t pid, - const struct timespec * abstime); +int reg_wait_proc(pid_t pid, + const struct timespec * abstime); -int reg_wait_ipcp_boot(struct ipcp_info * ipcp, - const struct timespec * abstime); +int reg_wait_ipcp_boot(struct ipcp_info * ipcp, + const struct timespec * abstime); -int reg_respond_ipcp(const struct ipcp_info * info); +int reg_respond_ipcp(const struct ipcp_info * info); #endif /* OUROBOROS_IRMD_REG_H */ diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c index a8c1b1fa..ab57241c 100644 --- a/src/irmd/reg/tests/reg_test.c +++ b/src/irmd/reg/tests/reg_test.c @@ -746,7 +746,7 @@ static int test_reg_direct_flow_success(void) reg_dealloc_flow(&info); if (info.state != FLOW_DEALLOC_PENDING) { - printf("Same endpoint dealloc changed state.\n"); + printf("Same PoA dealloc changed state.\n"); goto fail; } |
