aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libmdsclient/address.c79
-rw-r--r--src/libmdsclient/address.h8
2 files changed, 60 insertions, 27 deletions
diff --git a/src/libmdsclient/address.c b/src/libmdsclient/address.c
index 21017bb..09ef0da 100644
--- a/src/libmdsclient/address.c
+++ b/src/libmdsclient/address.c
@@ -20,7 +20,7 @@
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/socket.h>
+#include <netdb.h>
#include <netinet/ip.h>
#include <limits.h>
#include <string.h>
@@ -53,7 +53,7 @@ static int is_pzinteger(const char* restrict str)
/**
* Set the socket adress, with the address family `AF_UNIX`
*
- * @param out_address Output paramter for the socket address
+ * @param out_address Output parameter for the socket address
* @param pathlen Pointer to a variable where the length of the pathname will be stored
* @param format Formatting string for the pathname (should end with "%zn")
* @param ... Formatting arguments for the pathname (should end with `pathlen`)
@@ -97,29 +97,51 @@ static int set_af_unix(struct sockaddr** restrict out_address, ssize_t* pathlen,
* Set the socket address, with either of the address
* families `AF_INET` and `AF_INET6`
*
- * @param out_address Output paramter for the socket address
- * @param out_domain Output parameter for the protocol famility,
- * unused unless the address familiy is unknown
- * @param address_family The address family, -1 if unknown
- * @param host The host
- * @param port The address
- * @return Zero on success, -1 on error, `errno`
- * will have been set accordinly on error
+ * @param out_address Output parameter for the socket address
+ * @param out_address_len Output parameter for the socket address's allocation size
+ * @param out_gai_error Output parameter for error at `getaddrinfo`
+ * @param out_domain Output parameter for the protocol famility,
+ * unused unless the address familiy is unknown
+ * @param address_family The address family, `AF_UNSPEC` if unknown
+ * @param host The host
+ * @param port The address
+ * @return Zero on success, -1 on error, `errno` will have been
+ * set accordinly on error, `*out_gai_error` may be set
+ * on error and zero returned
*
* @throws ENOMEM Out of memory. Possibly, the application hit the
* RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
*/
__attribute__((nonnull))
-static int set_af_inet(struct sockaddr** restrict out_address, int* restrict out_domain,
- int address_family, const char* restrict host, const char* restrict port)
+static int set_af_inet(struct sockaddr** restrict out_address, socklen_t* restrict out_address_len,
+ int* restrict out_gai_error, int* restrict out_domain, int address_family,
+ const char* restrict host, const char* restrict port)
{
- /* TODO */
+ struct addrinfo hints;
+ struct addrinfo* result;
+ int saved_errno;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = address_family;
+
+ *out_gai_error = getaddrinfo(host, port, &hints, &result);
+ if (*out_gai_error)
+ return 0;
+
+ *out_address = malloc(result->ai_addrlen);
+ if (*out_address == NULL)
+ return saved_errno = errno, freeaddrinfo(result), errno = saved_errno, -1;
+ memcpy(*out_address, result->ai_addr, result->ai_addrlen);
+
+ *out_address_len = result->ai_addrlen;
+ *out_domain =
+ result->ai_family == AF_UNSPEC ? PF_UNSPEC :
+ result->ai_family == AF_INET ? PF_INET :
+ result->ai_family == AF_INET6 ? PF_INET6 :
+ result->ai_family;
+
+ freeaddrinfo(result);
return 0;
- (void) out_address;
- (void) out_domain;
- (void) address_family;
- (void) host;
- (void) port;
}
@@ -151,6 +173,7 @@ int libmds_parse_display_adress(const char* restrict display, libmds_display_add
address->protocol = -1;
address->address = NULL;
address->address_len = 0;
+ address->gai_error = 0;
if (strchr(display, ':') == NULL)
return 0;
@@ -202,21 +225,23 @@ int libmds_parse_display_adress(const char* restrict display, libmds_display_add
#define set(d, t, p) \
address->domain = (d), address->type = (t), address->protocol = (p)
- if (params == NULL) set(-1, SOCK_STREAM, IPPROTO_TCP);
- else if (param_test("ip/tcp", 1, "ip", "stream", "tcp")) set(-1, SOCK_STREAM, IPPROTO_TCP);
- else if (param_test("ipv4/tcp", 1, "ipv4", "stream", "tcp")) set(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- else if (param_test("ipv6/tcp", 1, "ipv6", "stream", "tcp")) set(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
- else if (param_test("inet/tcp", 1, "inet", "stream", "tcp")) set(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- else if (param_test("inet6/tcp", 1, "inet6", "stream", "tcp")) set(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ if (params == NULL) set(PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
+ else if (param_test("ip/tcp", 1, "ip", "stream", "tcp")) set(PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
+ else if (param_test("ipv4/tcp", 1, "ipv4", "stream", "tcp")) set(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ else if (param_test("ipv6/tcp", 1, "ipv6", "stream", "tcp")) set(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ else if (param_test("inet/tcp", 1, "inet", "stream", "tcp")) set(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ else if (param_test("inet6/tcp", 1, "inet6", "stream", "tcp")) set(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
else
return 0;
#undef set
#undef param_test
- return set_af_inet(&(address->address), &(address->domain),
- address->domain == PF_INET ? AF_INET :
- address->domain == PF_INET6 ? AF_INET6 :
+ return set_af_inet(&(address->address), &(address->address_len),
+ &(address->gai_error), &(address->domain),
+ address->domain == PF_UNSPEC ? AF_UNSPEC :
+ address->domain == PF_INET ? AF_INET :
+ address->domain == PF_INET6 ? AF_INET6 :
address->domain, host, port);
}
diff --git a/src/libmdsclient/address.h b/src/libmdsclient/address.h
index 88ad4d3..3a79373 100644
--- a/src/libmdsclient/address.h
+++ b/src/libmdsclient/address.h
@@ -63,6 +63,14 @@ typedef struct libmds_display_address
*/
socklen_t address_len;
+ /**
+ * Code for an error that has occured
+ * when parsing the address, whose
+ * description can be retrieved using
+ * `gia_strerror`, zero if none
+ */
+ int gai_error;
+
} libmds_display_address_t;