summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ipcpd/eth/CMakeLists.txt8
-rw-r--r--src/ipcpd/eth/eth.c17
-rw-r--r--src/ipcpd/ipcp.c13
-rw-r--r--src/ipcpd/shim-data.c34
-rw-r--r--src/ipcpd/shim-data.h19
-rw-r--r--src/ipcpd/udp/CMakeLists.txt34
-rw-r--r--src/ipcpd/udp/udp.c (renamed from src/ipcpd/udp/main.c)309
-rw-r--r--src/ipcpd/udp/udp4.c42
-rw-r--r--src/ipcpd/udp/udp6.c42
-rw-r--r--src/ipcpd/unicast/CMakeLists.txt5
-rw-r--r--src/irmd/config.h.in3
-rw-r--r--src/irmd/configfile.c77
-rw-r--r--src/irmd/main.c9
-rw-r--r--src/lib/pb/ipcp_config.proto14
-rw-r--r--src/lib/protobuf.c91
-rw-r--r--src/tools/irm/irm_ipcp_bootstrap.c114
-rw-r--r--src/tools/irm/irm_ipcp_create.c11
-rw-r--r--src/tools/irm/irm_ipcp_list.c17
18 files changed, 604 insertions, 255 deletions
diff --git a/src/ipcpd/eth/CMakeLists.txt b/src/ipcpd/eth/CMakeLists.txt
index 17ae74fc..44299a59 100644
--- a/src/ipcpd/eth/CMakeLists.txt
+++ b/src/ipcpd/eth/CMakeLists.txt
@@ -90,13 +90,13 @@ if (HAVE_ETH)
set(ETH_LLC_SOURCES
# Add source files here
- ${CMAKE_CURRENT_SOURCE_DIR}/llc.c
- )
+ llc.c
+ )
set(ETH_DIX_SOURCES
# Add source files here
- ${CMAKE_CURRENT_SOURCE_DIR}/dix.c
- )
+ dix.c
+ )
set(IPCP_ETH_LLC_TARGET ipcpd-eth-llc CACHE INTERNAL "")
set(IPCP_ETH_DIX_TARGET ipcpd-eth-dix CACHE INTERNAL "")
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c
index 1028ee03..d39b478c 100644
--- a/src/ipcpd/eth/eth.c
+++ b/src/ipcpd/eth/eth.c
@@ -113,7 +113,6 @@
#define ETH_MTU_MAX 1500
#endif /* BUILD_ETH_DIX */
-#define MAC_SIZE 6
#define ETH_TYPE_LENGTH_SIZE sizeof(uint16_t)
#define ETH_HEADER_SIZE (2 * MAC_SIZE + ETH_TYPE_LENGTH_SIZE)
@@ -694,11 +693,11 @@ static int eth_ipcp_name_query_req(const uint8_t * hash,
static int eth_ipcp_name_query_reply(const uint8_t * hash,
uint8_t * r_addr)
{
- uint64_t address = 0;
+ struct addr addr;
- memcpy(&address, r_addr, MAC_SIZE);
+ memcpy(&addr.mac, r_addr, MAC_SIZE);
- shim_data_dir_add_entry(eth_data.shim_data, hash, address);
+ shim_data_dir_add_entry(eth_data.shim_data, hash, addr);
shim_data_dir_query_respond(eth_data.shim_data, hash);
@@ -1699,7 +1698,7 @@ static int eth_ipcp_flow_alloc(int fd,
uint8_t ssap = 0;
#endif
uint8_t r_addr[MAC_SIZE];
- uint64_t addr = 0;
+ struct addr addr;
assert(hash);
@@ -1708,10 +1707,12 @@ static int eth_ipcp_flow_alloc(int fd,
HASH_VAL32(hash));
return -1;
}
+
addr = shim_data_dir_get_addr(eth_data.shim_data, hash);
+ memcpy(r_addr, &addr.mac, MAC_SIZE);
- pthread_rwlock_wrlock(&eth_data.flows_lock);
#ifdef BUILD_ETH_LLC
+ pthread_rwlock_wrlock(&eth_data.flows_lock);
ssap = bmp_allocate(eth_data.saps);
if (!bmp_is_id_valid(eth_data.saps, ssap)) {
pthread_rwlock_unlock(&eth_data.flows_lock);
@@ -1721,10 +1722,8 @@ static int eth_ipcp_flow_alloc(int fd,
eth_data.fd_to_ef[fd].sap = ssap;
eth_data.ef_to_fd[ssap] = fd;
-#endif
pthread_rwlock_unlock(&eth_data.flows_lock);
-
- memcpy(r_addr, &addr, MAC_SIZE);
+#endif
if (eth_ipcp_alloc(r_addr,
#if defined(BUILD_ETH_DIX)
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index a47b6226..62995727 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -74,7 +74,8 @@ static char * ipcp_type_str[] = {
"broadcast",
"eth-llc",
"eth-dix",
- "udp"
+ "udp4",
+ "udp6"
};
static char * dir_hash_str[] = {
@@ -228,8 +229,10 @@ static int ipcp_rib_read(const char * path,
strcpy(buf, "eth-llc\n");
else if (ipcpd.type == IPCP_ETH_DIX)
strcpy(buf, "eth-dix\n");
- else if (ipcpd.type == IPCP_UDP)
- strcpy(buf, "udp\n");
+ else if (ipcpd.type == IPCP_UDP4)
+ strcpy(buf, "udp4\n");
+ else if (ipcpd.type == IPCP_UDP6)
+ strcpy(buf, "udp6\n");
else
strcpy(buf, "bug\n");
}
@@ -455,7 +458,9 @@ static void do_bootstrap(ipcp_config_msg_t * conf_msg,
conf = ipcp_config_msg_to_s(conf_msg);
switch(conf.type) { /* FIXED algorithms */
- case IPCP_UDP:
+ case IPCP_UDP4:
+ /* FALLTHRU */
+ case IPCP_UDP6:
conf.layer_info.dir_hash_algo = (enum pol_dir_hash) HASH_MD5;
break;
case IPCP_BROADCAST:
diff --git a/src/ipcpd/shim-data.c b/src/ipcpd/shim-data.c
index 1fac63ac..8801213a 100644
--- a/src/ipcpd/shim-data.c
+++ b/src/ipcpd/shim-data.c
@@ -51,7 +51,7 @@ struct reg_entry {
struct dir_entry {
struct list_head list;
uint8_t * hash;
- uint64_t addr;
+ struct addr addr;
};
static void destroy_dir_query(struct dir_query * query)
@@ -108,14 +108,12 @@ static void reg_entry_destroy(struct reg_entry * entry)
{
assert(entry);
- if (entry->hash != NULL)
- free(entry->hash);
-
+ free(entry->hash);
free(entry);
}
-static struct dir_entry * dir_entry_create(uint8_t * hash,
- uint64_t addr)
+static struct dir_entry * dir_entry_create(uint8_t * hash,
+ struct addr addr)
{
struct dir_entry * entry = malloc(sizeof(*entry));
if (entry == NULL)
@@ -133,9 +131,7 @@ static void dir_entry_destroy(struct dir_entry * entry)
{
assert(entry);
- if (entry->hash != NULL)
- free(entry->hash);
-
+ free(entry->hash);
free(entry);
}
@@ -258,13 +254,15 @@ static struct reg_entry * find_reg_entry_by_hash(struct shim_data * data,
static struct dir_entry * find_dir_entry(struct shim_data * data,
const uint8_t * hash,
- uint64_t addr)
+ struct addr addr)
{
struct list_head * h;
list_for_each(h, &data->directory) {
struct dir_entry * e = list_entry(h, struct dir_entry, list);
- if (e->addr == addr &&
- !memcmp(e->hash, hash, ipcp_dir_hash_len()))
+ if (memcmp(&e->addr, &addr, sizeof(addr)) != 0)
+ continue;
+
+ if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0)
return e;
}
@@ -364,7 +362,7 @@ bool shim_data_reg_has(struct shim_data * data,
int shim_data_dir_add_entry(struct shim_data * data,
const uint8_t * hash,
- uint64_t addr)
+ struct addr addr)
{
struct dir_entry * entry;
uint8_t * entry_hash;
@@ -400,7 +398,7 @@ int shim_data_dir_add_entry(struct shim_data * data,
int shim_data_dir_del_entry(struct shim_data * data,
const uint8_t * hash,
- uint64_t addr)
+ struct addr addr)
{
struct dir_entry * e;
if (data == NULL)
@@ -437,11 +435,11 @@ bool shim_data_dir_has(struct shim_data * data,
return ret;
}
-uint64_t shim_data_dir_get_addr(struct shim_data * data,
- const uint8_t * hash)
+struct addr shim_data_dir_get_addr(struct shim_data * data,
+ const uint8_t * hash)
{
struct dir_entry * entry;
- uint64_t addr;
+ struct addr addr = {0};
pthread_rwlock_rdlock(&data->dir_lock);
@@ -449,7 +447,7 @@ uint64_t shim_data_dir_get_addr(struct shim_data * data,
if (entry == NULL) {
pthread_rwlock_unlock(&data->dir_lock);
log_warn("No address for " HASH_FMT32 ".", HASH_VAL32(hash));
- return 0; /* undefined behaviour, 0 may be a valid address */
+ return addr; /* undefined behaviour, 0 may be a valid address */
}
addr = entry->addr;
diff --git a/src/ipcpd/shim-data.h b/src/ipcpd/shim-data.h
index 372b4ea7..ea4ce413 100644
--- a/src/ipcpd/shim-data.h
+++ b/src/ipcpd/shim-data.h
@@ -25,9 +25,12 @@
#include <ouroboros/list.h>
-#include <sys/types.h>
#include <pthread.h>
#include <stdint.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+
+#define MAC_SIZE 6
enum dir_query_state {
QUERY_INIT = 0,
@@ -46,6 +49,14 @@ struct dir_query {
pthread_cond_t cond;
};
+struct addr {
+ union {
+ uint8_t mac[MAC_SIZE];
+ struct in_addr ip4;
+ struct in6_addr ip6;
+ };
+};
+
struct shim_data {
struct list_head registry;
pthread_rwlock_t reg_lock;
@@ -72,16 +83,16 @@ bool shim_data_reg_has(struct shim_data * data,
int shim_data_dir_add_entry(struct shim_data * data,
const uint8_t * hash,
- uint64_t addr);
+ struct addr addr);
int shim_data_dir_del_entry(struct shim_data * data,
const uint8_t * hash,
- uint64_t addr);
+ struct addr addr);
bool shim_data_dir_has(struct shim_data * data,
const uint8_t * hash);
-uint64_t shim_data_dir_get_addr(struct shim_data * data,
+struct addr shim_data_dir_get_addr(struct shim_data * data,
const uint8_t * hash);
struct dir_query * shim_data_dir_query_create(struct shim_data * data,
diff --git a/src/ipcpd/udp/CMakeLists.txt b/src/ipcpd/udp/CMakeLists.txt
index 5abf5a00..27e32094 100644
--- a/src/ipcpd/udp/CMakeLists.txt
+++ b/src/ipcpd/udp/CMakeLists.txt
@@ -12,16 +12,25 @@ include_directories(${CURRENT_BINARY_PARENT_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_BINARY_DIR}/include)
-set(IPCP_UDP_TARGET ipcpd-udp CACHE INTERNAL "")
+set(IPCP_UDP4_TARGET ipcpd-udp4 CACHE INTERNAL "")
+set(IPCP_UDP6_TARGET ipcpd-udp6 CACHE INTERNAL "")
-set(UDP_SOURCES
+set(UDP4_SOURCES
# Add source files here
- ${CMAKE_CURRENT_SOURCE_DIR}/main.c
- )
+ udp4.c
+)
-add_executable(ipcpd-udp ${UDP_SOURCES} ${IPCP_SOURCES})
+set(UDP6_SOURCES
+ # Add source files here
+ udp6.c
+)
+
+add_executable(ipcpd-udp4 ${UDP4_SOURCES} ${IPCP_SOURCES})
+target_link_libraries(ipcpd-udp4 LINK_PUBLIC ouroboros-dev)
+
+add_executable(ipcpd-udp6 ${UDP6_SOURCES} ${IPCP_SOURCES})
+target_link_libraries(ipcpd-udp6 LINK_PUBLIC ouroboros-dev)
-target_link_libraries(ipcpd-udp LINK_PUBLIC ouroboros-dev)
# Find the nsupdate executable
find_program(NSUPDATE_EXECUTABLE
@@ -55,15 +64,18 @@ else ()
endif ()
set(IPCP_UDP_RD_THR 3 CACHE STRING
- "Number of reader threads in UDP IPCP")
+ "Number of reader threads in UDP IPCPs")
set(IPCP_UDP_WR_THR 3 CACHE STRING
- "Number of writer threads in UDP IPCP")
+ "Number of writer threads in UDP IPCPs")
set(IPCP_UDP_MPL 5000 CACHE STRING
- "Default maximum packet lifetime for the UDP IPCP, in ms")
+ "Default maximum packet lifetime for the UDP IPCPs, in ms")
include(AddCompileFlags)
if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(ipcpd-udp -DCONFIG_OUROBOROS_DEBUG)
+ add_compile_flags(ipcpd-udp4 -DCONFIG_OUROBOROS_DEBUG)
+ add_compile_flags(ipcpd-udp6 -DCONFIG_OUROBOROS_DEBUG)
endif ()
-install(TARGETS ipcpd-udp RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+install(TARGETS ipcpd-udp4 RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+install(TARGETS ipcpd-udp6 RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+
diff --git a/src/ipcpd/udp/main.c b/src/ipcpd/udp/udp.c
index 5f770a61..d6d38362 100644
--- a/src/ipcpd/udp/main.c
+++ b/src/ipcpd/udp/udp.c
@@ -20,23 +20,14 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#if defined(__linux__) || defined(__CYGWIN__)
-#define _DEFAULT_SOURCE
-#else
-#define _POSIX_C_SOURCE 200112L
-#endif
-
#include "config.h"
-#define OUROBOROS_PREFIX "ipcpd/udp"
-
#include <ouroboros/bitmap.h>
#include <ouroboros/endian.h>
#include <ouroboros/hash.h>
#include <ouroboros/list.h>
#include <ouroboros/utils.h>
#include <ouroboros/dev.h>
-#include <ouroboros/ipcp-dev.h>
#include <ouroboros/fqueue.h>
#include <ouroboros/errno.h>
#include <ouroboros/logs.h>
@@ -59,12 +50,11 @@
#define FLOW_REQ 1
#define FLOW_REPLY 2
-#define THIS_TYPE IPCP_UDP
-#define IPCP_UDP_MAX_PACKET_SIZE 8980
#define OUR_HEADER_LEN sizeof(uint32_t) /* adds eid */
-#define IPCP_UDP_BUF_SIZE 8980
-#define IPCP_UDP_MSG_SIZE 8980
+#define IPCP_UDP_BUF_SIZE IPCP_UDP_MAX_PACKET_SIZE
+#define IPCP_UDP_MSG_SIZE IPCP_UDP_MAX_PACKET_SIZE
+
#define DNS_TTL 86400
#define SADDR ((struct sockaddr *) &udp_data.s_saddr)
@@ -102,24 +92,23 @@ struct mgmt_msg {
} __attribute__((packed));
struct mgmt_frame {
- struct list_head next;
- struct sockaddr_in r_saddr;
- uint8_t buf[MGMT_FRAME_BUF_SIZE];
- size_t len;
+ struct list_head next;
+ struct __SOCKADDR r_saddr;
+ uint8_t buf[MGMT_FRAME_BUF_SIZE];
+ size_t len;
};
/* UDP flow */
struct uf {
- int d_eid;
- struct sockaddr_in r_saddr;
+ int d_eid;
+ struct __SOCKADDR r_saddr;
};
struct {
struct shim_data * shim_data;
- uint32_t dns_addr;
-
- struct sockaddr_in s_saddr;
+ struct __ADDR dns_addr;
+ struct __SOCKADDR s_saddr;
int s_fd;
fset_t * np1_flows;
@@ -136,6 +125,12 @@ struct {
struct list_head mgmt_frames;
} udp_data;
+static const char * __inet_ntop(const struct __ADDR * addr,
+ char * buf)
+{
+ return inet_ntop(__AF, addr, buf, __ADDRSTRLEN);
+}
+
static int udp_data_init(void)
{
int i;
@@ -197,11 +192,11 @@ static void udp_data_fini(void)
pthread_mutex_destroy(&udp_data.mgmt_lock);
}
-static int udp_ipcp_port_alloc(const struct sockaddr_in * r_saddr,
- uint32_t s_eid,
- const uint8_t * dst,
- qosspec_t qs,
- const buffer_t * data)
+static int udp_ipcp_port_alloc(const struct __SOCKADDR * r_saddr,
+ uint32_t s_eid,
+ const uint8_t * dst,
+ qosspec_t qs,
+ const buffer_t * data)
{
uint8_t * buf;
struct mgmt_msg * msg;
@@ -236,6 +231,8 @@ static int udp_ipcp_port_alloc(const struct sockaddr_in * r_saddr,
if (sendto(udp_data.s_fd, msg, len + data->len,
SENDTO_FLAGS,
(const struct sockaddr *) r_saddr, sizeof(*r_saddr)) < 0) {
+ log_err("Failed to send flow allocation request: %s.",
+ strerror(errno));
free(buf);
return -1;
}
@@ -245,11 +242,11 @@ static int udp_ipcp_port_alloc(const struct sockaddr_in * r_saddr,
return 0;
}
-static int udp_ipcp_port_alloc_resp(const struct sockaddr_in * r_saddr,
- uint32_t s_eid,
- uint32_t d_eid,
- int8_t response,
- const buffer_t * data)
+static int udp_ipcp_port_alloc_resp(const struct __SOCKADDR * r_saddr,
+ uint32_t s_eid,
+ uint32_t d_eid,
+ int8_t response,
+ const buffer_t * data)
{
struct mgmt_msg * msg;
@@ -278,11 +275,11 @@ static int udp_ipcp_port_alloc_resp(const struct sockaddr_in * r_saddr,
return 0;
}
-static int udp_ipcp_port_req(struct sockaddr_in * c_saddr,
- int d_eid,
- const uint8_t * dst,
- qosspec_t qs,
- const buffer_t * data)
+static int udp_ipcp_port_req(struct __SOCKADDR * c_saddr,
+ int d_eid,
+ const uint8_t * dst,
+ qosspec_t qs,
+ const buffer_t * data)
{
int fd;
@@ -305,20 +302,26 @@ static int udp_ipcp_port_req(struct sockaddr_in * c_saddr,
return 0;
}
-static int udp_ipcp_port_alloc_reply(const struct sockaddr_in * saddr,
- uint32_t s_eid,
- uint32_t d_eid,
- int8_t response,
- const buffer_t * data)
+static int udp_ipcp_port_alloc_reply(const struct __SOCKADDR * saddr,
+ uint32_t s_eid,
+ uint32_t d_eid,
+ int8_t response,
+ const buffer_t * data)
{
time_t mpl = IPCP_UDP_MPL;
pthread_rwlock_wrlock(&udp_data.flows_lock);
if (memcmp(&udp_data.fd_to_uf[s_eid].r_saddr, saddr, sizeof(*saddr))) {
+ char ipstr[__ADDRSTRLEN];
pthread_rwlock_unlock(&udp_data.flows_lock);
- log_err("Flow allocation reply for %u from wrong source.",
- s_eid);
+ #ifdef BUILD_IPCP_UDP4
+ __inet_ntop(&saddr->sin_addr, ipstr);
+ #else
+ __inet_ntop(&saddr->sin6_addr, ipstr);
+ #endif
+ log_err("Flow allocation reply for %u from wrong source %s.",
+ s_eid, ipstr);
return -1;
}
@@ -338,9 +341,9 @@ static int udp_ipcp_port_alloc_reply(const struct sockaddr_in * saddr,
return 0;
}
-static int udp_ipcp_mgmt_frame(const uint8_t * buf,
- size_t len,
- struct sockaddr_in c_saddr)
+static int udp_ipcp_mgmt_frame(struct __SOCKADDR c_saddr,
+ const uint8_t * buf,
+ size_t len)
{
struct mgmt_msg * msg;
size_t msg_len;
@@ -411,7 +414,7 @@ static void * udp_ipcp_mgmt_handler(void * o)
pthread_mutex_unlock(&udp_data.mgmt_lock);
- udp_ipcp_mgmt_frame(frame->buf, frame->len, frame->r_saddr);
+ udp_ipcp_mgmt_frame(frame->r_saddr, frame->buf, frame->len);
free(frame);
}
@@ -438,7 +441,7 @@ static void * udp_ipcp_packet_reader(void * o)
while (true) {
struct mgmt_frame * frame;
- struct sockaddr_in r_saddr;
+ struct __SOCKADDR r_saddr;
socklen_t len;
struct shm_du_buff * sdb;
uint8_t * head;
@@ -521,9 +524,9 @@ static void * udp_ipcp_packet_writer(void * o)
pthread_cleanup_push(cleanup_fqueue, fq);
while (true) {
- struct sockaddr_in saddr;
- int eid;
- int fd;
+ struct __SOCKADDR saddr;
+ int eid;
+ int fd;
fevent(udp_data.np1_flows, fq, NULL);
while ((fd = fqueue_next(fq)) >= 0) {
struct shm_du_buff * sdb;
@@ -578,29 +581,39 @@ static void * udp_ipcp_packet_writer(void * o)
return (void *) 1;
}
-static const char * inet4_ntop(const void * addr,
- char * buf)
+static bool is_addr_specified(const struct __ADDR * addr)
{
- return inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
+#ifdef BUILD_IPCP_UDP4
+ return addr->s_addr != 0;
+#else
+ return !IN6_IS_ADDR_UNSPECIFIED(addr);
+#endif
}
static int udp_ipcp_bootstrap(struct ipcp_config * conf)
{
- char ipstr[INET_ADDRSTRLEN];
- char dnsstr[INET_ADDRSTRLEN];
+ char ipstr[__ADDRSTRLEN];
+ char dnsstr[__ADDRSTRLEN];
int i = 1;
+#ifdef BUILD_IPCP_UDP4
+ struct udp4_config * udp;
+ udp = &conf->udp4;
+#else
+ struct udp6_config * udp;
+ udp = &conf->udp6;
+#endif
assert(conf != NULL);
assert(conf->type == THIS_TYPE);
assert(conf->layer_info.dir_hash_algo == (enum pol_dir_hash) HASH_MD5);
- if (inet4_ntop(&conf->udp.ip_addr, ipstr) == NULL) {
+ if (__inet_ntop(&udp->ip_addr, ipstr) == NULL) {
log_err("Failed to convert IP address.");
return -1;
}
- if (conf->udp.dns_addr != 0) {
- if (inet4_ntop(&conf->udp.dns_addr, dnsstr) == NULL) {
+ if (is_addr_specified(&udp->dns_addr)) {
+ if (__inet_ntop(&udp->dns_addr, dnsstr) == NULL) {
log_err("Failed to convert DNS address.");
return -1;
}
@@ -612,24 +625,29 @@ static int udp_ipcp_bootstrap(struct ipcp_config * conf)
}
/* UDP listen server */
- udp_data.s_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ udp_data.s_fd = socket(__AF, SOCK_DGRAM, IPPROTO_UDP);
if (udp_data.s_fd < 0) {
log_err("Can't create socket: %s", strerror(errno));
goto fail_socket;
}
memset((char *) &udp_data.s_saddr, 0, sizeof(udp_data.s_saddr));
- udp_data.s_saddr.sin_family = AF_INET;
- udp_data.s_saddr.sin_addr.s_addr = conf->udp.ip_addr;
- udp_data.s_saddr.sin_port = htons(conf->udp.port);
-
+#ifdef BUILD_IPCP_UDP4
+ udp_data.s_saddr.sin_family = AF_INET;
+ udp_data.s_saddr.sin_addr = udp->ip_addr;
+ udp_data.s_saddr.sin_port = htons(udp->port);
+#else
+ udp_data.s_saddr.sin6_family = AF_INET6;
+ udp_data.s_saddr.sin6_addr = udp->ip_addr;
+ udp_data.s_saddr.sin6_port = htons(udp->port);
+#endif
if (bind(udp_data.s_fd, SADDR, SADDR_SIZE) < 0) {
log_err("Couldn't bind to %s:%d. %s.",
- ipstr, conf->udp.port, strerror(errno));
+ ipstr, udp->port, strerror(errno));
goto fail_bind;
}
- udp_data.dns_addr = conf->udp.dns_addr;
+ udp_data.dns_addr = udp->dns_addr;
if (pthread_create(&udp_data.mgmt_handler, NULL,
udp_ipcp_mgmt_handler, NULL)) {
@@ -653,10 +671,10 @@ static int udp_ipcp_bootstrap(struct ipcp_config * conf)
}
}
- log_dbg("Bootstrapped IPCP over UDP with pid %d.", getpid());
+ log_dbg("Bootstrapped " TYPE_STR " with pid %d.", getpid());
log_dbg("Bound to IP address %s.", ipstr);
- log_dbg("Using port %u.", conf->udp.port);
- if (conf->udp.dns_addr != 0)
+ log_dbg("Using port %u.", udp->port);
+ if (is_addr_specified(&udp_data.dns_addr))
log_dbg("DNS server address is %s.", dnsstr);
else
log_dbg("DNS server not in use.");
@@ -734,26 +752,26 @@ static int ddns_send(char * cmd)
return 0;
}
-static uint32_t ddns_resolve(char * name,
- uint32_t dns_addr)
+static struct __ADDR ddns_resolve(char * name,
+ struct __ADDR dns_addr)
{
- pid_t pid = -1;
- int wstatus;
- int pipe_fd[2];
- char dnsstr[INET_ADDRSTRLEN];
- char buf[IPCP_UDP_BUF_SIZE];
- ssize_t count = 0;
- char * substr = NULL;
- char * substr2 = NULL;
- char * addr_str = "Address:";
- uint32_t ip_addr = 0;
-
- if (inet4_ntop(&dns_addr, dnsstr) == NULL)
- return 0;
+ pid_t pid = -1;
+ int wstatus;
+ int pipe_fd[2];
+ char dnsstr[__ADDRSTRLEN];
+ char buf[IPCP_UDP_BUF_SIZE];
+ ssize_t count = 0;
+ char * substr = NULL;
+ char * substr2 = NULL;
+ char * addr_str = "Address:";
+ struct __ADDR ip_addr = __ADDR_ANY_INIT;
+
+ if (__inet_ntop(&dns_addr, dnsstr) == NULL)
+ return ip_addr;
if (pipe(pipe_fd)) {
log_err("Failed to create pipe: %s.", strerror(errno));
- return 0;
+ return ip_addr;
}
pid = fork();
@@ -761,7 +779,7 @@ static uint32_t ddns_resolve(char * name,
log_err("Failed to fork: %s.", strerror(errno));
close(pipe_fd[0]);
close(pipe_fd[1]);
- return -1;
+ return ip_addr;
}
if (pid == 0) {
@@ -781,7 +799,7 @@ static uint32_t ddns_resolve(char * name,
if (count <= 0) {
log_err("Failed to communicate with nslookup.");
close(pipe_fd[0]);
- return 0;
+ return ip_addr;
}
close(pipe_fd[0]);
@@ -802,12 +820,13 @@ static uint32_t ddns_resolve(char * name,
if (substr2 == NULL || strstr(substr2, addr_str) == NULL) {
log_err("Failed to resolve DNS address.");
- return 0;
+ return ip_addr;
}
- if (inet_pton(AF_INET, substr2 + strlen(addr_str) + 1, &ip_addr) != 1) {
+ if (inet_pton(__AF, substr2 + strlen(addr_str) + 1, &ip_addr) != 1) {
log_err("Failed to resolve DNS address.");
- return 0;
+ assert(!is_addr_specified(&ip_addr));
+ return ip_addr;
}
return ip_addr;
@@ -817,11 +836,11 @@ static uint32_t ddns_resolve(char * name,
static int udp_ipcp_reg(const uint8_t * hash)
{
#ifdef HAVE_DDNS
- char ipstr[INET_ADDRSTRLEN];
- char dnsstr[INET_ADDRSTRLEN];
- char cmd[1000];
- uint32_t dns_addr;
- uint32_t ip_addr;
+ char ipstr[__ADDRSTRLEN];
+ char dnsstr[__ADDRSTRLEN];
+ char cmd[1000];
+ struct __ADDR dns_addr;
+ struct __ADDR ip_addr;
#endif
char * hashstr;
@@ -847,16 +866,19 @@ static int udp_ipcp_reg(const uint8_t * hash)
dns_addr = udp_data.dns_addr;
- if (dns_addr != 0) {
- ip_addr = udp_data.s_saddr.sin_addr.s_addr;
-
- if (inet4_ntop(&ip_addr, ipstr) == NULL) {
+ if (is_addr_specified(&dns_addr)) {
+#ifdef BUILD_IPCP_UDP4
+ ip_addr = udp_data.s_saddr.sin_addr;
+#else
+ ip_addr = udp_data.s_saddr.sin6_addr;
+#endif
+ if (__inet_ntop(&ip_addr, ipstr) == NULL) {
log_err("Failed to convert IP address to string.");
free(hashstr);
return -1;
}
- if (inet4_ntop(&dns_addr, dnsstr) == NULL) {
+ if (__inet_ntop(&dns_addr, dnsstr) == NULL) {
log_err("Failed to convert DNS address to string.");
free(hashstr);
return -1;
@@ -881,12 +903,12 @@ static int udp_ipcp_reg(const uint8_t * hash)
static int udp_ipcp_unreg(const uint8_t * hash)
{
#ifdef HAVE_DDNS
- char dnsstr[INET_ADDRSTRLEN];
+ char dnsstr[__ADDRSTRLEN];
/* max DNS name length + max IP length + max command length */
- char cmd[100];
- uint32_t dns_addr;
+ char cmd[100];
+ struct __ADDR dns_addr;
#endif
- char * hashstr;
+ char * hashstr;
assert(hash);
@@ -903,8 +925,8 @@ static int udp_ipcp_unreg(const uint8_t * hash)
dns_addr = udp_data.dns_addr;
- if (dns_addr != 0) {
- if (inet4_ntop(&dns_addr, dnsstr) == NULL) {
+ if (is_addr_specified(&dns_addr)) {
+ if (__inet_ntop(&dns_addr, dnsstr) == NULL) {
log_err("Failed to convert DNS address to string.");
free(hashstr);
return -1;
@@ -925,11 +947,13 @@ static int udp_ipcp_unreg(const uint8_t * hash)
static int udp_ipcp_query(const uint8_t * hash)
{
- uint32_t ip_addr = 0;
- char * hashstr;
- struct hostent * h;
+ struct addr addr = {};
+ char * hashstr;
+ struct addrinfo hints;
+ struct addrinfo * ai;
#ifdef HAVE_DDNS
- uint32_t dns_addr = 0;
+ struct __ADDR dns_addr = __ADDR_ANY_INIT;
+ struct __ADDR ip_addr = __ADDR_ANY_INIT;
#endif
assert(hash);
@@ -949,28 +973,42 @@ static int udp_ipcp_query(const uint8_t * hash)
#ifdef HAVE_DDNS
dns_addr = udp_data.dns_addr;
- if (dns_addr != 0) {
+ if (is_addr_specified(&dns_addr)) {
ip_addr = ddns_resolve(hashstr, dns_addr);
- if (ip_addr == 0) {
+ if (!is_addr_specified(&ip_addr)) {
log_err("Could not resolve %s.", hashstr);
free(hashstr);
return -1;
}
} else {
#endif
- h = gethostbyname(hashstr);
- if (h == NULL) {
- log_err("Could not resolve %s.", hashstr);
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = __AF;
+ if (getaddrinfo(hashstr, NULL, &hints, &ai) != 0) {
+ log_err("Could not resolve %s: %s.", hashstr,
+ gai_strerror(errno));
free(hashstr);
return -1;
}
- ip_addr = *((uint32_t *) (h->h_addr_list[0]));
+ if (ai->ai_family != __AF) {
+ log_err("Wrong addres family for %s.", hashstr);
+ freeaddrinfo(ai);
+ free(hashstr);
+ return -1;
+ }
+
+ #ifdef BUILD_IPCP_UDP4
+ addr.ip4 = ((struct sockaddr_in *) (ai->ai_addr))->sin_addr;
+ #else
+ addr.ip6 = ((struct sockaddr_in6 *) (ai->ai_addr))->sin6_addr;
+ #endif
+ freeaddrinfo(ai);
#ifdef HAVE_DDNS
}
#endif
-
- if (shim_data_dir_add_entry(udp_data.shim_data, hash, ip_addr)) {
+ if (shim_data_dir_add_entry(udp_data.shim_data, hash, addr)) {
log_err("Failed to add directory entry.");
free(hashstr);
return -1;
@@ -986,9 +1024,10 @@ static int udp_ipcp_flow_alloc(int fd,
qosspec_t qs,
const buffer_t * data)
{
- struct sockaddr_in r_saddr; /* Server address */
- uint32_t ip_addr = 0;
- char ipstr[INET_ADDRSTRLEN];
+ struct __SOCKADDR r_saddr; /* Server address */
+ struct __ADDR ip_addr;
+ struct addr addr;
+ char ipstr[__ADDRSTRLEN];
(void) qs;
@@ -999,9 +1038,13 @@ static int udp_ipcp_flow_alloc(int fd,
return -1;
}
- ip_addr = (uint32_t) shim_data_dir_get_addr(udp_data.shim_data, dst);
-
- if (inet4_ntop(&ip_addr, ipstr) == NULL) {
+ addr = shim_data_dir_get_addr(udp_data.shim_data, dst);
+#ifdef BUILD_IPCP_UDP4
+ ip_addr = addr.ip4;
+#else
+ ip_addr = addr.ip6;
+#endif
+ if (__inet_ntop(&ip_addr, ipstr) == NULL) {
log_err("Could not convert IP address.");
return -1;
}
@@ -1010,9 +1053,15 @@ static int udp_ipcp_flow_alloc(int fd,
HASH_VAL32(dst), ipstr);
memset((char *) &r_saddr, 0, sizeof(r_saddr));
- r_saddr.sin_family = AF_INET;
- r_saddr.sin_addr.s_addr = ip_addr;
- r_saddr.sin_port = udp_data.s_saddr.sin_port;
+#ifdef BUILD_IPCP_UDP4
+ r_saddr.sin_family = AF_INET;
+ r_saddr.sin_addr = addr.ip4;
+ r_saddr.sin_port = udp_data.s_saddr.sin_port;
+#else
+ r_saddr.sin6_family = AF_INET6;
+ r_saddr.sin6_addr = addr.ip6;
+ r_saddr.sin6_port = udp_data.s_saddr.sin6_port;
+#endif
if (udp_ipcp_port_alloc(&r_saddr, fd, dst, qs, data) < 0) {
log_err("Could not allocate port.");
@@ -1035,8 +1084,8 @@ static int udp_ipcp_flow_alloc_resp(int fd,
int resp,
const buffer_t * data)
{
- struct sockaddr_in saddr;
- int d_eid;
+ struct __SOCKADDR saddr;
+ int d_eid;
if (ipcp_wait_flow_resp(fd) < 0) {
log_err("Failed to wait for flow response.");
diff --git a/src/ipcpd/udp/udp4.c b/src/ipcpd/udp/udp4.c
new file mode 100644
index 00000000..07d5f818
--- /dev/null
+++ b/src/ipcpd/udp/udp4.c
@@ -0,0 +1,42 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * IPC process over UDP/IPv4
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#define _DEFAULT_SOURCE
+#else
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+#include <ouroboros/ipcp-dev.h>
+
+#define BUILD_IPCP_UDP4
+#define THIS_TYPE IPCP_UDP4
+#define TYPE_STR "IPCP over UDP/IPv4"
+#define OUROBOROS_PREFIX "ipcpd/udp4"
+#define IPCP_UDP_MAX_PACKET_SIZE 8980
+#define __AF AF_INET
+#define __ADDRSTRLEN INET_ADDRSTRLEN
+#define __SOCKADDR sockaddr_in
+#define __ADDR in_addr
+#define __ADDR_ANY_INIT { .s_addr = INADDR_ANY }
+
+#include "udp.c"
diff --git a/src/ipcpd/udp/udp6.c b/src/ipcpd/udp/udp6.c
new file mode 100644
index 00000000..b7924a3f
--- /dev/null
+++ b/src/ipcpd/udp/udp6.c
@@ -0,0 +1,42 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * IPC process over UDP/IPv6
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#define _DEFAULT_SOURCE
+#else
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+#include <ouroboros/ipcp-dev.h>
+
+#define BUILD_IPCP_UDP6
+#define THIS_TYPE IPCP_UDP6
+#define TYPE_STR "IPCP over UDP/IPv6"
+#define OUROBOROS_PREFIX "ipcpd/udp6"
+#define IPCP_UDP_MAX_PACKET_SIZE 8952
+#define __AF AF_INET6
+#define __ADDRSTRLEN INET6_ADDRSTRLEN
+#define __SOCKADDR sockaddr_in6
+#define __ADDR in6_addr
+#define __ADDR_ANY_INIT IN6ADDR_ANY_INIT
+
+#include "udp.c"
diff --git a/src/ipcpd/unicast/CMakeLists.txt b/src/ipcpd/unicast/CMakeLists.txt
index 2df0bae0..ced045e6 100644
--- a/src/ipcpd/unicast/CMakeLists.txt
+++ b/src/ipcpd/unicast/CMakeLists.txt
@@ -73,7 +73,4 @@ install(TARGETS ipcpd-unicast RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
add_subdirectory(pff/tests)
add_subdirectory(routing/tests)
-
-if (NOT GNU)
- add_subdirectory(dir/tests)
-endif ()
+add_subdirectory(dir/tests)
diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in
index c829cfb7..527694c0 100644
--- a/src/irmd/config.h.in
+++ b/src/irmd/config.h.in
@@ -21,7 +21,8 @@
*/
-#define IPCP_UDP_EXEC "@IPCP_UDP_TARGET@"
+#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@"
diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c
index 9b0fa2f3..2dfb41a8 100644
--- a/src/irmd/configfile.c
+++ b/src/irmd/configfile.c
@@ -161,14 +161,16 @@ static int toml_eth_dix(toml_table_t * table,
return 0;
}
-static int toml_udp(toml_table_t * table,
- struct ipcp_config * conf)
+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 = udp_default_conf;
+ *conf = udp4_default_conf;
+ udp4 = &conf->udp4;
ip = toml_string_in(table, "ip");
if (!ip.ok) {
@@ -176,18 +178,68 @@ static int toml_udp(toml_table_t * table,
goto fail_ip;
}
- if (inet_pton (AF_INET, ip.u.s, &conf->udp.ip_addr) != 1) {
+ 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;
}
port = toml_int_in(table, "port");
if (port.ok)
- conf->udp.port = port.u.i;
+ udp4->port = port.u.i;
dns = toml_string_in(table, "dns");
if (dns.ok) {
- if (inet_pton(AF_INET, dns.u.s, &conf->udp.dns_addr) < 0) {
+ 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;
+ }
+
+ free(dns.u.s);
+ }
+
+ free(ip.u.s);
+
+ return 0;
+
+ fail_dns:
+ free(dns.u.s);
+ fail_addr:
+ free(ip.u.s);
+ fail_ip:
+ return -1;
+}
+
+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;
+ }
+
+ 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;
+ }
+
+ port = toml_int_in(table, "port");
+ if (port.ok)
+ conf->udp6.port = port.u.i;
+
+ 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;
}
@@ -643,8 +695,11 @@ static int toml_ipcp(toml_table_t * table,
case IPCP_ETH_LLC:
ret = toml_eth_llc(table, conf);
break;
- case IPCP_UDP:
- ret = toml_udp(table, conf);
+ 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);
@@ -966,8 +1021,10 @@ static int toml_toplevel(toml_table_t * table,
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, "udp") == 0)
- return toml_ipcp_list(subtable, IPCP_UDP);
+ 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/main.c b/src/irmd/main.c
index 05dfdf26..05f9236f 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -191,8 +191,11 @@ static pid_t spawn_ipcp(struct ipcp_info * info)
case IPCP_BROADCAST:
exec_name = IPCP_BROADCAST_EXEC;
break;
- case IPCP_UDP:
- exec_name = IPCP_UDP_EXEC;
+ 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;
@@ -330,7 +333,7 @@ int bootstrap_ipcp(pid_t pid,
goto fail;
}
- if (conf->type == IPCP_UDP)
+ 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)) {
diff --git a/src/lib/pb/ipcp_config.proto b/src/lib/pb/ipcp_config.proto
index becc63c0..1308c6d1 100644
--- a/src/lib/pb/ipcp_config.proto
+++ b/src/lib/pb/ipcp_config.proto
@@ -70,16 +70,24 @@ message eth_config_msg {
required uint32 ethertype = 2;
}
-message udp_config_msg {
+message udp4_config_msg {
required uint32 ip_addr = 1;
required uint32 port = 2;
required uint32 dns_addr = 3; /* set to 0 if unused */
}
+message udp6_config_msg {
+ required bytes ip_addr = 1;
+ required uint32 port = 2;
+ required bytes dns_addr = 3; /* set to NULL if unused */
+}
+
+
message ipcp_config_msg {
required layer_info_msg layer_info = 1;
required uint32 ipcp_type = 2;
optional uni_config_msg unicast = 3;
- optional udp_config_msg udp = 4;
- optional eth_config_msg eth = 5;
+ optional udp4_config_msg udp4 = 4;
+ optional udp6_config_msg udp6 = 5;
+ optional eth_config_msg eth = 6;
}
diff --git a/src/lib/protobuf.c b/src/lib/protobuf.c
index b2a0cb3b..b5ec8778 100644
--- a/src/lib/protobuf.c
+++ b/src/lib/protobuf.c
@@ -512,9 +512,9 @@ struct uni_config uni_config_msg_to_s(const uni_config_msg_t * msg)
return s;
}
-udp_config_msg_t * udp_config_s_to_msg(const struct udp_config * s)
+udp4_config_msg_t * udp4_config_s_to_msg(const struct udp4_config * s)
{
- udp_config_msg_t * msg;
+ udp4_config_msg_t * msg;
assert(s != NULL);
@@ -522,24 +522,77 @@ udp_config_msg_t * udp_config_s_to_msg(const struct udp_config * s)
if (msg == NULL)
return NULL;
- udp_config_msg__init(msg);
+ udp4_config_msg__init(msg);
- msg->ip_addr = s->ip_addr;
- msg->dns_addr = s->dns_addr;
+ msg->ip_addr = s->ip_addr.s_addr;
+ msg->dns_addr = s->dns_addr.s_addr;
msg->port = s->port;
return msg;
}
-struct udp_config udp_config_msg_to_s(const udp_config_msg_t * msg)
+struct udp4_config udp4_config_msg_to_s(const udp4_config_msg_t * msg)
{
- struct udp_config s;
+ struct udp4_config s;
assert(msg != NULL);
- s.ip_addr = msg->ip_addr;
- s.dns_addr = msg->dns_addr;
- s.port = msg->port;
+ s.ip_addr.s_addr = msg->ip_addr;
+ s.dns_addr.s_addr = msg->dns_addr;
+ s.port = msg->port;
+
+ return s;
+}
+
+#define IN6_LEN sizeof(struct in6_addr)
+udp6_config_msg_t * udp6_config_s_to_msg(const struct udp6_config * s)
+{
+ udp6_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ udp6_config_msg__init(msg);
+
+ msg->ip_addr.data = malloc(IN6_LEN);
+ if (msg->ip_addr.data == NULL)
+ goto fail_msg;
+
+ msg->ip_addr.len = IN6_LEN;
+ memcpy(msg->ip_addr.data, &s->ip_addr.s6_addr, IN6_LEN);
+
+ msg->dns_addr.data = malloc(IN6_LEN);
+ if (msg->dns_addr.data == NULL)
+ goto fail_msg;
+
+ msg->dns_addr.len = IN6_LEN;
+ memcpy(msg->dns_addr.data, &s->dns_addr.s6_addr, IN6_LEN);
+
+ msg->port = s->port;
+
+ return msg;
+
+ fail_msg:
+ udp6_config_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct udp6_config udp6_config_msg_to_s(const udp6_config_msg_t * msg)
+{
+ struct udp6_config s;
+
+ assert(msg != NULL);
+
+ assert(msg->ip_addr.len == IN6_LEN);
+ assert(msg->dns_addr.len == IN6_LEN);
+
+ memcpy(&s.ip_addr.s6_addr, msg->ip_addr.data, IN6_LEN);
+ memcpy(&s.dns_addr.s6_addr, msg->dns_addr.data, IN6_LEN);
+ s.port = msg->port;
return s;
}
@@ -613,9 +666,14 @@ ipcp_config_msg_t * ipcp_config_s_to_msg(const struct ipcp_config * s)
if (msg->eth == NULL)
goto fail_msg;
break;
- case IPCP_UDP:
- msg->udp = udp_config_s_to_msg(&s->udp);
- if (msg->udp == NULL)
+ case IPCP_UDP4:
+ msg->udp4 = udp4_config_s_to_msg(&s->udp4);
+ if (msg->udp4 == NULL)
+ goto fail_msg;
+ break;
+ case IPCP_UDP6:
+ msg->udp6 = udp6_config_s_to_msg(&s->udp6);
+ if (msg->udp6 == NULL)
goto fail_msg;
break;
default:
@@ -658,8 +716,11 @@ struct ipcp_config ipcp_config_msg_to_s(const ipcp_config_msg_t * msg)
case IPCP_ETH_DIX:
s.eth = eth_config_msg_to_s(msg->eth);
break;
- case IPCP_UDP:
- s.udp = udp_config_msg_to_s(msg->udp);
+ case IPCP_UDP4:
+ s.udp4 = udp4_config_msg_to_s(msg->udp4);
+ break;
+ case IPCP_UDP6:
+ s.udp6 = udp6_config_msg_to_s(msg->udp6);
break;
case IPCP_BROADCAST:
break;
diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c
index 4bbb9725..3fabc3cc 100644
--- a/src/tools/irm/irm_ipcp_bootstrap.c
+++ b/src/tools/irm/irm_ipcp_bootstrap.c
@@ -46,13 +46,15 @@
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
+#include <netinet/in.h>
#ifdef __FreeBSD__
#include <sys/socket.h>
#endif
#define UNICAST "unicast"
#define BROADCAST "broadcast"
-#define IP_UDP "udp"
+#define IP_UDP4 "udp4"
+#define IP_UDP6 "udp6"
#define ETH_LLC "eth-llc"
#define ETH_DIX "eth-dix"
#define LOCAL "local"
@@ -76,7 +78,8 @@
#define UNI(x) default_uni_config.x
#define DIX(x) eth_dix_default_conf.eth.x
#define LLC(x) eth_llc_default_conf.eth.x
-#define UDP(x) udp_default_conf.udp.x
+#define UD4(x) udp4_default_conf.udp4.x
+#define UD6(x) udp6_default_conf.udp6.x
static char * usage_str = \
"Usage: irm ipcp bootstrap\n"
@@ -84,7 +87,7 @@ static char * usage_str = \
" layer <layer name>\n"
" [type [TYPE]]\n"
"where TYPE in {" UNICAST " " BROADCAST " " LOCAL " "
- IP_UDP " " ETH_LLC " " ETH_DIX "},\n\n"
+ IP_UDP4 " " IP_UDP6 " " ETH_LLC " " ETH_DIX "},\n\n"
"if TYPE == " UNICAST "\n"
" [addr_auth <ADDRESS_POLICY> (default: %s)]\n"
" [directory <DIRECTORY_POLICY> (default: %s)]\n"
@@ -113,11 +116,17 @@ static char * usage_str = \
" [ls_t_recalc <pff recalc interval (s)> (default: %ld)]\n"
" [ls_t_update <LSA update interval (s)> (default: %ld)]\n"
" [ls_t_timeo <link timeout (s)> (default: %ld)]\n\n"
- "if TYPE == " IP_UDP "\n"
+ "if TYPE == " IP_UDP4 "\n"
" ip <IP address in dotted notation>\n"
" [port <UDP port> (default: %d)]\n"
- " [dns <DDNS IP address in dotted notation>"
+ " [dns <DDNS IPv4 address in dotted notation>"
" (default: none)]\n\n"
+ "if TYPE == " IP_UDP6 "\n"
+ " ip <IPv6 address>\n"
+ " [port <UDP port> (default: %d)]\n"
+ " [dns <DDNS IPv6 address>"
+ " (default: none)]\n\n"
+
"if TYPE == " ETH_LLC "\n"
" dev <interface name>\n"
" [hash [ALGORITHM] (default: %s)]\n"
@@ -150,8 +159,10 @@ static void usage(void)
/* ls */
default_ls_config.t_recalc, default_ls_config.t_update,
default_ls_config.t_timeo,
- /* udp */
- UDP(port),
+ /* udp4 */
+ UD4(port),
+ /* udp6 */
+ UD6(port),
/* eth_llc */
SHA3_256,
/* eth_dix */
@@ -177,9 +188,14 @@ int do_bootstrap_ipcp(int argc,
enum pol_addr_auth addr_auth_type = UNI(addr_auth_type);
enum pol_cong_avoid cong_avoid = UNI(cong_avoid);
enum pol_dir_hash hash_algo = DIR_HASH_SHA3_256;
- uint32_t ip_addr = 0;
- uint32_t dns_addr = UDP(dns_addr);
- int port = UDP(port);
+ char * ipstr = NULL;
+ char * dnsstr = NULL;
+ struct in_addr ip4_addr = {.s_addr = INADDR_ANY};
+ struct in_addr dns4_addr = UD4(dns_addr);
+ int port4 = UD4(port);
+ struct in6_addr ip6_addr = IN6ADDR_ANY_INIT;
+ struct in6_addr dns6_addr = UD6(dns_addr);
+ int port6 = UD6(port);
char * ipcp_type = NULL;
enum ipcp_type type = IPCP_INVALID;
char * layer = NULL;
@@ -211,11 +227,9 @@ int do_bootstrap_ipcp(int argc,
else
goto unknown_param;
} else if (matches(*argv, "ip") == 0) {
- if (inet_pton (AF_INET, *(argv + 1), &ip_addr) != 1)
- goto unknown_param;
+ ipstr = *(argv + 1);
} else if (matches(*argv, "dns") == 0) {
- if (inet_pton(AF_INET, *(argv + 1), &dns_addr) != 1)
- goto unknown_param;
+ dnsstr = *(argv + 1);
} else if (matches(*argv, "device") == 0) {
dev = *(argv + 1);
} else if (matches(*argv, "ethertype") == 0) {
@@ -237,7 +251,8 @@ int do_bootstrap_ipcp(int argc,
} else if (matches(*argv, "ttl") == 0) {
max_ttl = atoi(*(argv + 1));
} else if (matches(*argv, "port") == 0) {
- port = atoi(*(argv + 1));
+ port4 = atoi(*(argv + 1));
+ port6 = port4;
} else if (matches(*argv, "autobind") == 0) {
autobind = true;
cargs = 1;
@@ -311,21 +326,59 @@ int do_bootstrap_ipcp(int argc,
}
if (ipcp_type != NULL) {
- if (strcmp(ipcp_type, UNICAST) == 0)
+ if (matches(ipcp_type, UNICAST) == 0)
type = IPCP_UNICAST;
- else if (strcmp(ipcp_type, BROADCAST) == 0)
+ else if (matches(ipcp_type, BROADCAST) == 0)
type = IPCP_BROADCAST;
- else if (strcmp(ipcp_type, IP_UDP) == 0)
- type = IPCP_UDP;
- else if (strcmp(ipcp_type, ETH_LLC) == 0)
- type = IPCP_ETH_LLC;
- else if (strcmp(ipcp_type, ETH_DIX) == 0)
+ else if (matches(ipcp_type, IP_UDP4) == 0)
+ type = IPCP_UDP4;
+ else if (matches(ipcp_type, IP_UDP6) == 0)
+ type = IPCP_UDP6;
+ else if (matches(ipcp_type, ETH_DIX) == 0)
type = IPCP_ETH_DIX;
- else if (strcmp(ipcp_type, LOCAL) == 0)
+ else if (matches(ipcp_type, ETH_LLC) == 0)
+ type = IPCP_ETH_LLC;
+ else if (matches(ipcp_type, LOCAL) == 0)
type = IPCP_LOCAL;
else goto fail_usage;
}
+ if (type == IPCP_UDP4) {
+ if (inet_pton (AF_INET, ipstr, &ip4_addr) != 1) {
+ printf("Invalid IPv4 address: \"%s\".\n", ipstr);
+ goto fail_usage;
+ }
+
+ if (ip4_addr.s_addr == INADDR_ANY) {
+ printf("Cannot use IPv4 address: \"%s\".\n", ipstr);
+ goto fail_usage;
+ }
+
+ if (dnsstr != NULL &&
+ inet_pton(AF_INET, dnsstr, &dns4_addr) != 1) {
+ printf("Invalid DNS IPv4 address: \"%s\".\n", dnsstr);
+ goto fail_usage;
+ }
+ }
+
+ if (type == IPCP_UDP6) {
+ if (inet_pton(AF_INET6, ipstr, &ip6_addr) != 1) {
+ printf("Invalid IPv6 address: \"%s\".\n", ipstr);
+ goto fail_usage;
+ }
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&ip6_addr)) {
+ printf("Cannot use IPv6 address: \"%s\".\n", ipstr);
+ goto fail_usage;
+ }
+
+ if (dnsstr != NULL &&
+ inet_pton(AF_INET6, dnsstr, &dns6_addr) != 1) {
+ printf("Invalid DNS IPv6 address: \"%s\".\n", dnsstr);
+ goto fail_usage;
+ }
+ }
+
if (pid == -1) {
if (ipcp_type == NULL) {
printf("No IPCPs matching %s found.\n\n", ipcp);
@@ -374,12 +427,15 @@ int do_bootstrap_ipcp(int argc,
conf.unicast.cong_avoid = cong_avoid;
conf.unicast.dir = dir_config;
break;
- case IPCP_UDP:
- if (ip_addr == 0)
- goto fail_usage;
- conf.udp.ip_addr = ip_addr;
- conf.udp.dns_addr = dns_addr;
- conf.udp.port = port;
+ case IPCP_UDP4:
+ conf.udp4.ip_addr = ip4_addr;
+ conf.udp4.dns_addr = dns4_addr;
+ conf.udp4.port = port4;
+ break;
+ case IPCP_UDP6:
+ conf.udp6.ip_addr = ip6_addr;
+ conf.udp6.dns_addr = dns6_addr;
+ conf.udp6.port = port6;
break;
case IPCP_ETH_DIX:
conf.eth.ethertype = ethertype;
diff --git a/src/tools/irm/irm_ipcp_create.c b/src/tools/irm/irm_ipcp_create.c
index 35d33782..e2a5c488 100644
--- a/src/tools/irm/irm_ipcp_create.c
+++ b/src/tools/irm/irm_ipcp_create.c
@@ -46,7 +46,8 @@
#define UNICAST "unicast"
#define BROADCAST "broadcast"
-#define UDP "udp"
+#define UDP4 "udp4"
+#define UDP6 "udp6"
#define ETH_LLC "eth-llc"
#define ETH_DIX "eth-dix"
#define LOCAL "local"
@@ -57,7 +58,7 @@ static void usage(void)
" name <ipcp name>\n"
" type [TYPE]\n\n"
"where TYPE in {" UNICAST " " BROADCAST " " LOCAL " "
- UDP " " ETH_LLC " " ETH_DIX "}\n");
+ UDP4 " " UDP6 " " ETH_LLC " " ETH_DIX "}\n");
}
int do_create_ipcp(int argc,
@@ -92,8 +93,10 @@ int do_create_ipcp(int argc,
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, UDP4) == 0)
+ type = IPCP_UDP4;
+ else if (strcmp(ipcp_type, UDP6) == 0)
+ type = IPCP_UDP6;
else if (strcmp(ipcp_type, LOCAL) == 0)
type = IPCP_LOCAL;
else if (strcmp(ipcp_type, ETH_LLC) == 0)
diff --git a/src/tools/irm/irm_ipcp_list.c b/src/tools/irm/irm_ipcp_list.c
index dfa3099f..54985eb4 100644
--- a/src/tools/irm/irm_ipcp_list.c
+++ b/src/tools/irm/irm_ipcp_list.c
@@ -48,7 +48,8 @@
#define UNICAST "unicast"
#define BROADCAST "broadcast"
-#define UDP "udp"
+#define UDP4 "udp4"
+#define UDP6 "udp6"
#define ETH_LLC "eth-llc"
#define ETH_DIX "eth-dix"
#define LOCAL "local"
@@ -60,7 +61,7 @@ static void usage(void)
" [layer <layer_name>]\n\n"
" [type [TYPE]]\n\n"
"where TYPE = {" UNICAST " " LOCAL " "
- UDP " " ETH_LLC " " ETH_DIX "}\n");
+ UDP4 " " UDP6 " " ETH_LLC " " ETH_DIX "}\n");
}
static char * str_type(enum ipcp_type type)
@@ -74,8 +75,10 @@ static char * str_type(enum ipcp_type type)
return ETH_LLC;
case IPCP_ETH_DIX:
return ETH_DIX;
- case IPCP_UDP:
- return UDP;
+ case IPCP_UDP4:
+ return UDP4;
+ case IPCP_UDP6:
+ return UDP6;
case IPCP_LOCAL:
return LOCAL;
default:
@@ -113,8 +116,10 @@ int do_list_ipcp(int argc,
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, UDP4) == 0)
+ type = IPCP_UDP4;
+ else if (strcmp(ipcp_type, UDP6) == 0)
+ type = IPCP_UDP6;
else if (strcmp(ipcp_type, LOCAL) == 0)
type = IPCP_LOCAL;
else if (strcmp(ipcp_type, ETH_LLC) == 0)