diff options
Diffstat (limited to 'src/ipcpd')
-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 |
10 files changed, 339 insertions, 184 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(ð_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) |