Index: uspace/app/df/df.c
===================================================================
--- uspace/app/df/df.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/app/df/df.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -50,5 +50,5 @@
 #define HEADER_TABLE_HR "Filesystem           Size           Used      Available Used%% Mounted on"
 
-#define PERCENTAGE(x, tot) ((unsigned long long) (100L * (x) / (tot)))
+#define PERCENTAGE(x, tot) (tot ? (100ULL * (x) / (tot)) : 0)
 #define FSBK_TO_BK(x, fsbk, bk) \
 	(((fsbk) != 0 && (fsbk) < (bk)) ? \
@@ -59,5 +59,5 @@
 static unsigned int human_readable;
 
-static int size_to_human_readable(char buf[], uint64_t bytes);
+static void size_to_human_readable(char *buf, uint64_t bytes);
 static void print_header(void);
 static void print_statfs(struct statfs *, char *, char *);
@@ -90,5 +90,6 @@
  
 		case ':':
-			fprintf(stderr, "Option -%c requires an operand\n", optopt);
+			fprintf(stderr, "Option -%c requires an operand\n",
+			    optopt);
 			errflg++;
 			break;
@@ -100,5 +101,6 @@
 
 		default:
-			fprintf(stderr, "Unknown error while parsing command line options.");
+			fprintf(stderr,
+			    "Unknown error while parsing command line options");
 			errflg++;
 			break;
@@ -107,5 +109,5 @@
 
 	if (optind > argc) {
-		fprintf(stderr, "Too many input parameter\n");
+		fprintf(stderr, "Too many input parameters\n");
 		errflg++;
 	}
@@ -118,4 +120,5 @@
 	LIST_INITIALIZE(mtab_list);
 	get_mtab_list(&mtab_list);
+
 	print_header();
 	list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
@@ -123,24 +126,20 @@
 		print_statfs(&st, mtab_ent->fs_name, mtab_ent->mp);
 	}
+
 	putchar('\n');
 	return 0;
 }
 
-static int size_to_human_readable(char buf[], uint64_t bytes)
+static void size_to_human_readable(char *buf, uint64_t bytes)
 {
 	const char *units = "BkMGTPEZY";
 	int i = 0;
-	int limit;
-
-	limit = str_length(units);
+
 	while (bytes >= 1024) {
-		if (i >= limit) 
-			return -1;
 		bytes /= 1024;
 		i++;
 	}
-	snprintf(buf, 6, "%4llu%c", (unsigned long long)bytes, units[i]);
-
-	return 0;
+
+	snprintf(buf, 6, "%4llu%c", (unsigned long long) bytes, units[i]);
 }
 
@@ -151,4 +150,5 @@
 	else
 		printf(HEADER_TABLE, unit_size);
+
 	putchar('\n');
 }
@@ -156,27 +156,38 @@
 static void print_statfs(struct statfs *st, char *name, char *mountpoint)
 {
+	uint64_t const used_blocks = st->f_blocks - st->f_bfree;
+	unsigned const perc_used = PERCENTAGE(used_blocks, st->f_blocks);
+
 	printf("%10s", name);
 
 	if (human_readable) {
 		char tmp[1024];
+
+		/* Print size */
 		size_to_human_readable(tmp, st->f_blocks *  st->f_bsize);
-		printf(" %14s", tmp);                                                                  /* Size       */
-		size_to_human_readable(tmp, (st->f_blocks - st->f_bfree)  *  st->f_bsize);
-		printf(" %14s", tmp);                                                                  /* Used       */
+		printf(" %14s", tmp);
+
+		/* Number of used blocks */
+		size_to_human_readable(tmp, used_blocks  *  st->f_bsize);
+		printf(" %14s", tmp);
+
+		/* Number of available blocks */
 		size_to_human_readable(tmp, st->f_bfree *  st->f_bsize);
-		printf(" %14s", tmp);                                                                  /* Available  */
-		printf(" %4llu%% %s\n", 
-			(st->f_blocks)?PERCENTAGE(st->f_blocks - st->f_bfree, st->f_blocks):0L,        /* Used%      */
-			mountpoint                                                                     /* Mounted on */
-		);
-	}
-	else
-		printf(" %15llu %14llu %14llu %4llu%% %s\n", 
-			FSBK_TO_BK(st->f_blocks, st->f_bsize, unit_size),                              /* Blocks     */
-			FSBK_TO_BK(st->f_blocks - st->f_bfree, st->f_bsize, unit_size),                /* Used       */
-			FSBK_TO_BK(st->f_bfree, st->f_bsize, unit_size),                               /* Available  */
-			(st->f_blocks)?PERCENTAGE(st->f_blocks - st->f_bfree, st->f_blocks):0L,        /* Used%      */
-			mountpoint                                                                     /* Mounted on */
-		);
+		printf(" %14s", tmp);
+
+		/* Percentage of used blocks */
+		printf(" %4u%%", perc_used);
+
+		/* Mount point */
+		printf(" %s\n", mountpoint);
+	} else {
+		/* Blocks / Used blocks / Available blocks / Used% / Mounted on */
+		printf(" %15llu %14llu %14llu %4u%% %s\n", 
+		    FSBK_TO_BK(st->f_blocks, st->f_bsize, unit_size),
+		    FSBK_TO_BK(used_blocks, st->f_bsize, unit_size),
+		    FSBK_TO_BK(st->f_bfree, st->f_bsize, unit_size),
+		    perc_used,
+		    mountpoint);
+	}
 
 }
Index: uspace/app/inet/inet.c
===================================================================
--- uspace/app/inet/inet.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/app/inet/inet.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -312,4 +312,50 @@
 }
 
+static int link_list(void)
+{
+	sysarg_t *link_list;
+	inet_link_info_t linfo;
+
+	size_t count;
+	size_t i;
+	int rc;
+
+	rc = inetcfg_get_link_list(&link_list, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting link list.\n");
+		return rc;
+	}
+
+	printf("IP links:\n");
+	if (count > 0)
+		printf("    [Link-layer Address] [Link-Name] [Def-MTU]\n");
+
+	for (i = 0; i < count; i++) {
+		rc = inetcfg_link_get(link_list[i], &linfo);
+		if (rc != EOK) {
+			printf("Failed getting properties of link %zu.\n",
+			    (size_t)link_list[i]);
+			continue;
+		}
+
+		printf("    %02x:%02x:%02x:%02x:%02x:%02x %s %zu\n",
+		    linfo.mac_addr[0], linfo.mac_addr[1],
+		    linfo.mac_addr[2], linfo.mac_addr[3],
+		    linfo.mac_addr[4], linfo.mac_addr[5],
+		    linfo.name, linfo.def_mtu);
+
+		free(linfo.name);
+
+		linfo.name = NULL;
+	}
+
+	if (count == 0)
+		printf("    None\n");
+
+	free(link_list);
+
+	return EOK;
+}
+
 static int sroute_list(void)
 {
@@ -404,4 +450,7 @@
 		if (rc != EOK)
 			return 1;
+		rc = link_list();
+		if (rc != EOK)
+			return 1;
 		return 0;
 	}
Index: uspace/lib/block/block.c
===================================================================
--- uspace/lib/block/block.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/block/block.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -37,5 +37,4 @@
  */
 
-#include "../../srv/vfs/vfs.h"
 #include <ipc/loc.h>
 #include <ipc/services.h>
Index: uspace/lib/block/block.h
===================================================================
--- uspace/lib/block/block.h	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/block/block.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -29,7 +29,7 @@
  */
 
-/** @addtogroup libblock 
+/** @addtogroup libblock
  * @{
- */ 
+ */
 /**
  * @file
@@ -41,8 +41,8 @@
 #include <stdint.h>
 #include <async.h>
-#include "../../srv/vfs/vfs.h"
 #include <fibril_synch.h>
 #include <adt/hash_table.h>
 #include <adt/list.h>
+#include <loc.h>
 
 /*
@@ -50,5 +50,5 @@
  */
 
-/** 
+/**
  * This macro is a symbolic value for situations where no special flags are
  * needed.
Index: uspace/lib/c/generic/inetcfg.c
===================================================================
--- uspace/lib/c/generic/inetcfg.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/c/generic/inetcfg.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -279,9 +279,10 @@
 	aid_t req = async_send_1(exch, INETCFG_LINK_GET, link_id, &answer);
 	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN, &dreply);
+	int rc = async_data_read_start(exch, &linfo->mac_addr, sizeof(addr48_t));
 	async_wait_for(dreq, &dretval);
 
 	async_exchange_end(exch);
 
-	if (dretval != EOK) {
+	if (dretval != EOK || rc != EOK) {
 		async_forget(req);
 		return dretval;
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -893,41 +893,28 @@
 }
 
-int statfs(const char *path, struct statfs *statfs)
-{
-	sysarg_t rc;
-	sysarg_t rc_orig;
+int statfs(const char *path, struct statfs *st)
+{
+	sysarg_t rc, rc_orig;
 	aid_t req;
 	size_t pa_size;
-	
+
 	char *pa = absolutize(path, &pa_size);
 	if (!pa)
 		return ENOMEM;
-	async_exch_t *exch = vfs_exchange_begin();
-	
+
+	async_exch_t *exch = vfs_exchange_begin();
+
 	req = async_send_0(exch, VFS_IN_STATFS, NULL);
 	rc = async_data_write_start(exch, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	rc = async_data_read_start(exch, (void *) statfs, sizeof(struct statfs));
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
+	if (rc != EOK)
+		goto exit;
+
+	rc = async_data_read_start(exch, (void *) st, sizeof(*st));
+
+exit:
 	vfs_exchange_end(exch);
 	free(pa);
-	async_wait_for(req, &rc);
-	return rc;
+	async_wait_for(req, &rc_orig);
+	return (int) (rc_orig != EOK ? rc_orig : rc);
 }
 
Index: uspace/lib/c/include/inet/inet.h
===================================================================
--- uspace/lib/c/include/inet/inet.h	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/c/include/inet/inet.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -39,24 +39,5 @@
 #include <ipc/loc.h>
 #include <sys/types.h>
-
-#define INET_TTL_MAX 255
-
-typedef struct {
-	/** Local IP link service ID (optional) */
-	service_id_t iplink;
-	inet_addr_t src;
-	inet_addr_t dest;
-	uint8_t tos;
-	void *data;
-	size_t size;
-} inet_dgram_t;
-
-typedef struct {
-	int (*recv)(inet_dgram_t *);
-} inet_ev_ops_t;
-
-typedef enum {
-	INET_DF = 1
-} inet_df_t;
+#include <types/inet.h>
 
 extern int inet_init(uint8_t, inet_ev_ops_t *);
Index: uspace/lib/c/include/inet/inetcfg.h
===================================================================
--- uspace/lib/c/include/inet/inetcfg.h	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/c/include/inet/inetcfg.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -38,32 +38,5 @@
 #include <inet/inet.h>
 #include <sys/types.h>
-
-/** Address object info */
-typedef struct {
-	/** Network address */
-	inet_naddr_t naddr;
-	/** Link service ID */
-	sysarg_t ilink;
-	/** Address object name */
-	char *name;
-} inet_addr_info_t;
-
-/** IP link info */
-typedef struct {
-	/** Link service name */
-	char *name;
-	/** Default MTU */
-	size_t def_mtu;
-} inet_link_info_t;
-
-/** Static route info */
-typedef struct {
-	/** Destination network address */
-	inet_naddr_t dest;
-	/** Router address */
-	inet_addr_t router;
-	/** Static route name */
-	char *name;
-} inet_sroute_info_t;
+#include <types/inetcfg.h>
 
 extern int inetcfg_init(void);
Index: uspace/lib/c/include/types/inet.h
===================================================================
--- uspace/lib/c/include/types/inet.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
+++ uspace/lib/c/include/types/inet.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012 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_H_
+#define LIBC_TYPES_INET_H_
+
+#include <inet/addr.h>
+#include <ipc/loc.h>
+#include <sys/types.h>
+
+#define INET_TTL_MAX 255
+
+typedef struct {
+	/** Local IP link service ID (optional) */
+	service_id_t iplink;
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint8_t tos;
+	void *data;
+	size_t size;
+} inet_dgram_t;
+
+typedef struct {
+	int (*recv)(inet_dgram_t *);
+} inet_ev_ops_t;
+
+typedef enum {
+	INET_DF = 1
+} inet_df_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/types/inetcfg.h
===================================================================
--- uspace/lib/c/include/types/inetcfg.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
+++ uspace/lib/c/include/types/inetcfg.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 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_INETCFG_H_
+#define LIBC_TYPES_INETCFG_H_
+
+#include <inet/inet.h>
+#include <sys/types.h>
+
+/** Address object info */
+typedef struct {
+	/** Network address */
+	inet_naddr_t naddr;
+	/** Link service ID */
+	sysarg_t ilink;
+	/** Address object name */
+	char *name;
+} inet_addr_info_t;
+
+/** IP link info */
+typedef struct {
+	/** Link service name */
+	char *name;
+	/** Default MTU */
+	size_t def_mtu;
+	/** Link layer address */
+	addr48_t mac_addr;
+} inet_link_info_t;
+
+/** Static route info */
+typedef struct {
+	/** Destination network address */
+	inet_naddr_t dest;
+	/** Router address */
+	inet_addr_t router;
+	/** Static route name */
+	char *name;
+} inet_sroute_info_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -39,4 +39,5 @@
 #include <errno.h>
 #include <malloc.h>
+#include <ipc/vfs.h>
 #include "libext4.h"
 
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/lib/fs/libfs.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -806,9 +806,9 @@
 	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
+
 	fs_node_t *fn;
 	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
-	
+
 	ipc_callid_t callid;
 	size_t size;
@@ -820,8 +820,8 @@
 		return;
 	}
-	
+
 	struct stat stat;
 	memset(&stat, 0, sizeof(struct stat));
-	
+
 	stat.fs_handle = fs_handle;
 	stat.service_id = service_id;
@@ -832,5 +832,5 @@
 	stat.size = ops->size_get(fn);
 	stat.service = ops->service_get(fn);
-	
+
 	ops->node_put(fn);
 
@@ -845,39 +845,39 @@
 	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
+
 	fs_node_t *fn;
 	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
-	
+
 	ipc_callid_t callid;
 	size_t size;
 	if ((!async_data_read_receive(&callid, &size)) ||
 	    (size != sizeof(struct statfs))) {
-		ops->node_put(fn);
-		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	struct statfs statfs;
-	memset(&statfs, 0, sizeof(struct statfs));
-
-	if (NULL != ops->size_block) {	
-		rc = ops->size_block(service_id, &statfs.f_bsize);
-		if (rc != EOK) goto error;
-	}
-
-	if (NULL != ops->total_block_count) {
-		rc = ops->total_block_count(service_id, &statfs.f_blocks);
-		if (rc != EOK) goto error;
-	}
-
-	if (NULL != ops->free_block_count) {
-		rc = ops->free_block_count(service_id, &statfs.f_bfree);
-		if (rc != EOK) goto error;
+		goto error;
+	}
+
+	struct statfs st;
+	memset(&st, 0, sizeof(struct statfs));
+
+	if (ops->size_block != NULL) {
+		rc = ops->size_block(service_id, &st.f_bsize);
+		if (rc != EOK)
+			goto error;
+	}
+
+	if (ops->total_block_count != NULL) {
+		rc = ops->total_block_count(service_id, &st.f_blocks);
+		if (rc != EOK)
+			goto error;
+	}
+
+	if (ops->free_block_count != NULL) {
+		rc = ops->free_block_count(service_id, &st.f_bfree);
+		if (rc != EOK)
+			goto error;
 	}
 
 	ops->node_put(fn);
-	async_data_read_finalize(callid, &statfs, sizeof(struct statfs));
+	async_data_read_finalize(callid, &st, sizeof(struct statfs));
 	async_answer_0(rid, EOK);
 	return;
Index: uspace/srv/net/dhcp/dhcp.c
===================================================================
--- uspace/srv/net/dhcp/dhcp.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/srv/net/dhcp/dhcp.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -53,5 +53,5 @@
 
 static int transport_fd = -1;
-static addr48_t mac_addr;
+static inet_link_info_t link_info;
 static uint8_t msgbuf[MAX_MSG_SIZE];
 
@@ -132,5 +132,5 @@
 	hdr->flags = flag_broadcast;
 
-	addr48(mac_addr, hdr->chaddr);
+	addr48(link_info.mac_addr, hdr->chaddr);
 	hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
 
@@ -178,5 +178,5 @@
 	hdr->flags = flag_broadcast;
 	hdr->ciaddr = host2uint32_t_be(offer->oaddr.addr);
-	addr48(mac_addr, hdr->chaddr);
+	addr48(link_info.mac_addr, hdr->chaddr);
 	hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
 
@@ -387,5 +387,5 @@
 		rc = dnsr_set_srvaddr(&offer->dns_server);
 		if (rc != EOK) {
-			printf("%s: Failed setting nameserver address (%d))\n",
+			printf("%s: Error setting nameserver address (%d))\n",
 			    NAME, rc);
 			return rc;
@@ -413,5 +413,5 @@
 	rc = inetcfg_init();
 	if (rc != EOK) {
-		printf("Failed contacting inet configuration service.\n");
+		printf("Error contacting inet configuration service.\n");
 		return 1;
 	}
@@ -419,15 +419,14 @@
 	rc = loc_service_get_id(argv[1], &iplink, 0);
 	if (rc != EOK) {
-		printf("Failed resolving service '%s'.\n", argv[1]);
-		return 1;
-	}
-
-	/* XXX Determine MAC address automatically */
-	mac_addr[0] = 0xaa;
-	mac_addr[1] = 0xde;
-	mac_addr[2] = 0xad;
-	mac_addr[3] = 0xbe;
-	mac_addr[4] = 0xef;
-	mac_addr[5] = 0xfe;
+		printf("Error resolving service '%s'.\n", argv[1]);
+		return 1;
+	}
+
+	/* Get link hardware address */
+	rc = inetcfg_link_get(iplink, &link_info);
+	if (rc != EOK) {
+		printf("Error getting properties for link '%s'.\n", argv[1]);
+		return 1;
+	}
 
 	laddr.sin_family = AF_INET;
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -493,4 +493,34 @@
 }
 
+/** Get IDs of all links. */
+int inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount)
+{
+	sysarg_t *id_list;
+	size_t count, i;
+
+	fibril_mutex_lock(&inet_discovery_lock);
+	count = list_count(&inet_link_list);
+
+	id_list = calloc(count, sizeof(sysarg_t));
+	if (id_list == NULL) {
+		fibril_mutex_unlock(&inet_discovery_lock);
+		return ENOMEM;
+	}
+
+	i = 0;
+	list_foreach(inet_link_list, link_list, inet_link_t, ilink) {
+		id_list[i++] = ilink->svc_id;
+		log_msg(LOG_DEFAULT, LVL_NOTE, "add link to list");
+	}
+
+	fibril_mutex_unlock(&inet_discovery_lock);
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "return %zu links", count);
+	*rid_list = id_list;
+	*rcount = count;
+
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/srv/net/inetsrv/inet_link.h
===================================================================
--- uspace/srv/net/inetsrv/inet_link.h	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/srv/net/inetsrv/inet_link.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -47,4 +47,5 @@
     uint8_t, uint8_t, int);
 extern inet_link_t *inet_link_get_by_id(sysarg_t);
+extern int inet_link_get_id_list(sysarg_t **, size_t *);
 
 #endif
Index: uspace/srv/net/inetsrv/inetcfg.c
===================================================================
--- uspace/srv/net/inetsrv/inetcfg.c	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/srv/net/inetsrv/inetcfg.c	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -44,4 +44,5 @@
 #include <str.h>
 #include <sys/types.h>
+#include <types/inetcfg.h>
 
 #include "addrobj.h"
@@ -151,5 +152,5 @@
 static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count)
 {
-	return ENOTSUP;
+	return inet_link_get_id_list(addrs, count);
 }
 
@@ -170,4 +171,10 @@
 	linfo->name = str_dup(ilink->svc_name);
 	linfo->def_mtu = ilink->def_mtu;
+	if (ilink->mac_valid) {
+		addr48(ilink->mac, linfo->mac_addr);
+	} else {
+		memset(linfo->mac_addr, 0, sizeof(linfo->mac_addr));
+	}
+
 	return EOK;
 }
@@ -411,4 +418,5 @@
 {
 	ipc_callid_t rcallid;
+	size_t count;
 	size_t max_size;
 	size_t act_size;
@@ -417,5 +425,5 @@
 	int rc;
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_link_list_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_addr_list_srv()");
 
 	if (!async_data_read_receive(&rcallid, &max_size)) {
@@ -425,5 +433,5 @@
 	}
 
-	rc = inetcfg_get_link_list(&id_buf, &act_size);
+	rc = inetcfg_get_link_list(&id_buf, &count);
 	if (rc != EOK) {
 		async_answer_0(rcallid, rc);
@@ -432,4 +440,5 @@
 	}
 
+	act_size = count * sizeof(sysarg_t);
 	size = min(act_size, max_size);
 
@@ -476,6 +485,8 @@
 static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call)
 {
-	ipc_callid_t rcallid;
-	size_t max_size;
+	ipc_callid_t name_callid;
+	ipc_callid_t laddr_callid;
+	size_t name_max_size;
+	size_t laddr_max_size;
 
 	sysarg_t link_id;
@@ -488,6 +499,12 @@
 	linfo.name = NULL;
 
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
+	if (!async_data_read_receive(&name_callid, &name_max_size)) {
+		async_answer_0(name_callid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	if (!async_data_read_receive(&laddr_callid, &laddr_max_size)) {
+		async_answer_0(name_callid, EREFUSED);
 		async_answer_0(callid, EREFUSED);
 		return;
@@ -496,11 +513,22 @@
 	rc = inetcfg_link_get(link_id, &linfo);
 	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sysarg_t retval = async_data_read_finalize(rcallid, linfo.name,
-	    min(max_size, str_size(linfo.name)));
+		async_answer_0(laddr_callid, rc);
+		async_answer_0(name_callid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(name_callid, linfo.name,
+	    min(name_max_size, str_size(linfo.name)));
+	if (retval != EOK) {
+		free(linfo.name);
+		async_answer_0(laddr_callid, retval);
+		async_answer_0(callid, retval);
+		return;
+	}
+
+	retval = async_data_read_finalize(laddr_callid, &linfo.mac_addr,
+	    min(laddr_max_size, sizeof(linfo.mac_addr)));
+
 	free(linfo.name);
 
Index: uspace/srv/net/inetsrv/inetsrv.h
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.h	(revision 772a172ffc7ed74c654c4b83dbba49c64d265379)
+++ uspace/srv/net/inetsrv/inetsrv.h	(revision f65d9cc6202c333ec08c2357aa4d0c99cec01b45)
@@ -44,4 +44,5 @@
 #include <ipc/loc.h>
 #include <sys/types.h>
+#include <types/inet.h>
 #include <async.h>
 
@@ -73,32 +74,4 @@
 } inetping6_client_t;
 
-/** Address object info */
-typedef struct {
-	/** Network address */
-	inet_naddr_t naddr;
-	/** Link service ID */
-	sysarg_t ilink;
-	/** Address object name */
-	char *name;
-} inet_addr_info_t;
-
-/** IP link info */
-typedef struct {
-	/** Link service name */
-	char *name;
-	/** Default MTU */
-	size_t def_mtu;
-} inet_link_info_t;
-
-/** Static route info */
-typedef struct {
-	/** Destination network address */
-	inet_naddr_t dest;
-	/** Router address */
-	inet_addr_t router;
-	/** Static route name */
-	char *name;
-} inet_sroute_info_t;
-
 typedef struct {
 	/** Source address */
@@ -125,13 +98,4 @@
 	size_t size;
 } inet_packet_t;
-
-typedef struct {
-	service_id_t iplink;
-	inet_addr_t src;
-	inet_addr_t dest;
-	uint8_t tos;
-	void *data;
-	size_t size;
-} inet_dgram_t;
 
 typedef struct {
