diff --git a/mud.c b/mud.c index b212b91..e8da289 100644 --- a/mud.c +++ b/mud.c @@ -9,7 +9,6 @@ #endif #include -#include #include #include #include @@ -287,41 +286,6 @@ mud_unmapv4(struct sockaddr_storage *addr) memcpy(addr, &sin, sizeof(sin)); } -static size_t -mud_addrlen(struct sockaddr_storage *addr) -{ - return (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6); -} - -static int -mud_addrinfo(struct sockaddr_storage *addr, const char *host, int port) -{ - struct sockaddr_in sin = { - .sin_family = AF_INET, - .sin_port = htons(port), - }; - - if (inet_pton(AF_INET, host, &sin.sin_addr) == 1) { - memcpy(addr, &sin, sizeof(sin)); - return 0; - } - - struct sockaddr_in6 sin6 = { - .sin6_family = AF_INET6, - .sin6_port = htons(port), - }; - - if (inet_pton(AF_INET6, host, &sin6.sin6_addr) == 1) { - memcpy(addr, &sin6, sizeof(sin6)); - return 0; - } - - errno = EINVAL; - - return -1; -} - static ssize_t mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now, void *data, size_t size, int tc, int flags) @@ -329,6 +293,10 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now, if (!size) return 0; + const socklen_t addrlen = path->addr.ss_family == AF_INET + ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6); + struct iovec iov = { .iov_base = data, .iov_len = size, @@ -336,7 +304,7 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now, struct msghdr msg = { .msg_name = &path->addr, - .msg_namelen = mud_addrlen(&path->addr), + .msg_namelen = addrlen, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = path->ctrl.data, @@ -405,9 +373,9 @@ mud_set_path(struct mud_path *path, struct sockaddr_storage *local_addr, memset(&path->ctrl, 0, sizeof(path->ctrl)); if (local_addr) - memmove(&path->local_addr, local_addr, mud_addrlen(local_addr)); + memmove(&path->local_addr, local_addr, sizeof(*local_addr)); - memmove(&path->addr, addr, mud_addrlen(addr)); + memmove(&path->addr, addr, sizeof(*addr)); if (addr->ss_family == AF_INET) { if (local_addr) { @@ -506,34 +474,48 @@ mud_path(struct mud *mud, struct sockaddr_storage *local_addr, return path; } -int -mud_peer(struct mud *mud, const char *host, int port) +static int +mud_ss_from_sa(struct sockaddr_storage *ss, struct sockaddr *sa) { - if (!host || !port) { + if (!ss || !sa) { errno = EINVAL; return -1; } - if (mud_addrinfo(&mud->peer.addr, host, port)) + switch (sa->sa_family) { + case AF_INET: + memcpy(ss, sa, sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(ss, sa, sizeof(struct sockaddr_in6)); + break; + default: + errno = EINVAL; + return -1; + } + + mud_unmapv4(ss); + + return 0; +} + +int +mud_peer(struct mud *mud, struct sockaddr *peer) +{ + if (mud_ss_from_sa(&mud->peer.addr, peer)) return -1; - mud_unmapv4(&mud->peer.addr); mud->peer.set = 1; return 0; } int -mud_del_path(struct mud *mud, const char *name) +mud_del_path(struct mud *mud, struct sockaddr *peer) { - if (!name) { - errno = EINVAL; - return -1; - } - struct sockaddr_storage addr; - if (mud_addrinfo(&addr, name, 0)) + if (mud_ss_from_sa(&addr, peer)) return -1; struct mud_path *path; @@ -549,16 +531,16 @@ mud_del_path(struct mud *mud, const char *name) } int -mud_add_path(struct mud *mud, const char *name) +mud_add_path(struct mud *mud, struct sockaddr *peer) { - if (!name || !mud->peer.set) { + if (!mud->peer.set) { errno = EINVAL; return -1; } struct sockaddr_storage addr; - if (mud_addrinfo(&addr, name, 0)) + if (mud_ss_from_sa(&addr, peer)) return -1; return -!mud_path(mud, &addr, &mud->peer.addr, 1); @@ -718,30 +700,6 @@ mud_setup_socket(int fd, int v4, int v6) return 0; } -static int -mud_create_socket(int port, int v4, int v6) -{ - struct sockaddr_storage addr; - - if (mud_addrinfo(&addr, v6 ? "::" : "0.0.0.0", port)) - return -1; - - int fd = socket(addr.ss_family, SOCK_DGRAM, IPPROTO_UDP); - - if (fd == -1) - return -1; - - if (mud_setup_socket(fd, v4, v6) || - bind(fd, (struct sockaddr *)&addr, mud_addrlen(&addr))) { - int err = errno; - close(fd); - errno = err; - return -1; - } - - return fd; -} - static void mud_keyx_set(struct mud *mud, unsigned char *key, unsigned char *secret, unsigned char *pub0, unsigned char *pub1) @@ -818,13 +776,29 @@ mud_set_aes(struct mud *mud) } struct mud * -mud_create(int port, int v4, int v6) +mud_create(struct sockaddr *addr, int v4, int v6) { + if (!addr) + return NULL; + uint64_t now = mud_now(); if (now >> 48) return NULL; + socklen_t addrlen = 0; + + switch (addr->sa_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; + default: + return NULL; + } + if (sodium_init() == -1) return NULL; @@ -835,9 +809,11 @@ mud_create(int port, int v4, int v6) memset(mud, 0, sizeof(struct mud)); - mud->fd = mud_create_socket(port, v4, v6); + mud->fd = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); - if (mud->fd == -1) { + if ((mud->fd == -1) || + (mud_setup_socket(mud->fd, v4, v6)) || + (bind(mud->fd, addr, addrlen))) { mud_delete(mud); return NULL; } diff --git a/mud.h b/mud.h index fae6cda..71fa0d7 100644 --- a/mud.h +++ b/mud.h @@ -3,8 +3,9 @@ #include struct mud; +struct sockaddr; -struct mud *mud_create (int, int, int); +struct mud *mud_create (struct sockaddr *, int, int); void mud_delete (struct mud *); int mud_get_fd (struct mud *); @@ -20,10 +21,10 @@ int mud_set_time_tolerance (struct mud *, unsigned long); int mud_set_tc (struct mud *, int); int mud_set_aes (struct mud *); -int mud_peer (struct mud *, const char *, int); +int mud_peer (struct mud *, struct sockaddr *); -int mud_add_path (struct mud *, const char *); -int mud_del_path (struct mud *, const char *); +int mud_add_path (struct mud *, struct sockaddr *); +int mud_del_path (struct mud *, struct sockaddr *); int mud_recv (struct mud *, void *, size_t); int mud_send (struct mud *, const void *, size_t, int);