diff options
-rw-r--r-- | doc/man/ouroboros.8 | 28 | ||||
-rw-r--r-- | include/ouroboros/ipcp.h | 38 | ||||
-rw-r--r-- | include/ouroboros/protobuf.h | 11 | ||||
-rw-r--r-- | irmd.conf.in | 9 | ||||
-rw-r--r-- | src/ipcpd/eth/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/ipcpd/eth/eth.c | 17 | ||||
-rw-r--r-- | src/ipcpd/ipcp.c | 13 | ||||
-rw-r--r-- | src/ipcpd/shim-data.c | 34 | ||||
-rw-r--r-- | src/ipcpd/shim-data.h | 19 | ||||
-rw-r--r-- | src/ipcpd/udp/CMakeLists.txt | 34 | ||||
-rw-r--r-- | src/ipcpd/udp/udp.c (renamed from src/ipcpd/udp/main.c) | 309 | ||||
-rw-r--r-- | src/ipcpd/udp/udp4.c | 42 | ||||
-rw-r--r-- | src/ipcpd/udp/udp6.c | 42 | ||||
-rw-r--r-- | src/ipcpd/unicast/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/irmd/config.h.in | 3 | ||||
-rw-r--r-- | src/irmd/configfile.c | 77 | ||||
-rw-r--r-- | src/irmd/main.c | 9 | ||||
-rw-r--r-- | src/lib/pb/ipcp_config.proto | 14 | ||||
-rw-r--r-- | src/lib/protobuf.c | 91 | ||||
-rw-r--r-- | src/tools/irm/irm_ipcp_bootstrap.c | 114 | ||||
-rw-r--r-- | src/tools/irm/irm_ipcp_create.c | 11 | ||||
-rw-r--r-- | src/tools/irm/irm_ipcp_list.c | 17 |
22 files changed, 670 insertions, 275 deletions
diff --git a/doc/man/ouroboros.8 b/doc/man/ouroboros.8 index 428fac47..10b86011 100644 --- a/doc/man/ouroboros.8 +++ b/doc/man/ouroboros.8 @@ -127,7 +127,9 @@ creates an IPCP process of type \fItype\fR in the system with name .PP \fBeth-dix\fR - create an IPCP that attaches to Ethernet using DIX frames. .PP -\fBudp\fR - create an IPCP that attaches to a UDP socket. +\fBudp4\fR - create an IPCP that attaches to a UDP/IPv4 socket. +.PP +\fBudp6\fR - create an IPCP that attaches to a UDP/IPv6 socket. .PP \fBunicast\fR - create a unicast IPCP that uses lower level layers. .PP @@ -190,17 +192,17 @@ default: SHA3_256. .RE .PP -\fBudp\fR +\fBudp4\fR .RS 4 .PP -ip \fIip\fR specifies the local IP address to bind to +ip \fIip\fR specifies the local IPv4 address to bind to .PP [dns \fIdns\fR] specifies an optional DDNS server that will be used for the directory. .PP [port \fIport\fR] specifies a UDP port that is used for sending and -receiving ouroboros traffic. This must be the same for the entire UDP -layer. Parallel UDP layers should use different ports. This UDP port +receiving ouroboros traffic. This must be the same for the entire UDP4 +layer. Parallel UDP4 layers should use different ports. This UDP port needs to be forwarded if the server is behind a NAT and wants to receive incoming requests. .br @@ -208,6 +210,22 @@ default: 3435 .RE .PP +\fBudp6\fR +.RS 4 +.PP +ip \fIip\fR specifies the local IPv6 address to bind to +.PP +[dns \fIdns\fR] specifies an optional DDNS server that will be used for +the directory. +.PP +[port \fIport\fR] specifies a UDP port that is used for sending and +receiving ouroboros traffic. This must be the same for the entire UDP6 +layer. Parallel UDP6 layers should use different ports. +.br +default: 3435 +.RE + +.PP \fBunicast\fR .RS 4 .PP diff --git a/include/ouroboros/ipcp.h b/include/ouroboros/ipcp.h index 26fcdec4..c397f250 100644 --- a/include/ouroboros/ipcp.h +++ b/include/ouroboros/ipcp.h @@ -26,6 +26,7 @@ #include <stdint.h> #include <unistd.h> #include <stdbool.h> +#include <netinet/in.h> #include <sys/types.h> #define IPCP_NAME_SIZE 255 @@ -49,7 +50,8 @@ enum ipcp_type { /* IRMd uses order to select an IPCP for flow allocation. */ IPCP_BROADCAST, IPCP_ETH_LLC, IPCP_ETH_DIX, - IPCP_UDP, + IPCP_UDP4, + IPCP_UDP6, IPCP_INVALID }; @@ -257,10 +259,16 @@ struct eth_config { uint16_t ethertype; /* DIX only*/ }; -struct udp_config { - uint32_t ip_addr; - uint32_t dns_addr; - uint16_t port; +struct udp4_config { + struct in_addr ip_addr; + struct in_addr dns_addr; + uint16_t port; +}; + +struct udp6_config { + struct in6_addr ip_addr; + struct in6_addr dns_addr; + uint16_t port; }; /* Layers */ @@ -276,9 +284,10 @@ struct ipcp_config { enum ipcp_type type; union { - struct uni_config unicast; - struct udp_config udp; - struct eth_config eth; + struct uni_config unicast; + struct udp4_config udp4; + struct udp6_config udp6; + struct eth_config eth; }; }; @@ -307,9 +316,16 @@ static const struct ipcp_config eth_llc_default_conf = { } }; -static const struct ipcp_config udp_default_conf = { - .type = IPCP_UDP, - .udp = { +static const struct ipcp_config udp4_default_conf = { + .type = IPCP_UDP4, + .udp4 = { + .port = 3435 + } +}; + +static const struct ipcp_config udp6_default_conf = { + .type = IPCP_UDP6, + .udp6 = { .port = 3435 } }; diff --git a/include/ouroboros/protobuf.h b/include/ouroboros/protobuf.h index 6cb24c2f..780d58dc 100644 --- a/include/ouroboros/protobuf.h +++ b/include/ouroboros/protobuf.h @@ -38,7 +38,8 @@ typedef DtConfigMsg dt_config_msg_t; typedef DirConfigMsg dir_config_msg_t; typedef DirDhtConfigMsg dir_dht_config_msg_t; typedef EthConfigMsg eth_config_msg_t; -typedef UdpConfigMsg udp_config_msg_t; +typedef Udp4ConfigMsg udp4_config_msg_t; +typedef Udp6ConfigMsg udp6_config_msg_t; typedef UniConfigMsg uni_config_msg_t; #include "ipcp.pb-c.h" @@ -94,9 +95,13 @@ eth_config_msg_t * eth_config_s_to_msg(const struct eth_config * s); struct eth_config eth_config_msg_to_s(const eth_config_msg_t * msg); -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); -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); + +udp6_config_msg_t * udp6_config_s_to_msg(const struct udp6_config * s); + +struct udp6_config udp6_config_msg_to_s(const udp6_config_msg_t * msg); ipcp_config_msg_t * ipcp_config_s_to_msg(const struct ipcp_config * s); diff --git a/irmd.conf.in b/irmd.conf.in index 5f44ed45..4861bc51 100644 --- a/irmd.conf.in +++ b/irmd.conf.in @@ -86,13 +86,20 @@ dev="lo" # hash="SHA3_224" # Defaults to SHA3_256. reg=["lan1"] -[udp.udp1] +[udp4.udp1] bootstrap="udp" # Defaults to not set. # BOOTSTRAP CONFIGURATION ip="127.0.0.1" # port=9000 # Defaults to 3435. # dns="127.0.0.1" # Requires a DDNS server. Disables DDNS support if not set. +[udp6.udp2] +bootstrap="udp2" # Defaults to not set. + # BOOTSTRAP CONFIGURATION +ip="::1" +# port=9000 # Defaults to 3435. +# dns="::1" # Requires a DDNS server. Disables DDNS support if not set. + [broadcast.bc1] bootstrap="broadcast" # Defaults to not set. # autobind=true # Defaults to false. 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(ð_data.flows_lock); #ifdef BUILD_ETH_LLC + pthread_rwlock_wrlock(ð_data.flows_lock); ssap = bmp_allocate(eth_data.saps); if (!bmp_is_id_valid(eth_data.saps, ssap)) { pthread_rwlock_unlock(ð_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(ð_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) |