Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/c/Makefile	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -98,4 +98,7 @@
 	generic/inet/addr.c \
 	generic/inet/endpoint.c \
+	generic/inet/host.c \
+	generic/inet/hostname.c \
+	generic/inet/hostport.c \
 	generic/inet/tcp.c \
 	generic/inet/udp.c \
Index: uspace/lib/c/generic/inet/addr.c
===================================================================
--- uspace/lib/c/generic/inet/addr.c	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/c/generic/inet/addr.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -290,5 +290,5 @@
 
 static int inet_addr_parse_v4(const char *str, inet_addr_t *raddr,
-    int *prefix)
+    int *prefix, char **endptr)
 {
 	uint32_t a = 0;
@@ -306,9 +306,6 @@
 		i++;
 
-		if (*cur == '\0' || *cur == '/')
+		if (*cur != '.')
 			break;
-
-		if (*cur != '.')
-			return EINVAL;
 
 		if (i < 4)
@@ -326,5 +323,8 @@
 	}
 
-	if (i != 4 || (*cur != '\0'))
+	if (i != 4)
+		return EINVAL;
+
+	if (endptr == NULL && *cur != '\0')
 		return EINVAL;
 
@@ -332,10 +332,15 @@
 	raddr->addr = a;
 
+	if (endptr != NULL)
+		*endptr = cur;
+
 	return EOK;
 }
 
-static int inet_addr_parse_v6(const char *str, inet_addr_t *raddr, int *prefix)
+static int inet_addr_parse_v6(const char *str, inet_addr_t *raddr, int *prefix,
+    char **endptr)
 {
 	uint8_t data[16];
+	int explicit_groups;
 
 	memset(data, 0, 16);
@@ -351,15 +356,12 @@
 		wildcard_pos = 0;
 		wildcard_size = 16;
-
-		/* Handle the unspecified address */
-		if (*cur == '\0')
-			goto success;
 	}
 
 	while (i < 16) {
 		uint16_t bioctet;
-		int rc = str_uint16_t(cur, &cur, 16, false, &bioctet);
+		const char *gend;
+		int rc = str_uint16_t(cur, &gend, 16, false, &bioctet);
 		if (rc != EOK)
-			return rc;
+			break;
 
 		data[i] = (bioctet >> 8) & 0xff;
@@ -375,12 +377,12 @@
 		i += 2;
 
-		if (*cur != ':')
+		if (*gend != ':') {
+			cur = gend;
 			break;
+		}
 
 		if (i < 16) {
-			cur++;
-
 			/* Handle wildcard */
-			if (*cur == ':') {
+			if (gend[1] == ':') {
 				if (wildcard_pos != (size_t) -1)
 					return EINVAL;
@@ -388,11 +390,11 @@
 				wildcard_pos = i;
 				wildcard_size = 16 - i;
-				cur++;
-
-				if (*cur == '\0' || *cur == '/')
-					break;
+				cur = gend + 2;
 			}
 		}
 	}
+
+	/* Number of explicitly specified groups */
+	explicit_groups = i;
 
 	if (prefix != NULL) {
@@ -406,5 +408,5 @@
 	}
 
-	if (*cur != '\0')
+	if (endptr == NULL && *cur != '\0')
 		return EINVAL;
 
@@ -418,29 +420,38 @@
 			data[j] = 0;
 		}
-	}
-
-success:
+	} else {
+		/* Verify that all groups have been specified */
+		if (explicit_groups != 16)
+			return EINVAL;
+	}
+
 	raddr->version = ip_v6;
 	memcpy(raddr->addr6, data, 16);
+	if (endptr != NULL)
+		*endptr = (char *)cur;
 	return EOK;
 }
 
 /** Parse node address.
+ *
+ * Will fail if @a text contains extra characters at the and and @a endptr
+ * is @c NULL.
  *
  * @param text Network address in common notation.
  * @param addr Place to store node address.
+ * @param endptr Place to store pointer to next character oc @c NULL
  *
  * @return EOK on success, EINVAL if input is not in valid format.
  *
  */
-int inet_addr_parse(const char *text, inet_addr_t *addr)
+int inet_addr_parse(const char *text, inet_addr_t *addr, char **endptr)
 {
 	int rc;
 
-	rc = inet_addr_parse_v4(text, addr, NULL);
+	rc = inet_addr_parse_v4(text, addr, NULL, endptr);
 	if (rc == EOK)
 		return EOK;
 
-	rc = inet_addr_parse_v6(text, addr, NULL);
+	rc = inet_addr_parse_v6(text, addr, NULL, endptr);
 	if (rc == EOK)
 		return EOK;
@@ -451,11 +462,15 @@
 /** Parse network address.
  *
+ * Will fail if @a text contains extra characters at the and and @a endptr
+ * is @c NULL.
+ *
  * @param text  Network address in common notation.
  * @param naddr Place to store network address.
+ * @param endptr Place to store pointer to next character oc @c NULL
  *
  * @return EOK on success, EINVAL if input is not in valid format.
  *
  */
-int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
+int inet_naddr_parse(const char *text, inet_naddr_t *naddr, char **endptr)
 {
 	int rc;
@@ -463,5 +478,5 @@
 	int prefix;
 
-	rc = inet_addr_parse_v4(text, &addr, &prefix);
+	rc = inet_addr_parse_v4(text, &addr, &prefix, endptr);
 	if (rc == EOK) {
 		inet_addr_naddr(&addr, prefix, naddr);
@@ -469,5 +484,5 @@
 	}
 
-	rc = inet_addr_parse_v6(text, &addr, &prefix);
+	rc = inet_addr_parse_v6(text, &addr, &prefix, endptr);
 	if (rc == EOK) {
 		inet_addr_naddr(&addr, prefix, naddr);
Index: uspace/lib/c/generic/inet/host.c
===================================================================
--- uspace/lib/c/generic/inet/host.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/generic/inet/host.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file Internet host specification
+ *
+ * Either a host name or an address.
+ */
+
+#include <errno.h>
+#include <inet/addr.h>
+#include <inet/dnsr.h>
+#include <inet/host.h>
+#include <inet/hostname.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+
+/** Parse host string.
+ *
+ * @param str Host string
+ * @param rhost Place to store pointer to new host structure
+ * @param endptr Place to store pointer to next character in string or @c NULL
+ *
+ * @return EOK on success. EINVAL if @a str does not start with a valid
+ *         host specification or if @a endptr is @c NULL and @a str contains
+ *         extra characters at the end. ENOMEM if out of memory
+ */
+int inet_host_parse(const char *str, inet_host_t **rhost,
+    char **endptr)
+{
+	inet_host_t *host;
+	inet_addr_t addr;
+	char *name;
+	char *aend;
+	int rc;
+
+	host = calloc(1, sizeof(inet_host_t));
+	if (host == NULL)
+		return ENOMEM;
+
+	/* Try address */
+	rc = inet_addr_parse(str, &addr, &aend);
+	if (rc == EOK) {
+		host->hform = inet_host_addr;
+		host->host.addr = addr;
+		goto have_host;
+	}
+
+
+	/* Try <hostname> */
+	rc = inet_hostname_parse(str, &name, &aend);
+	if (rc == EOK) {
+		host->hform = inet_host_name;
+		host->host.name = name;
+		goto have_host;
+	}
+
+	free(host);
+	return EINVAL;
+
+have_host:
+	if (*aend != '\0' && endptr == NULL) {
+		/* Extra characters */
+		free(host);
+		return EINVAL;
+	}
+
+	*rhost = host;
+	if (endptr != NULL)
+		*endptr = (char *)aend;
+	return EOK;
+}
+
+/** Convert host structure to string representation.
+ *
+ * @param host Host structure
+ * @param rstr Place to store pointer to new string
+ * @return EOK on success, ENOMEM if out of memory
+ */
+int inet_host_format(inet_host_t *host, char **rstr)
+{
+	int rc;
+	char *str = NULL;
+
+	switch (host->hform) {
+	case inet_host_addr:
+		rc = inet_addr_format(&host->host.addr, &str);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			return ENOMEM;
+		}
+
+		break;
+	case inet_host_name:
+		str = str_dup(host->host.name);
+		if (str == NULL)
+			return ENOMEM;
+		break;
+	}
+
+	*rstr = str;
+	return EOK;
+}
+
+/** Destroy host structure.
+ *
+ * @param host Host structure or @c NULL
+ */
+void inet_host_destroy(inet_host_t *host)
+{
+	if (host == NULL)
+		return;
+
+	switch (host->hform) {
+	case inet_host_addr:
+		break;
+	case inet_host_name:
+		free(host->host.name);
+		break;
+	}
+
+	free(host);
+}
+
+/** Look up first address corresponding to host.
+ *
+ * If host contains a host name, name resolution is performed.
+ *
+ * @param host Host structure
+ * @param version Desired IP version (ip_any to get any version)
+ * @param addr Place to store address
+ *
+ * @reutrn EOK on success, ENOENT on resolurion failure
+ */
+int inet_host_lookup_one(inet_host_t *host, ip_ver_t version, inet_addr_t *addr)
+{
+	dnsr_hostinfo_t *hinfo = NULL;
+	int rc;
+
+	switch (host->hform) {
+	case inet_host_addr:
+		*addr = host->host.addr;
+		break;
+	case inet_host_name:
+		rc = dnsr_name2host(host->host.name, &hinfo, version);
+		if (rc != EOK) {
+			dnsr_hostinfo_destroy(hinfo);
+			return ENOENT;
+		}
+
+		*addr = hinfo->addr;
+		dnsr_hostinfo_destroy(hinfo);
+		break;
+	}
+
+	return EOK;
+}
+
+/** Look up first address corresponding to host string.
+ *
+ * If host contains a host name, name resolution is performed.
+ *
+ * @param str Host string
+ * @param version Desired IP version (ip_any to get any version)
+ * @param addr Place to store address
+ * @param endptr Place to store pointer to next character in string or @c NULL
+ * @param errmsg Place to store pointer to error message (no need to free it)
+ *               or @c NULL
+ *
+ * @return EOK on success. EINVAL if @a str has incorrect format or if
+ *         @a endptr is @c NULL and @a str contains extra characters at
+ *         the end. ENOENT if host was not found during resolution,
+ *         ENOMEM if out of memory
+ */
+int inet_host_plookup_one(const char *str, ip_ver_t version, inet_addr_t *addr,
+    char **endptr, const char **errmsg)
+{
+	inet_host_t *host = NULL;
+	char *eptr;
+	int rc;
+
+	rc = inet_host_parse(str, &host, endptr != NULL ? &eptr : NULL);
+	if (rc != EOK) {
+		switch (rc) {
+		case EINVAL:
+			if (errmsg != NULL)
+				*errmsg = "Invalid format";
+			goto error;
+		case ENOMEM:
+			if (errmsg != NULL)
+				*errmsg = "Out of memory";
+			goto error;
+		default:
+			assert(false);
+		}
+	}
+
+	rc = inet_host_lookup_one(host, version, addr);
+	if (rc != EOK) {
+		/* XXX Distinguish between 'not found' and other error */
+		rc = ENOENT;
+		if (errmsg != NULL)
+			*errmsg = "Name resolution failed";
+		goto error;
+	}
+
+	inet_host_destroy(host);
+	if (endptr != NULL)
+		*endptr = eptr;
+	return EOK;
+error:
+	inet_host_destroy(host);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inet/hostname.c
===================================================================
--- uspace/lib/c/generic/inet/hostname.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/generic/inet/hostname.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file Internet host name
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <inet/hostname.h>
+#include <stdlib.h>
+#include <str.h>
+
+/** Parse host name
+ *
+ * Determine whether string begins with a valid host name and where that
+ * host name ends.
+ *
+ * Currntly accepting names per 'host' definition in RFC 1738
+ * (Uniform Resource Locators) - generic URI syntax not accepted.
+ *
+ * @param str String containing host name
+ * @param rname Place to store pointer to new string containing just the
+ *              host name or @c NULL if not interested
+ * @param endptr Place to store pointer to next character in string or @c NULL
+ *               if no extra characters in the string are allowed
+ *
+ * @return EOK on success. EINVAL if @a str does not start with a valid
+ *         host name or if @a endptr is @c NULL and @a str contains
+ *         extra characters at the end. ENOMEM if out of memory
+ */
+int inet_hostname_parse(const char *str, char **rname, char **endptr)
+{
+	const char *c;
+	const char *dstart = NULL;
+	char *name;
+
+	c = str;
+	while (isalnum(*c)) {
+		/* Domain label */
+		dstart = c;
+
+		do {
+			++c;
+		} while (isalnum(*c) || *c == '-');
+
+		/* Domain separator? */
+		if (*c != '.' || !isalnum(c[1]))
+			break;
+
+		++c;
+	}
+
+	/*
+	 * Last domain label must not start with a digit (to distinguish from
+	 * IPv4 address)
+	 */
+	if (dstart == NULL || !isalpha(*dstart))
+		return EINVAL;
+
+	/* If endptr is null, check that entire string matched */
+	if (endptr == NULL && *c != '\0')
+		return EINVAL;
+
+	if (endptr != NULL)
+		*endptr = (char *)c;
+
+	if (rname != NULL) {
+		name = str_ndup(str, c - str);
+		if (name == NULL)
+			return ENOMEM;
+
+		*rname = name;
+	}
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/inet/hostport.c
===================================================================
--- uspace/lib/c/generic/inet/hostport.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/generic/inet/hostport.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file Internet host:port specification
+ *
+ * As in RFC 1738 Uniform Resouce Locators (URL) and RFC 2732 Format for
+ * literal IPv6 Addresses in URLs
+ */
+
+#include <errno.h>
+#include <inet/addr.h>
+#include <inet/dnsr.h>
+#include <inet/endpoint.h>
+#include <inet/hostname.h>
+#include <inet/hostport.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+
+/** Parse host:port string.
+ *
+ * @param str Host:port string
+ * @param rhp Place to store pointer to new hostport structure
+ * @param endptr Place to store pointer to next character in string or @c NULL
+ *
+ * @return EOK on success. EINVAL if @a str does not start with a valid
+ *         host:port or if @a endptr is @c NULL and @a str contains
+ *         extra characters at the end. ENOMEM if out of memory
+ */
+int inet_hostport_parse(const char *str, inet_hostport_t **rhp,
+    char **endptr)
+{
+	inet_hostport_t *hp;
+	inet_addr_t addr;
+	uint16_t port;
+	char *name;
+	char *aend;
+	const char *pend;
+	int rc;
+
+	hp = calloc(1, sizeof(inet_hostport_t));
+	if (hp == NULL)
+		return ENOMEM;
+
+	if (str[0] == '[') {
+		/* Try [<ip-addr-literal>] */
+		rc = inet_addr_parse(str + 1, &addr, &aend);
+		if (rc == EOK) {
+			if (*aend == ']') {
+				hp->hform = inet_host_addr;
+				hp->host.addr = addr;
+				++aend;
+			}
+			goto have_host;
+		}
+	}
+
+	/* Try <ipv4-addr> */
+	rc = inet_addr_parse(str, &addr, &aend);
+	if (rc == EOK) {
+		hp->hform = inet_host_addr;
+		hp->host.addr = addr;
+		goto have_host;
+	}
+
+	/* Try <hostname> */
+	rc = inet_hostname_parse(str, &name, &aend);
+	if (rc == EOK) {
+		hp->hform = inet_host_name;
+		hp->host.name = name;
+		goto have_host;
+	}
+
+	free(hp);
+	return EINVAL;
+
+have_host:
+	if (*aend == ':') {
+		/* Port number */
+		rc = str_uint16_t(aend + 1, &pend, 10, false, &port);
+		if (rc != EOK) {
+			free(hp);
+			return EINVAL;
+		}
+	} else {
+		/* Port number omitted */
+		port = 0;
+		pend = aend;
+	}
+
+	hp->port = port;
+
+	if (*pend != '\0' && endptr == NULL) {
+		/* Extra characters */
+		free(hp);
+		return EINVAL;
+	}
+
+	*rhp = hp;
+	if (endptr != NULL)
+		*endptr = (char *)pend;
+	return EOK;
+}
+
+/** Convert host:port to string representation.
+ *
+ * @param hp Host:port structure
+ * @param rstr Place to store pointer to new string
+ * @return EOK on success, ENOMEM if out of memory
+ */
+int inet_hostport_format(inet_hostport_t *hp, char **rstr)
+{
+	int rc;
+	char *astr, *str;
+	char *hstr = NULL;
+
+	switch (hp->hform) {
+	case inet_host_addr:
+		rc = inet_addr_format(&hp->host.addr, &astr);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			return ENOMEM;
+		}
+
+		if (hp->host.addr.version != ip_v4) {
+			hstr = astr;
+		} else {
+			rc = asprintf(&hstr, "[%s]", astr);
+			if (rc < 0) {
+				free(astr);
+				return ENOMEM;
+			}
+
+			free(astr);
+		}
+
+		break;
+	case inet_host_name:
+		hstr = str_dup(hp->host.name);
+		if (hstr == NULL)
+			return ENOMEM;
+		break;
+	}
+
+	rc = asprintf(&str, "%s:%u", hstr, hp->port);
+	if (rc < 0)
+		return ENOMEM;
+
+	free(hstr);
+	*rstr = str;
+	return EOK;
+}
+
+/** Destroy host:port structure.
+ *
+ * @param hp Host:port or @c NULL
+ */
+void inet_hostport_destroy(inet_hostport_t *hp)
+{
+	if (hp == NULL)
+		return;
+
+	switch (hp->hform) {
+	case inet_host_addr:
+		break;
+	case inet_host_name:
+		free(hp->host.name);
+		break;
+	}
+
+	free(hp);
+}
+
+/** Look up first endpoint corresponding to host:port.
+ *
+ * If host:port contains a host name, name resolution is performed.
+ *
+ * @param hp Host:port structure
+ * @param version Desired IP version (ip_any to get any version)
+ * @param ep Place to store endpoint
+ *
+ * @return EOK on success, ENOENT on resolution failure
+ */
+int inet_hostport_lookup_one(inet_hostport_t *hp, ip_ver_t version,
+    inet_ep_t *ep)
+{
+	dnsr_hostinfo_t *hinfo = NULL;
+	int rc;
+
+	inet_ep_init(ep);
+
+	switch (hp->hform) {
+	case inet_host_addr:
+		ep->addr = hp->host.addr;
+		break;
+	case inet_host_name:
+		rc = dnsr_name2host(hp->host.name, &hinfo, ip_any);
+		if (rc != EOK) {
+			dnsr_hostinfo_destroy(hinfo);
+			return ENOENT;
+		}
+
+		ep->addr = hinfo->addr;
+		dnsr_hostinfo_destroy(hinfo);
+		break;
+	}
+
+	ep->port = hp->port;
+	return EOK;
+}
+
+/** Look up first endpoint corresponding to host:port string.
+ *
+ * If host:port contains a host name, name resolution is performed.
+ *
+ * @param str Host:port string
+ * @param version Desired IP version (ip_any to get any version)
+ * @param ep Place to store endpoint
+ * @param endptr Place to store pointer to next character in string or @c NULL
+ * @param errmsg Place to store pointer to error message (no need to free it)
+ *               or @c NULL
+ *
+ * @return EOK on success. EINVAL if @a str has incorrect format or if
+ *         @a endptr is @c NULL and @a str contains extra characters at
+ *         the end. ENOENT if host was not found during resolution,
+ *         ENOMEM if out of memory
+ */
+int inet_hostport_plookup_one(const char *str, ip_ver_t version, inet_ep_t *ep,
+    char **endptr, const char **errmsg)
+{
+	inet_hostport_t *hp = NULL;
+	char *eptr;
+	int rc;
+
+	rc = inet_hostport_parse(str, &hp, endptr != NULL ? &eptr : NULL);
+	if (rc != EOK) {
+		switch (rc) {
+		case EINVAL:
+			if (errmsg != NULL)
+				*errmsg = "Invalid format";
+			goto error;
+		case ENOMEM:
+			if (errmsg != NULL)
+				*errmsg = "Out of memory";
+			goto error;
+		case EOK:
+			break;
+		default:
+			assert(false);
+		}
+	}
+
+	rc = inet_hostport_lookup_one(hp, version, ep);
+	if (rc != EOK) {
+		/* XXX Distinguish between 'not found' and other error */
+		rc = ENOENT;
+		if (errmsg != NULL)
+			*errmsg = "Name resolution failed";
+		goto error;
+	}
+
+	inet_hostport_destroy(hp);
+	if (endptr != NULL)
+		*endptr = eptr;
+	return EOK;
+error:
+	inet_hostport_destroy(hp);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/addr.h
===================================================================
--- uspace/lib/c/include/inet/addr.h	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/c/include/inet/addr.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -111,6 +111,6 @@
 extern int inet_naddr_compare_mask(const inet_naddr_t *, const inet_addr_t *);
 
-extern int inet_addr_parse(const char *, inet_addr_t *);
-extern int inet_naddr_parse(const char *, inet_naddr_t *);
+extern int inet_addr_parse(const char *, inet_addr_t *, char **);
+extern int inet_naddr_parse(const char *, inet_naddr_t *, char **);
 
 extern int inet_addr_format(const inet_addr_t *, char **);
Index: uspace/lib/c/include/inet/dnsr.h
===================================================================
--- uspace/lib/c/include/inet/dnsr.h	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/c/include/inet/dnsr.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -33,6 +33,6 @@
  */
 
-#ifndef LIBC_INET_DNSRES_H_
-#define LIBC_INET_DNSRES_H_
+#ifndef LIBC_INET_DNSR_H_
+#define LIBC_INET_DNSR_H_
 
 #include <inet/inet.h>
Index: uspace/lib/c/include/inet/endpoint.h
===================================================================
--- uspace/lib/c/include/inet/endpoint.h	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/c/include/inet/endpoint.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -33,6 +33,6 @@
  */
 
-#ifndef LIBC_INET_ASSOC_H_
-#define LIBC_INET_ASSOC_H_
+#ifndef LIBC_INET_ENDPOINT_H_
+#define LIBC_INET_ENDPOINT_H_
 
 #include <stdint.h>
Index: uspace/lib/c/include/inet/host.h
===================================================================
--- uspace/lib/c/include/inet/host.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/include/inet/host.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_HOST_H_
+#define LIBC_INET_HOST_H_
+
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <types/inet/hostport.h>
+
+extern int inet_host_parse(const char *, inet_host_t **, char **);
+extern int inet_host_format(inet_host_t *, char **);
+extern void inet_host_destroy(inet_host_t *);
+extern int inet_host_lookup_one(inet_host_t *, ip_ver_t, inet_addr_t *);
+extern int inet_host_plookup_one(const char *, ip_ver_t, inet_addr_t *,
+    char **, const char **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/hostname.h
===================================================================
--- uspace/lib/c/include/inet/hostname.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/include/inet/hostname.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_HOSTNAME_H_
+#define LIBC_INET_HOSTNAME_H_
+
+extern int inet_hostname_parse(const char *, char **, char **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/inet/hostport.h
===================================================================
--- uspace/lib/c/include/inet/hostport.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/include/inet/hostport.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_HOSTPORT_H_
+#define LIBC_INET_HOSTPORT_H_
+
+#include <inet/addr.h>
+#include <inet/endpoint.h>
+#include <types/inet/hostport.h>
+
+extern int inet_hostport_parse(const char *, inet_hostport_t **, char **);
+extern int inet_hostport_format(inet_hostport_t *, char **);
+extern void inet_hostport_destroy(inet_hostport_t *);
+extern int inet_hostport_lookup_one(inet_hostport_t *, ip_ver_t, inet_ep_t *);
+extern int inet_hostport_plookup_one(const char *, ip_ver_t, inet_ep_t *,
+    char **, const char **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/types/inet/host.h
===================================================================
--- uspace/lib/c/include/types/inet/host.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/include/types/inet/host.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_TYPES_INET_HOST_H_
+#define LIBC_TYPES_INET_HOST_H_
+
+#include <inet/addr.h>
+
+typedef enum {
+	/** Host name */
+	inet_host_name,
+	/** Host address */
+	inet_host_addr
+} inet_host_form_t;
+
+/** Internet host:port specification
+ *
+ * As in RFC 1738 Uniform Resouce Locators (URL) and RFC 2732 Format for
+ * literal IPv6 Addresses in URLs
+ */
+typedef struct {
+	/** Host form */
+	inet_host_form_t hform;
+
+	union {
+		/** Host name */
+		char *name;
+		/** Host address */
+		inet_addr_t addr;
+	} host;
+} inet_host_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/types/inet/hostport.h
===================================================================
--- uspace/lib/c/include/types/inet/hostport.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
+++ uspace/lib/c/include/types/inet/hostport.h	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_TYPES_INET_HOSTPORT_H_
+#define LIBC_TYPES_INET_HOSTPORT_H_
+
+#include <inet/addr.h>
+#include <stdint.h>
+#include <types/inet/host.h>
+
+/** Internet host:port specification
+ *
+ * As in RFC 1738 Uniform Resouce Locators (URL) and RFC 2732 Format for
+ * literal IPv6 Addresses in URLs
+ */
+typedef struct {
+	/** Host form */
+	inet_host_form_t hform;
+
+	union {
+		/** Host name */
+		char *name;
+		/** Host address */
+		inet_addr_t addr;
+	} host;
+
+	/** Port number of 0 if omitted */
+	uint16_t port;
+} inet_hostport_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/http/src/http.c
===================================================================
--- uspace/lib/http/src/http.c	(revision ae7bbfd0bcf872d80ac6f3f37faf7fa216782613)
+++ uspace/lib/http/src/http.c	(revision dc0e41c0a99302899fc0abd3fe566ef8a5a04157)
@@ -40,5 +40,6 @@
 #include <macros.h>
 
-#include <inet/dnsr.h>
+#include <inet/endpoint.h>
+#include <inet/host.h>
 #include <inet/tcp.h>
 
@@ -88,18 +89,8 @@
 		return EBUSY;
 	
-	/* Interpret as address */
-	int rc = inet_addr_parse(http->host, &http->addr);
-	
-	if (rc != EOK) {
-		/* Interpret as a host name */
-		dnsr_hostinfo_t *hinfo = NULL;
-		rc = dnsr_name2host(http->host, &hinfo, ip_any);
-		
-		if (rc != EOK)
-			return rc;
-		
-		http->addr = hinfo->addr;
-		dnsr_hostinfo_destroy(hinfo);
-	}
+	int rc = inet_host_plookup_one(http->host, ip_any, &http->addr, NULL,
+	    NULL);
+	if (rc != EOK)
+		return rc;
 	
 	inet_ep2_t epp;
