Index: uspace/app/inet/inet.c
===================================================================
--- uspace/app/inet/inet.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/app/inet/inet.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -370,7 +370,7 @@
 		table_printf(table, "%02x:%02x:%02x:%02x:%02x:%02x\t"
 		    "%s\t" "%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.mac_addr.b[0], linfo.mac_addr.b[1],
+		    linfo.mac_addr.b[2], linfo.mac_addr.b[3],
+		    linfo.mac_addr.b[4], linfo.mac_addr.b[5],
 		    linfo.name, linfo.def_mtu);
 
Index: uspace/lib/drv/generic/remote_ieee80211.c
===================================================================
--- uspace/lib/drv/generic/remote_ieee80211.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/drv/generic/remote_ieee80211.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -109,5 +109,5 @@
 			return -1;
 
-		if (mac_matches(mac, link_info.mac_addr))
+		if (mac_matches(mac, link_info.mac_addr.b))
 			return link_list[i];
 	}
@@ -229,5 +229,5 @@
 			return rc;
 
-		if (mac_matches(wifi_mac.address, link_info.mac_addr)) {
+		if (mac_matches(wifi_mac.address, link_info.mac_addr.b)) {
 			if (str_test_prefix(addr_info.name, "dhcp")) {
 				rc = inetcfg_addr_delete(addr_list[i]);
Index: uspace/lib/inet/include/inet/addr.h
===================================================================
--- uspace/lib/inet/include/inet/addr.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/inet/include/inet/addr.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,5 +40,11 @@
 
 typedef uint32_t addr32_t;
-typedef uint8_t addr48_t[6];
+
+#define ETH_ADDR_SIZE 6
+
+typedef struct {
+	uint8_t b[ETH_ADDR_SIZE];
+} addr48_t;
+
 typedef uint8_t addr128_t[16];
 
@@ -80,11 +86,11 @@
 extern const addr48_t addr48_broadcast;
 
-extern void addr48(const addr48_t, addr48_t);
+extern void addr48(const addr48_t *, addr48_t *);
 extern void addr128(const addr128_t, addr128_t);
 
-extern int addr48_compare(const addr48_t, const addr48_t);
+extern int addr48_compare(const addr48_t *, const addr48_t *);
 extern int addr128_compare(const addr128_t, const addr128_t);
 
-extern void addr48_solicited_node(const addr128_t, addr48_t);
+extern void addr48_solicited_node(const addr128_t, addr48_t *);
 
 extern void host2addr128_t_be(const addr128_t, addr128_t);
Index: uspace/lib/inet/include/inet/eth_addr.h
===================================================================
--- uspace/lib/inet/include/inet/eth_addr.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
+++ uspace/lib/inet/include/inet/eth_addr.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 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 inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef _LIBC_INET_ETH_ADDR_H_
+#define _LIBC_INET_ETH_ADDR_H_
+
+// XXX Move addr48 here
+#include <inet/addr.h>
+
+extern void mac48_encode(addr48_t *, void *);
+extern void mac48_decode(const void *, addr48_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/inet/include/inet/iplink.h
===================================================================
--- uspace/lib/inet/include/inet/iplink.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/inet/include/inet/iplink.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -79,5 +79,5 @@
 typedef struct iplink_ev_ops {
 	errno_t (*recv)(iplink_t *, iplink_recv_sdu_t *, ip_ver_t);
-	errno_t (*change_addr)(iplink_t *, addr48_t);
+	errno_t (*change_addr)(iplink_t *, addr48_t *);
 } iplink_ev_ops_t;
 
@@ -90,5 +90,5 @@
 extern errno_t iplink_get_mtu(iplink_t *, size_t *);
 extern errno_t iplink_get_mac48(iplink_t *, addr48_t *);
-extern errno_t iplink_set_mac48(iplink_t *, addr48_t);
+extern errno_t iplink_set_mac48(iplink_t *, addr48_t *);
 extern void *iplink_get_userptr(iplink_t *);
 
Index: uspace/lib/inet/meson.build
===================================================================
--- uspace/lib/inet/meson.build	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/inet/meson.build	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -32,4 +32,5 @@
 	'src/dnsr.c',
 	'src/endpoint.c',
+	'src/eth_addr.c',
 	'src/host.c',
 	'src/hostname.c',
Index: uspace/lib/inet/src/addr.c
===================================================================
--- uspace/lib/inet/src/addr.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/inet/src/addr.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * Copyright (c) 2013 Martin Decky
  * All rights reserved.
@@ -72,7 +72,7 @@
 };
 
-void addr48(const addr48_t src, addr48_t dst)
-{
-	memcpy(dst, src, 6);
+void addr48(const addr48_t *src, addr48_t *dst)
+{
+	memcpy(dst, src, sizeof(addr48_t));
 }
 
@@ -86,7 +86,7 @@
  * @return Non-zero if equal, zero if not equal.
  */
-int addr48_compare(const addr48_t a, const addr48_t b)
-{
-	return memcmp(a, b, 6) == 0;
+int addr48_compare(const addr48_t *a, const addr48_t *b)
+{
+	return memcmp(a->b, b->b, 6) == 0;
 }
 
@@ -106,8 +106,8 @@
  *
  */
-void addr48_solicited_node(const addr128_t ip, addr48_t mac)
-{
-	memcpy(mac, inet_addr48_solicited_node, 3);
-	memcpy(mac + 3, ip + 13, 3);
+void addr48_solicited_node(const addr128_t ip, addr48_t *mac)
+{
+	memcpy(&mac->b[0], &inet_addr48_solicited_node.b[0], 3);
+	memcpy(&mac->b[3], ip + 13, 3);
 }
 
Index: uspace/lib/inet/src/eth_addr.c
===================================================================
--- uspace/lib/inet/src/eth_addr.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
+++ uspace/lib/inet/src/eth_addr.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 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
+ * @brief
+ */
+
+#include <inet/eth_addr.h>
+#include <mem.h>
+
+void mac48_encode(addr48_t *addr, void *buf)
+{
+	uint8_t *bp = (uint8_t *)buf;
+
+	memcpy(bp, &addr->b[0], ETH_ADDR_SIZE);
+}
+
+void mac48_decode(const void *buf, addr48_t *addr)
+{
+	const uint8_t *bp = (uint8_t *)buf;
+
+	memcpy(&addr->b[0], bp, ETH_ADDR_SIZE);
+}
+
+/** @}
+ */
Index: uspace/lib/inet/src/iplink.c
===================================================================
--- uspace/lib/inet/src/iplink.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/lib/inet/src/iplink.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -175,5 +175,5 @@
 }
 
-errno_t iplink_set_mac48(iplink_t *iplink, addr48_t mac)
+errno_t iplink_set_mac48(iplink_t *iplink, addr48_t *mac)
 {
 	async_exch_t *exch = async_exchange_begin(iplink->sess);
@@ -274,5 +274,5 @@
 	}
 
-	rc = iplink->ev_ops->change_addr(iplink, *addr);
+	rc = iplink->ev_ops->change_addr(iplink, addr);
 	free(addr);
 	async_answer_0(icall, EOK);
Index: uspace/srv/net/dhcp/dhcp.c
===================================================================
--- uspace/srv/net/dhcp/dhcp.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/dhcp/dhcp.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -161,5 +161,6 @@
 	hdr->flags = flag_broadcast;
 
-	addr48(dlink->link_info.mac_addr, hdr->chaddr);
+	memcpy(dlink->link_info.mac_addr.b, hdr->chaddr,
+	    sizeof(dlink->link_info.mac_addr.b));
 	hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
 
@@ -185,5 +186,5 @@
 	hdr->flags = flag_broadcast;
 	hdr->ciaddr = host2uint32_t_be(offer->oaddr.addr);
-	addr48(dlink->link_info.mac_addr, hdr->chaddr);
+	memcpy(hdr->chaddr, dlink->link_info.mac_addr.b, 6);
 	hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
 
Index: uspace/srv/net/ethip/arp.c
===================================================================
--- uspace/srv/net/ethip/arp.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/arp.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -79,5 +79,5 @@
 
 	(void) atrans_add(packet.sender_proto_addr,
-	    packet.sender_hw_addr);
+	    &packet.sender_hw_addr);
 
 	if (packet.opcode == aop_request) {
@@ -85,7 +85,7 @@
 
 		reply.opcode = aop_reply;
-		addr48(nic->mac_addr, reply.sender_hw_addr);
+		addr48(&nic->mac_addr, &reply.sender_hw_addr);
 		reply.sender_proto_addr = laddr_v4;
-		addr48(packet.sender_hw_addr, reply.target_hw_addr);
+		addr48(&packet.sender_hw_addr, &reply.target_hw_addr);
 		reply.target_proto_addr = packet.sender_proto_addr;
 
@@ -95,9 +95,9 @@
 
 errno_t arp_translate(ethip_nic_t *nic, addr32_t src_addr, addr32_t ip_addr,
-    addr48_t mac_addr)
+    addr48_t *mac_addr)
 {
 	/* Broadcast address */
 	if (ip_addr == addr32_broadcast_all_hosts) {
-		addr48(addr48_broadcast, mac_addr);
+		addr48(&addr48_broadcast, mac_addr);
 		return EOK;
 	}
@@ -110,7 +110,7 @@
 
 	packet.opcode = aop_request;
-	addr48(nic->mac_addr, packet.sender_hw_addr);
+	addr48(&nic->mac_addr, &packet.sender_hw_addr);
 	packet.sender_proto_addr = src_addr;
-	addr48(addr48_broadcast, packet.target_hw_addr);
+	addr48(&addr48_broadcast, &packet.target_hw_addr);
 	packet.target_proto_addr = ip_addr;
 
@@ -138,6 +138,6 @@
 		return rc;
 
-	addr48(packet->target_hw_addr, frame.dest);
-	addr48(packet->sender_hw_addr, frame.src);
+	addr48(&packet->target_hw_addr, &frame.dest);
+	addr48(&packet->sender_hw_addr, &frame.src);
 	frame.etype_len = ETYPE_ARP;
 	frame.data = pdata;
Index: uspace/srv/net/ethip/arp.h
===================================================================
--- uspace/srv/net/ethip/arp.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/arp.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,5 +43,5 @@
 
 extern void arp_received(ethip_nic_t *, eth_frame_t *);
-extern errno_t arp_translate(ethip_nic_t *, addr32_t, addr32_t, addr48_t);
+extern errno_t arp_translate(ethip_nic_t *, addr32_t, addr32_t, addr48_t *);
 
 #endif
Index: uspace/srv/net/ethip/atrans.c
===================================================================
--- uspace/srv/net/ethip/atrans.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/atrans.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -59,5 +59,5 @@
 }
 
-errno_t atrans_add(addr32_t ip_addr, addr48_t mac_addr)
+errno_t atrans_add(addr32_t ip_addr, addr48_t *mac_addr)
 {
 	ethip_atrans_t *atrans;
@@ -69,5 +69,5 @@
 
 	atrans->ip_addr = ip_addr;
-	addr48(mac_addr, atrans->mac_addr);
+	addr48(mac_addr, &atrans->mac_addr);
 
 	fibril_mutex_lock(&atrans_list_lock);
@@ -103,5 +103,5 @@
 }
 
-static errno_t atrans_lookup_locked(addr32_t ip_addr, addr48_t mac_addr)
+static errno_t atrans_lookup_locked(addr32_t ip_addr, addr48_t *mac_addr)
 {
 	ethip_atrans_t *atrans = atrans_find(ip_addr);
@@ -109,9 +109,9 @@
 		return ENOENT;
 
-	addr48(atrans->mac_addr, mac_addr);
+	addr48(&atrans->mac_addr, mac_addr);
 	return EOK;
 }
 
-errno_t atrans_lookup(addr32_t ip_addr, addr48_t mac_addr)
+errno_t atrans_lookup(addr32_t ip_addr, addr48_t *mac_addr)
 {
 	errno_t rc;
@@ -135,5 +135,5 @@
 
 errno_t atrans_lookup_timeout(addr32_t ip_addr, usec_t timeout,
-    addr48_t mac_addr)
+    addr48_t *mac_addr)
 {
 	fibril_timer_t *t;
Index: uspace/srv/net/ethip/atrans.h
===================================================================
--- uspace/srv/net/ethip/atrans.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/atrans.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,8 +42,8 @@
 #include "ethip.h"
 
-extern errno_t atrans_add(addr32_t, addr48_t);
+extern errno_t atrans_add(addr32_t, addr48_t *);
 extern errno_t atrans_remove(addr32_t);
-extern errno_t atrans_lookup(addr32_t, addr48_t);
-extern errno_t atrans_lookup_timeout(addr32_t, usec_t, addr48_t);
+extern errno_t atrans_lookup(addr32_t, addr48_t *);
+extern errno_t atrans_lookup_timeout(addr32_t, usec_t, addr48_t *);
 
 #endif
Index: uspace/srv/net/ethip/ethip.c
===================================================================
--- uspace/srv/net/ethip/ethip.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/ethip.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -177,5 +177,5 @@
 	eth_frame_t frame;
 
-	errno_t rc = arp_translate(nic, sdu->src, sdu->dest, frame.dest);
+	errno_t rc = arp_translate(nic, sdu->src, sdu->dest, &frame.dest);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IPv4 address 0x%"
@@ -184,5 +184,5 @@
 	}
 
-	addr48(nic->mac_addr, frame.src);
+	addr48(&nic->mac_addr, &frame.src);
 	frame.etype_len = ETYPE_IP;
 	frame.data = sdu->data;
@@ -208,6 +208,6 @@
 	eth_frame_t frame;
 
-	addr48(sdu->dest, frame.dest);
-	addr48(nic->mac_addr, frame.src);
+	addr48(&sdu->dest, &frame.dest);
+	addr48(&nic->mac_addr, &frame.src);
 	frame.etype_len = ETYPE_IPV6;
 	frame.data = sdu->data;
@@ -281,5 +281,5 @@
 
 	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
-	addr48(nic->mac_addr, *mac);
+	addr48(&nic->mac_addr, mac);
 
 	return EOK;
@@ -291,5 +291,5 @@
 
 	ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
-	addr48(*mac, nic->mac_addr);
+	addr48(mac, &nic->mac_addr);
 
 	return EOK;
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -193,5 +193,5 @@
 	}
 
-	addr48(nic_address.address, nic->mac_addr);
+	mac48_decode(nic_address.address, &nic->mac_addr);
 
 	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
@@ -400,5 +400,5 @@
 
 		addr48_t mac;
-		addr48_solicited_node(v6, mac);
+		addr48_solicited_node(v6, &mac);
 
 		/* Avoid duplicate addresses in the list */
@@ -407,5 +407,7 @@
 
 		for (size_t j = 0; j < i; j++) {
-			if (addr48_compare(mac_list[j].address, mac)) {
+			addr48_t mac_entry;
+			mac48_decode(mac_list[j].address, &mac_entry);
+			if (addr48_compare(&mac_entry, &mac)) {
 				found = true;
 				break;
@@ -414,8 +416,9 @@
 
 		if (!found) {
-			addr48(mac, mac_list[i].address);
+			mac48_encode(&mac, mac_list[i].address);
 			i++;
-		} else
+		} else {
 			count--;
+		}
 	}
 
Index: uspace/srv/net/ethip/pdu.c
===================================================================
--- uspace/srv/net/ethip/pdu.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/pdu.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -60,6 +60,6 @@
 
 	hdr = (eth_header_t *)data;
-	addr48(frame->src, hdr->src);
-	addr48(frame->dest, hdr->dest);
+	mac48_encode(&frame->src, hdr->src);
+	mac48_encode(&frame->dest, hdr->dest);
 	hdr->etype_len = host2uint16_t_be(frame->etype_len);
 
@@ -93,6 +93,6 @@
 		return ENOMEM;
 
-	addr48(hdr->src, frame->src);
-	addr48(hdr->dest, frame->dest);
+	mac48_decode(hdr->src, &frame->src);
+	mac48_decode(hdr->dest, &frame->dest);
 	frame->etype_len = uint16_t_be2host(hdr->etype_len);
 
@@ -140,8 +140,8 @@
 	pfmt->proto_addr_size = IPV4_ADDR_SIZE;
 	pfmt->opcode = host2uint16_t_be(fopcode);
-	addr48(packet->sender_hw_addr, pfmt->sender_hw_addr);
+	mac48_encode(&packet->sender_hw_addr, pfmt->sender_hw_addr);
 	pfmt->sender_proto_addr =
 	    host2uint32_t_be(packet->sender_proto_addr);
-	addr48(packet->target_hw_addr, pfmt->target_hw_addr);
+	mac48_encode(&packet->target_hw_addr, pfmt->target_hw_addr);
 	pfmt->target_proto_addr =
 	    host2uint32_t_be(packet->target_proto_addr);
@@ -203,8 +203,8 @@
 	}
 
-	addr48(pfmt->sender_hw_addr, packet->sender_hw_addr);
+	mac48_decode(pfmt->sender_hw_addr, &packet->sender_hw_addr);
 	packet->sender_proto_addr =
 	    uint32_t_be2host(pfmt->sender_proto_addr);
-	addr48(pfmt->target_hw_addr, packet->target_hw_addr);
+	mac48_decode(pfmt->target_hw_addr, &packet->target_hw_addr);
 	packet->target_proto_addr =
 	    uint32_t_be2host(pfmt->target_proto_addr);
Index: uspace/srv/net/ethip/pdu.h
===================================================================
--- uspace/srv/net/ethip/pdu.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/pdu.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,4 +44,6 @@
 extern errno_t arp_pdu_encode(arp_eth_packet_t *, void **, size_t *);
 extern errno_t arp_pdu_decode(void *, size_t, arp_eth_packet_t *);
+extern void mac48_encode(addr48_t *, void *);
+extern void mac48_decode(void *, addr48_t *);
 
 #endif
Index: uspace/srv/net/ethip/std.h
===================================================================
--- uspace/srv/net/ethip/std.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/ethip/std.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,5 +39,4 @@
 
 #include <stdint.h>
-#include <inet/addr.h>
 
 #define ETH_ADDR_SIZE       6
@@ -48,7 +47,7 @@
 typedef struct {
 	/** Destination Address */
-	addr48_t dest;
+	uint8_t dest[ETH_ADDR_SIZE];
 	/** Source Address */
-	addr48_t src;
+	uint8_t src[ETH_ADDR_SIZE];
 	/** Ethertype or Length */
 	uint16_t etype_len;
@@ -68,11 +67,11 @@
 	uint16_t opcode;
 	/** Sender hardware address */
-	addr48_t sender_hw_addr;
+	uint8_t sender_hw_addr[ETH_ADDR_SIZE];
 	/** Sender protocol address */
-	addr32_t sender_proto_addr;
+	uint32_t sender_proto_addr;
 	/** Target hardware address */
-	addr48_t target_hw_addr;
+	uint8_t target_hw_addr[ETH_ADDR_SIZE];
 	/** Target protocol address */
-	addr32_t target_proto_addr;
+	uint32_t target_proto_addr;
 } __attribute__((packed)) arp_eth_packet_fmt_t;
 
Index: uspace/srv/net/inetsrv/addrobj.c
===================================================================
--- uspace/srv/net/inetsrv/addrobj.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/addrobj.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -239,9 +239,9 @@
 		 * Translate local destination IPv6 address.
 		 */
-		rc = ndp_translate(lsrc_v6, ldest_v6, ldest_mac, addr->ilink);
+		rc = ndp_translate(lsrc_v6, ldest_v6, &ldest_mac, addr->ilink);
 		if (rc != EOK)
 			return rc;
 
-		return inet_link_send_dgram6(addr->ilink, ldest_mac, dgram,
+		return inet_link_send_dgram6(addr->ilink, &ldest_mac, dgram,
 		    proto, ttl, df);
 	default:
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -56,5 +56,5 @@
 
 static errno_t inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, ip_ver_t);
-static errno_t inet_iplink_change_addr(iplink_t *, addr48_t);
+static errno_t inet_iplink_change_addr(iplink_t *, addr48_t *);
 static inet_link_t *inet_link_get_by_id_locked(sysarg_t);
 
@@ -70,15 +70,15 @@
     { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0 };
 
-static void inet_link_local_node_ip(addr48_t mac_addr,
+static void inet_link_local_node_ip(addr48_t *mac_addr,
     addr128_t ip_addr)
 {
 	memcpy(ip_addr, link_local_node_ip, 16);
 
-	ip_addr[8] = mac_addr[0] ^ 0x02;
-	ip_addr[9] = mac_addr[1];
-	ip_addr[10] = mac_addr[2];
-	ip_addr[13] = mac_addr[3];
-	ip_addr[14] = mac_addr[4];
-	ip_addr[15] = mac_addr[5];
+	ip_addr[8] = mac_addr->b[0] ^ 0x02;
+	ip_addr[9] = mac_addr->b[1];
+	ip_addr[10] = mac_addr->b[2];
+	ip_addr[13] = mac_addr->b[3];
+	ip_addr[14] = mac_addr->b[4];
+	ip_addr[15] = mac_addr->b[5];
 }
 
@@ -121,9 +121,9 @@
 }
 
-static errno_t inet_iplink_change_addr(iplink_t *iplink, addr48_t mac)
+static errno_t inet_iplink_change_addr(iplink_t *iplink, addr48_t *mac)
 {
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_change_addr(): "
 	    "new addr=%02x:%02x:%02x:%02x:%02x:%02x",
-	    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	    mac->b[0], mac->b[1], mac->b[2], mac->b[3], mac->b[4], mac->b[5]);
 
 	list_foreach(inet_links, link_list, inet_link_t, ilink) {
@@ -261,5 +261,5 @@
 
 		addr128_t link_local;
-		inet_link_local_node_ip(ilink->mac, link_local);
+		inet_link_local_node_ip(&ilink->mac, link_local);
 
 		inet_naddr_set6(link_local, 64, &addr6->naddr);
@@ -387,5 +387,5 @@
  *
  */
-errno_t inet_link_send_dgram6(inet_link_t *ilink, addr48_t ldest,
+errno_t inet_link_send_dgram6(inet_link_t *ilink, addr48_t *ldest,
     inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
 {
@@ -401,5 +401,5 @@
 
 	iplink_sdu6_t sdu6;
-	addr48(ldest, sdu6.dest);
+	addr48(ldest, &sdu6.dest);
 
 	/*
Index: uspace/srv/net/inetsrv/inet_link.h
===================================================================
--- uspace/srv/net/inetsrv/inet_link.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/inet_link.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,5 +45,5 @@
 extern errno_t inet_link_send_dgram(inet_link_t *, addr32_t,
     addr32_t, inet_dgram_t *, uint8_t, uint8_t, int);
-extern errno_t inet_link_send_dgram6(inet_link_t *, addr48_t, inet_dgram_t *,
+extern errno_t inet_link_send_dgram6(inet_link_t *, addr48_t *, inet_dgram_t *,
     uint8_t, uint8_t, int);
 extern inet_link_t *inet_link_get_by_id(sysarg_t);
Index: uspace/srv/net/inetsrv/inetcfg.c
===================================================================
--- uspace/srv/net/inetsrv/inetcfg.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/inetcfg.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2013 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -177,7 +177,7 @@
 	linfo->def_mtu = ilink->def_mtu;
 	if (ilink->mac_valid) {
-		addr48(ilink->mac, linfo->mac_addr);
+		addr48(&ilink->mac, &linfo->mac_addr);
 	} else {
-		memset(linfo->mac_addr, 0, sizeof(linfo->mac_addr));
+		memset(&linfo->mac_addr, 0, sizeof(linfo->mac_addr));
 	}
 
Index: uspace/srv/net/inetsrv/ndp.c
===================================================================
--- uspace/srv/net/inetsrv/ndp.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/ndp.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -69,5 +69,5 @@
 	ndp_pdu_encode(packet, &dgram);
 
-	inet_link_send_dgram6(link, packet->target_hw_addr, &dgram,
+	inet_link_send_dgram6(link, &packet->target_hw_addr, &dgram,
 	    IP_PROTO_ICMPV6, INET6_HOP_LIMIT_MAX, 0);
 
@@ -108,5 +108,5 @@
 		if (laddr != NULL) {
 			rc = ntrans_add(packet.sender_proto_addr,
-			    packet.sender_hw_addr);
+			    &packet.sender_hw_addr);
 			if (rc != EOK)
 				return rc;
@@ -115,7 +115,7 @@
 
 			reply.opcode = ICMPV6_NEIGHBOUR_ADVERTISEMENT;
-			addr48(laddr->ilink->mac, reply.sender_hw_addr);
+			addr48(&laddr->ilink->mac, &reply.sender_hw_addr);
 			addr128(packet.target_proto_addr, reply.sender_proto_addr);
-			addr48(packet.sender_hw_addr, reply.target_hw_addr);
+			addr48(&packet.sender_hw_addr, &reply.target_hw_addr);
 			addr128(packet.sender_proto_addr, reply.target_proto_addr);
 
@@ -128,5 +128,5 @@
 		if (laddr != NULL)
 			return ntrans_add(packet.sender_proto_addr,
-			    packet.sender_hw_addr);
+			    &packet.sender_hw_addr);
 
 		break;
@@ -151,5 +151,5 @@
  *
  */
-errno_t ndp_translate(addr128_t src_addr, addr128_t ip_addr, addr48_t mac_addr,
+errno_t ndp_translate(addr128_t src_addr, addr128_t ip_addr, addr48_t *mac_addr,
     inet_link_t *ilink)
 {
@@ -167,8 +167,8 @@
 
 	packet.opcode = ICMPV6_NEIGHBOUR_SOLICITATION;
-	addr48(ilink->mac, packet.sender_hw_addr);
+	addr48(&ilink->mac, &packet.sender_hw_addr);
 	addr128(src_addr, packet.sender_proto_addr);
 	addr128(ip_addr, packet.solicited_ip);
-	addr48_solicited_node(ip_addr, packet.target_hw_addr);
+	addr48_solicited_node(ip_addr, &packet.target_hw_addr);
 	ndp_solicited_node_ip(ip_addr, packet.target_proto_addr);
 
Index: uspace/srv/net/inetsrv/ndp.h
===================================================================
--- uspace/srv/net/inetsrv/ndp.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/ndp.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -64,5 +64,5 @@
 
 extern errno_t ndp_received(inet_dgram_t *);
-extern errno_t ndp_translate(addr128_t, addr128_t, addr48_t, inet_link_t *);
+extern errno_t ndp_translate(addr128_t, addr128_t, addr48_t *, inet_link_t *);
 
 #endif
Index: uspace/srv/net/inetsrv/ntrans.c
===================================================================
--- uspace/srv/net/inetsrv/ntrans.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/ntrans.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -73,5 +73,5 @@
  *
  */
-errno_t ntrans_add(addr128_t ip_addr, addr48_t mac_addr)
+errno_t ntrans_add(addr128_t ip_addr, addr48_t *mac_addr)
 {
 	inet_ntrans_t *ntrans;
@@ -83,5 +83,5 @@
 
 	addr128(ip_addr, ntrans->ip_addr);
-	addr48(mac_addr, ntrans->mac_addr);
+	addr48(mac_addr, &ntrans->mac_addr);
 
 	fibril_mutex_lock(&ntrans_list_lock);
@@ -134,5 +134,5 @@
  *
  */
-errno_t ntrans_lookup(addr128_t ip_addr, addr48_t mac_addr)
+errno_t ntrans_lookup(addr128_t ip_addr, addr48_t *mac_addr)
 {
 	fibril_mutex_lock(&ntrans_list_lock);
@@ -144,5 +144,5 @@
 
 	fibril_mutex_unlock(&ntrans_list_lock);
-	addr48(ntrans->mac_addr, mac_addr);
+	addr48(&ntrans->mac_addr, mac_addr);
 	return EOK;
 }
Index: uspace/srv/net/inetsrv/ntrans.h
===================================================================
--- uspace/srv/net/inetsrv/ntrans.h	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/ntrans.h	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -48,7 +48,7 @@
 } inet_ntrans_t;
 
-extern errno_t ntrans_add(addr128_t, addr48_t);
+extern errno_t ntrans_add(addr128_t, addr48_t *);
 extern errno_t ntrans_remove(addr128_t);
-extern errno_t ntrans_lookup(addr128_t, addr48_t);
+extern errno_t ntrans_lookup(addr128_t, addr48_t *);
 extern errno_t ntrans_wait_timeout(usec_t);
 
Index: uspace/srv/net/inetsrv/pdu.c
===================================================================
--- uspace/srv/net/inetsrv/pdu.c	(revision 98a935ebd156845f2511fad291365f6649289e1f)
+++ uspace/srv/net/inetsrv/pdu.c	(revision f05edcb84588b46065563dbdd0d0e78b9b4fb2b6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,4 +40,5 @@
 #include <errno.h>
 #include <fibril_synch.h>
+#include <inet/eth_addr.h>
 #include <io/log.h>
 #include <macros.h>
@@ -504,5 +505,5 @@
 
 	message->length = 1;
-	addr48(ndp->sender_hw_addr, message->mac);
+	mac48_encode(&ndp->sender_hw_addr, message->mac);
 
 	icmpv6_phdr_t phdr;
@@ -552,5 +553,5 @@
 
 	addr128_t_be2host(message->target_address, ndp->target_proto_addr);
-	addr48(message->mac, ndp->sender_hw_addr);
+	mac48_decode(message->mac, &ndp->sender_hw_addr);
 
 	return EOK;
