diff --git a/Makefile.dep b/Makefile.dep
index 578f190882f5db3592ed9657b9d19adbdd091ba5..9d86d5abad67f84048a1dc88ca49d02804cb54f6 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -102,3 +102,9 @@ ifneq (,$(filter vtimer,$(USEMODULE)))
 		USEMODULE += timex
 	endif
 endif
+
+ifneq (,$(filter net_if,$(USEMODULE)))
+	ifeq (,$(filter transceiver,$(USEMODULE)))
+		USEMODULE += transceiver
+	endif
+endif
diff --git a/sys/Makefile b/sys/Makefile
index e6c9cfef07287cc843831870cb9b6961ccdb8731..0614547c705b8fecaa01359288aa310abf8eef16 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -42,6 +42,9 @@ endif
 ifneq (,$(filter vtimer,$(USEMODULE)))
     DIRS += vtimer
 endif
+ifneq (,$(filter net_if,$(USEMODULE)))
+    DIRS += net/link_layer/net_if
+endif
 ifneq (,$(filter destiny,$(USEMODULE)))
     DIRS += net/transport_layer/destiny
 endif
diff --git a/sys/auto_init/Makefile b/sys/auto_init/Makefile
index dc73b225e9b74e6d10730de15d9373c8b0556936..f5b62c8ad7ab2f7e6451048aba6d031d00b8f615 100644
--- a/sys/auto_init/Makefile
+++ b/sys/auto_init/Makefile
@@ -1,3 +1,7 @@
 MODULE = auto_init
 
+ifneq (,$(filter net_if,$(USEMODULE)))
+	INCLUDES += -I$(RIOTBASE)/sys/net/include/
+endif
+
 include $(RIOTBASE)/Makefile.base
diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c
index 8cf58b8dff59e641f3761668f3df30c12444e605..5652f3ce7ac462489fc4dc35f2c56160b8850875 100644
--- a/sys/auto_init/auto_init.c
+++ b/sys/auto_init/auto_init.c
@@ -55,6 +55,11 @@
 #include "destiny.h"
 #endif
 
+#ifdef MODULE_NET_IF
+#include "net_if.h"
+#include "transceiver.h"
+#endif
+
 #define ENABLE_DEBUG (0)
 #include "debug.h"
 
@@ -97,6 +102,40 @@ void auto_init(void)
     DEBUG("Auto init mci module.\n");
     MCI_initialize();
 #endif
+#ifdef MODULE_NET_IF
+    DEBUG("Auto init net_if module.\n");
+    transceiver_type_t transceivers = 0;
+#ifdef MODULE_AT86RF231
+    transceivers |= TRANSCEIVER_AT86RF231;
+#endif
+#ifdef MODULE_CC1020
+    transceivers |= TRANSCEIVER_CC1020;
+#endif
+#if MODULE_CC110X || MODULE_CC110X_NG
+    transceivers |= TRANSCEIVER_CC1100;
+#endif
+#ifdef MODULE_CC2420
+    transceivers |= TRANSCEIVER_CC2420;
+#endif
+#ifdef MODULE_MC1322X
+    transceivers |= TRANSCEIVER_MC1322X;
+#endif
+#ifdef MODULE_NATIVENET
+    transceivers |= TRANSCEIVER_NATIVE;
+#endif
+    net_if_init();
+
+    if (transceivers != 0) {
+        transceiver_init(transceivers);
+        transceiver_start();
+        int iface = net_if_init_interface(0, transceivers);
+
+        if (iface >= 0) {
+            DEBUG("Interface %d initialized\n", iface);
+        }
+    }
+
+#endif
 #ifdef MODULE_PROFILING
     extern void profiling_init(void);
     profiling_init();
diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h
index 132cc052f2bf47eed99152efa53a5e758fea0a7d..42af6b5dfaff2981b8af752dcd102fa4684eb578 100644
--- a/sys/net/include/ieee802154_frame.h
+++ b/sys/net/include/ieee802154_frame.h
@@ -38,6 +38,10 @@
 #define IEEE_802154_SHORT_ADDR_M        2
 #define IEEE_802154_LONG_ADDR_M         3
 
+#define IEEE_802154_SHORT_MCAST_ADDR    (0xffff)
+#define IEEE_802154_LONG_MCAST_ADDR     {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+                                          0xff, 0xff}}
+
 #define IEEE_802154_PAN_ID              0x1234
 
 typedef struct __attribute__((packed)) {
diff --git a/sys/net/include/net_help.h b/sys/net/include/net_help.h
index 6dd566efa1416d74fc315cdc2475cffac7890fac..03d890b711b33169d49f90a3a06970c472ef8ccd 100644
--- a/sys/net/include/net_help.h
+++ b/sys/net/include/net_help.h
@@ -21,8 +21,17 @@
                   (((uint32_t) (a) & 0x00ff0000) >> 8)  | \
                   (((uint32_t) (a) & 0x0000ff00) << 8)  | \
                   (((uint32_t) (a) & 0x000000ff) << 24))
+#define HTONLL(a) ((((uint64_t) (a) & 0xff00000000000000) >> 56) | \
+                   (((uint64_t) (a) & 0x00ff000000000000) >> 40)  | \
+                   (((uint64_t) (a) & 0x0000ff0000000000) >> 24) | \
+                   (((uint64_t) (a) & 0x000000ff00000000) >> 8)  | \
+                   (((uint64_t) (a) & 0x00000000ff000000) << 8)  | \
+                   (((uint64_t) (a) & 0x0000000000ff0000) << 24)  | \
+                   (((uint64_t) (a) & 0x000000000000ff00) << 40)  | \
+                   (((uint64_t) (a) & 0x00000000000000ff) << 56))
 #define NTOHS HTONS
 #define NTOHL HTONL
+#define NTOHLL HTONLL
 
 #define CMP_IPV6_ADDR(a, b) (memcmp(a, b, 16))
 
diff --git a/sys/net/include/net_if.h b/sys/net/include/net_if.h
new file mode 100644
index 0000000000000000000000000000000000000000..561788f0625e06657b2139ced68db56a10c30173
--- /dev/null
+++ b/sys/net/include/net_if.h
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2013  Freie Universität Berlin.
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @defgroup    net_if Network interfaces
+ * @brief       Abstraction layer between transceiver module and L3 protocol
+ *              implementations.
+ * @ingroup     net
+ *
+ * @{
+ *
+ * @file        net_if.h
+ * @brief       Types and functions for network interfaces
+ * @author      Freie Universität Berlin
+ * @author      Martin Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef _NET_IF_H
+#define _NET_IF_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "mutex.h"
+#include "transceiver.h"
+
+/**
+ * @brief   type to specify types of upper layer addresses
+ */
+typedef uint8_t net_if_l3p_t;
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Use raw packets with
+ *          static addresses in upper layer.
+ */
+#define NET_IF_L3P_RAW          (0x00)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Use unicast IPv6
+ *          address in upper layer, addr_len must be 128.
+ */
+#define NET_IF_L3P_IPV6_UNICAST (0x01)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Use multicast IPv6
+ *          address in upper layer, addr_len must be 128.
+ */
+#define NET_IF_L3P_IPV6_MULTICAST (0x02)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Use anycast IPv6
+ *          address in upper layer, addr_len must be 128.
+ */
+#define NET_IF_L3P_IPV6_ANYCAST (0x04)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Use IPv6 prefix in
+ *          upper layer, addr_len <= 128 becomes prefix length.
+ */
+#define NET_IF_L3P_IPV6_PREFIX  (0x08)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Convenience macro
+ *          combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST, and
+ *          NET_IF_L3P_IPV6_MULTICAST for comparisons
+ */
+#define NET_IF_L3P_IPV6_ADDR    (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \
+                                | NET_IF_L3P_IPV6_MULTICAST)
+
+/**
+ * @brief   Interface protocols (for net_if_t.protocols): Convenience macro
+ *          combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST,
+ *          NET_IF_L3P_IPV6_MULTICAST, and NET_IF_L3P_IPV6_PREFIX for
+ *          comparisons
+ */
+#define NET_IF_L3P_IPV6         (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \
+                                | NET_IF_L3P_IPV6_MULTICAST | NET_IF_L3P_IPV6_PREFIX)
+
+/**
+ * @brief   Interface protocols: Return value of net_if_get_l3p_types() on
+ *          error.
+ */
+#define NET_IF_L3P_FAILURE      (0x80)
+
+#ifndef NET_IF_MAX
+/**
+ * @brief   Maximum number of interfaces. Redefinable via compiler flag.
+ */
+#define NET_IF_MAX      (1)
+#endif
+
+/**
+ * @brief Data type to represent an EUI-64.
+ */
+typedef union __attribute__((packed)) {
+    uint8_t uint8[8];   ///< split into 8 8-bit words.
+    uint16_t uint16[4]; ///< split into 4 16-bit words.
+    uint32_t uint32[2]; ///< split into 2 32-bit words.
+    uint64_t uint64;    ///< as one 64-bit word.
+} net_if_eui64_t;
+
+/**
+ * @brief   list type for upper layer address of an interface.
+ *
+ * @details The interpretation of the address data is left to the upper layer
+ *          implementations.
+ */
+typedef struct __attribute__((packed)) net_if_addr_t {
+    /**
+     * @brief The next address on the interface. Initialise with NULL
+     */
+    struct net_if_addr_t *addr_next;
+
+    /**
+     * @brief The next address on the interface. Initialise with NULL
+     */
+    struct net_if_addr_t *addr_prev;
+
+    /**
+     * @brief Flags to define upper layer protocols this address applies to
+     */
+    net_if_l3p_t addr_protocol;
+    void *addr_data;                    ///< The actual upper layer address
+    uint8_t addr_len;                   ///< Length of the upper layer address in bit.
+} net_if_addr_t;
+
+typedef uint8_t net_if_trans_addr_m_t;
+
+/**
+ * @brief   Interface type.
+ */
+typedef struct __attribute__((packed)) {
+    uint8_t initialized;                ///< Detemines if interface is initialized
+    uint8_t protocols;                  ///< Interface L3 protocols
+    transceiver_type_t transceivers;    ///< Transceivers to use with this interface
+    net_if_trans_addr_m_t trans_src_addr_m; ///< Transceiver address mode
+    mutex_t address_buffer_mutex;       ///< Mutex for address buffer operations
+    net_if_addr_t *addresses;           ///< Adresses
+    uint8_t l3p_data[9];                ///< generic L3 data
+} net_if_t;
+
+#define NET_IF_TRANS_ADDR_M_SHORT  2    ///< Transceiver address mode for short addresses
+#define NET_IF_TRANS_ADDR_M_LONG   3    ///< Transceiver address mode for long addresses
+
+/**
+ * All registered interfaces.
+ */
+extern net_if_t interfaces[NET_IF_MAX];
+
+/**
+ * @brief   Initializes the module.
+ */
+void net_if_init(void);
+
+/**
+ * @brief   Inititializes a new interface
+ *
+ * @pre     *transceivers* may not be zero.
+ *
+ * @param[in] protocols     The upper layer protocols to use on this interface.
+ * @param[in] transceivers  The transceivers this interface uses.
+ *
+ * @return  The new interface's ID on success, -1 on failure.
+ */
+int net_if_init_interface(net_if_l3p_t protocols,
+                          transceiver_type_t transceivers);
+
+/**
+ * @brief   Get interface.
+ *
+ * @param[in] if_id The interface's ID
+ *
+ * @return  The interface identified by *if_id* or NULL on failure.
+ */
+static inline net_if_t *net_if_get_interface(int if_id)
+{
+    if (if_id < NET_IF_MAX && interfaces[if_id].initialized) {
+        return &interfaces[if_id];
+    }
+    else {
+        return NULL;
+    }
+}
+
+
+/**
+ * @brief   Iterates over all intitialized interfaces
+ *
+ * @param[in] start  Return value of last iteration step. -1 to start iteration.
+ *
+ * @return  ID of an initialized interface. -1 if end of interface list is
+ *          reached.
+ */
+int net_if_iter_interfaces(int start);
+
+/**
+ * @brief   Sets the source address mode for the interface
+ *
+ * @param[in] if_id Interface to set source address mode for.
+ * @param[in] mode  The mode to set to.
+ *
+ * @return  1 on success, 0 on error
+ */
+static inline int net_if_set_src_address_mode(int if_id,
+        net_if_trans_addr_m_t mode)
+{
+    if (!interfaces[if_id].initialized) {
+        return 0;
+    }
+
+    interfaces[if_id].trans_src_addr_m = mode;
+    return 1;
+}
+
+/**
+ * @brief   Gets the source address mode for the interface
+ *
+ * @param[in] if_id Interface to get source address mode from.
+ *
+ * @return  The interfaces address mode, 0 on error
+ */
+static inline net_if_trans_addr_m_t net_if_get_src_address_mode(int if_id)
+{
+    if (!interfaces[if_id].initialized) {
+        return 0;
+    }
+
+    return interfaces[if_id].trans_src_addr_m;
+}
+
+/**
+ * @brief   Adds new address to interface
+ *
+ * @pre *addr* is not NULL, *addr->addr_data* is not NULL
+ *
+ * @param[in] if_id     The interface's ID
+ * @param[in] addr      The address to add
+ *
+ * @return  1 on success, 0 on failure.
+ */
+int net_if_add_address(int if_id, net_if_addr_t *addr);
+
+/**
+ * @brief   Removes first occurance of address from interface
+ *
+ * @pre *addr* is not NULL, *addr->addr_data* is not NULL
+ *
+ * @param[in] if_id     The interface's ID
+ * @param[in] addr      The address to remove
+ *
+ * @return  1 on success (and if given address is not registered to this
+ *          interface), 0 on failure
+ */
+int net_if_del_address(int if_id, net_if_addr_t *addr);
+
+/**
+ * @brief   Iterates over registered addresses of an interface.
+ *
+ * @param[in] if_id     The interface's ID
+ * @param[in,out] addr  The previous address as in or the next address as out.
+ *                      If *addr* points to NULL it will be set to the
+ *                      first address assigned to *if_id*, if *addr* points to
+ *                      NULL as out, the last address assigned to *if_id* was
+ *                      given as *addr* previously (and the address list was
+ *                      completely iterated).
+ *
+ * @return  The pointer *addr* refers to after call of this function or NULL on
+ *          error
+ */
+net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr);
+
+/**
+ * @brief   Get the upper layer protocol types assigned to the interface *if_id*
+ *
+ * @param[in] if_id The interface's ID
+ * @return  The upper layer protocol types assigned to the interface *if_id* on
+ *          success, NET_IF_L3P_FAILURE on failure.
+ */
+net_if_l3p_t net_if_get_l3p_types(int if_id);
+
+/**
+ * @brief   Add an upper layer protocol types to the interface *if_id*
+ *
+ * @param[in] if_id     The interface's ID
+ * @param[in] protocols The upper layer protocol types to assign to the
+ *                      interface *if_id*
+ * @return  1 on success, 0 on failure.
+ */
+int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols);
+
+/**
+ * @brief   Remove upper layer protocol types and all addresses of this scope
+ *          from the interface *if_id*
+ *
+ * @param[in] if_id     The interface's ID
+ * @param[in] protocols The upper layer protocol types to be removed from the
+ *                      interface *if_id*
+ * @return  1 on success, 0 on failure.
+ */
+int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols);
+
+/**
+ * @brief   Sends a packet to a short address over the interface.
+ *
+ * @pre     Transceivers has to be initialized and transceiver thread has
+ *          to be started.
+ *
+ * @param[in] if_id         The interface's ID.
+ * @param[in] target        The target's short transceiver address.
+ * @param[in] packet_data   The packet to send
+ * @param[in] packet_len    The length of the packet's data in byte, negative
+ *                          number on error.
+ *
+ * @return The number of bytes send on success, negative value on failure
+ */
+int net_if_send_packet(int if_id, uint16_t target, const void *packet_data,
+                       size_t packet_len);
+
+/**
+ * @brief   Sends a packet to a long address over the interface. If transceiver
+ *          only supports smaller addresses the least significant bit of the
+ *          address will be taken.
+ *
+ * @pre     Transceivers has to be initialized and transceiver thread has
+ *          to be started.
+ *
+ * @param[in] if_id         The interface's ID.
+ * @param[in] target        The target's long transceiver address.
+ * @param[in] packet_data   The packet to send
+ * @param[in] packet_len    The length of the packet's data in byte, negative
+ *                          number on error.
+ *
+ * @return The number of bytes send on success, negative value on failure
+ */
+int net_if_send_packet_long(int if_id, net_if_eui64_t *target,
+                            const void *packet_data, size_t packet_len);
+
+/**
+ * @brief   Sends a packet over all initialized interfaces.
+ *
+ * @pre     Transceivers has to be initialized and transceiver thread has
+ *          to be started.
+ *
+ * @param[in] preferred_dest_mode   The preferred transceiver address mode for
+ *                                  the destination broadcast address. Choose
+ *                                  NET_IF_TRANS_ADDR_M_SHORT if you are not
+ *                                  sure
+ * @param[in] packet_data           The packet to send
+ * @param[in] packet_len            The length of the packet's data in byte,
+ *                                  negative number on error.
+ *
+ * @return The number of bytes send on success, negative value on failure
+ */
+int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode,
+                                 const void *payload, size_t payload_len);
+
+/**
+ * @brief register a thread for events an interface's transceiver
+ * @details This function just wraps transceiver_register().
+ *
+ * @pre     Transceivers has to be initialized and transceiver thread has
+ *          to be started.
+ *
+ * @param[in] if_id     The transceiver's interface to register for
+ * @param[in] pid       The pid of the thread to register
+ *
+ * @return              1 on success, 0 otherwise
+ */
+int net_if_register(int if_id, int pid);
+
+/**
+ * Returns the EUI-64 of the transeivers attached to this interface. This can
+ * be get by the actual EUI-64 if the transceiver has one or a generated one
+ * based of the hardware address
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4944#section-6">
+ *          RFC 4944, section 5
+ *      </a>
+ * @see <a href="http://tools.ietf.org/search/rfc6282#section-3.2.2">
+ *          RFC 6282, section 3.2.2
+ *      </a>
+ *
+ * @param[out] eui64            The EUI-64 to fill
+ * @param[in]  if_id            The interface's ID
+ * @param[in]  force_generation Force generation from a short address if the
+ *                              hardware supports it, even if the hardware
+ *                              supplies an EUI-64
+ *
+ * @return  1 on success, 0 on failure
+ */
+int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation);
+
+/**
+ * @brief   Parses a string to an EUI-64.
+ * @detail  The parsing will be back to front, every non-hexadecimal character
+ *          and every hexadecimal character beyond the count of 8 will be
+ *          ignored
+ *
+ * @param[out] eui64        The generated binary EUI-64.
+ * @param[in]  eui64_str    A hexadecimal number in string representation.
+ */
+void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str);
+
+/**
+ * Returns the address of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ *
+ * @return  The transceiver's hardware address on success, 0 on failure
+ */
+uint16_t net_if_get_hardware_address(int if_id);
+
+/**
+ * Returns the EUI-64 of the transeivers attached to this interface. This can
+ * be get by the actual EUI-64 if the transceiver has one or a generated one
+ * based of the hardware address
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id            The interface's ID
+ * @param[in] eui64             The new EUI-64
+ *
+ * @return  1 on success, 0 on failure
+ */
+int net_if_set_eui64(int if_id, net_if_eui64_t *eui64);
+
+/**
+ * Sets the address of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ * @param[in]  addr     The new hardware address
+ *
+ * @return  the new hardware address on success, 0 on failure.
+ */
+uint16_t net_if_set_hardware_address(int if_id, uint16_t addr);
+
+/**
+ * Returns the channel of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ *
+ * @return  The transceiver's frequency channel on success, -1 on failure.
+ */
+int32_t net_if_get_channel(int if_id);
+
+/**
+ * Sets the channel of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ * @param[in]  channel  The new frequency channel
+ *
+ * @return  the new channel on success, -1 on failure.
+ */
+int32_t net_if_set_channel(int if_id, uint16_t channel);
+
+/**
+ * Returns the PAN ID of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ *
+ * @return  The transceiver's PAN ID on success, -1 on failure
+ */
+int32_t net_if_get_pan_id(int if_id);
+
+/**
+ * Sets the PAN ID of the transceiver associated with the given interface.
+ *
+ * @pre     Transceivers of this interface has to be initialized and
+ *          transceiver thread has to be started.
+ *
+ * @param[in]  if_id    The interface's ID
+ * @param[in]  pan_id   The new frequency channel
+ *
+ * @return  the PAN ID on success, -1 on failure.
+ */
+int32_t net_if_set_pan_id(int if_id, uint16_t pan_id);
+
+/**
+ * @}
+ */
+#endif /* _NET_IF_H */
diff --git a/sys/net/link_layer/net_if/Makefile b/sys/net/link_layer/net_if/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..81bfe881437e5f68d9b07aa8132fd5d2c4855c93
--- /dev/null
+++ b/sys/net/link_layer/net_if/Makefile
@@ -0,0 +1,5 @@
+MODULE:=$(shell basename $(CURDIR))
+INCLUDES += -I$(RIOTBASE)/drivers/include \
+			-I$(RIOTBASE)/drivers/cc110x_ng/include \
+			-I$(RIOTBASE)/sys/net/include
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/net/link_layer/net_if/net_if.c b/sys/net/link_layer/net_if/net_if.c
new file mode 100644
index 0000000000000000000000000000000000000000..4ded2494a5e91bf836f86bec9c9da1c0c9eee696
--- /dev/null
+++ b/sys/net/link_layer/net_if/net_if.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2013  Freie Universität Berlin.
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup net_if
+ * @{
+ * @file    net_if.c
+ * @author  Martin Lenders <mlenders@inf.fu-berlin.de>
+ */
+#include <string.h>
+
+#include "clist.h"
+#include "ieee802154_frame.h"
+#include "msg.h"
+#include "mutex.h"
+#include "net_help.h"
+#include "transceiver.h"
+
+#include "net_if.h"
+
+#define ENABLE_DEBUG    (0)
+#if ENABLE_DEBUG
+#define DEBUG_ENABLED
+#endif
+#include "debug.h"
+
+net_if_t interfaces[NET_IF_MAX];
+
+#ifdef DEBUG_ENABLED
+void print_addr_hex(net_if_addr_t *addr)
+{
+    int i;
+    DEBUG("0x");
+
+    for (i = 0; i < addr->addr_len; i++) {
+        DEBUG("%02x", ((char *)addr->addr_data)[i]);
+    }
+
+    DEBUG("\n");
+}
+#endif
+
+uint8_t net_if_hex_to_dec(char c)
+{
+    if (c >= '0' && c <= '9') {
+        return (uint8_t)(c - '0');
+    }
+    else if (c >= 'A' && c <= 'F') {
+        return (uint8_t)(c - 55);
+    }
+    else if (c >= 'a' && c <= 'f') {
+        return (uint8_t)(c - 87);
+    }
+    else {
+        return 0xff;
+    }
+}
+
+void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str)
+{
+    int i;
+    const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1];
+    eui64->uint64 = 0;
+
+    for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) {
+        uint8_t digit;
+
+        while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) {
+            if (--eui64_rev < eui64_str) {
+                return;
+            }
+        }
+
+        eui64->uint8[i] = digit;
+        eui64_rev--;
+
+        while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) {
+            if (--eui64_rev < eui64_str) {
+                return;
+            }
+        }
+
+        eui64->uint8[i] |= digit << 4;
+        eui64_rev--;
+    }
+}
+
+void net_if_init(void)
+{
+    memset(&interfaces, 0, sizeof(net_if_t) * NET_IF_MAX);
+}
+
+int net_if_init_interface(uint8_t protocols, transceiver_type_t transceivers)
+{
+    int i;
+
+    if (transceivers == 0) {
+        DEBUG("Interface initialization: Precondition not met.\n");
+        return -1;
+    }
+
+    for (i = 0; i < NET_IF_MAX; i++) {
+        if (!interfaces[i].initialized) {
+            interfaces[i].initialized = 1;
+            interfaces[i].protocols = protocols;
+            mutex_init(&interfaces[i].address_buffer_mutex);
+            interfaces[i].transceivers = transceivers;
+            DEBUG("Initialized interface %d for protocols %d on transceivers 0x%x\n",
+                  i, protocols, transceivers);
+            return i;
+        }
+    }
+
+    DEBUG("Interface buffer full.\n");
+    return -1;
+}
+
+int net_if_iter_interfaces(int start)
+{
+    if (start == NET_IF_MAX - 1) {
+        return -1;
+    }
+
+    start++;
+
+    while (start < NET_IF_MAX && !interfaces[start].initialized) {
+        start++;
+    }
+
+    return start;
+}
+
+int net_if_add_address(int if_id, net_if_addr_t *addr)
+{
+    if (!addr || !addr->addr_data) {
+        DEBUG("Address addition: Precondition not met.\n");
+        return 0;
+    }
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Address addition: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    mutex_lock(&interfaces[if_id].address_buffer_mutex);
+
+    interfaces[if_id].protocols |= addr->addr_protocol;
+
+    clist_add((clist_node_t **)&interfaces[if_id].addresses,
+              (clist_node_t *)addr);
+
+    mutex_unlock(&interfaces[if_id].address_buffer_mutex);
+
+    return 1;
+}
+
+int net_if_del_address(int if_id, net_if_addr_t *addr)
+{
+    if (!addr || !addr->addr_data) {
+        DEBUG("Address deletion: Precondition not met.\n");
+        return 0;
+    }
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Address deletion: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    mutex_lock(&interfaces[if_id].address_buffer_mutex);
+
+    clist_remove((clist_node_t **)&interfaces[if_id].addresses,
+                 (clist_node_t *)addr);
+
+    mutex_unlock(&interfaces[if_id].address_buffer_mutex);
+
+    return 1;
+}
+
+net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Address iteration: No interface initialized with ID %d.\n", if_id);
+        return NULL;
+    }
+
+    if (*addr == NULL) {
+        *addr = interfaces[if_id].addresses;
+        return *addr;
+    }
+
+    clist_advance((clist_node_t **)addr);
+
+    if (*addr == interfaces[if_id].addresses) {
+        *addr = NULL;
+    }
+
+    return *addr;
+}
+
+net_if_l3p_t net_if_get_l3p_types(int if_id)
+{
+    net_if_l3p_t protocols;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Get L3 protocols: No interface initialized with ID %d.\n", if_id);
+        return NET_IF_L3P_FAILURE;
+    }
+
+    mutex_lock(&interfaces[if_id].address_buffer_mutex);
+
+    protocols = interfaces[if_id].protocols;
+
+    mutex_unlock(&interfaces[if_id].address_buffer_mutex);
+
+    return protocols;
+}
+
+int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Add L3 protocols: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    interfaces[if_id].protocols |= protocols;
+
+    return 1;
+}
+
+int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols)
+{
+    net_if_addr_t *addr_ptr = NULL;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Remove L3 protocols: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    while (net_if_iter_addresses(if_id, &addr_ptr)) {
+        if (addr_ptr->addr_protocol & protocols) {
+            net_if_del_address(if_id, addr_ptr);
+            addr_ptr = NULL;
+        }
+    }
+
+    interfaces[if_id].protocols &= ~protocols;
+
+    return 1;
+}
+
+uint32_t net_if_transceiver_get_set_handler(int if_id, uint16_t op_type,
+        void *data)
+{
+    DEBUG("net_if_transceiver_get_set_handler: if_id = %d, op_type = %d, data = %p\n",
+          if_id, op_type, data);
+    msg_t msg;
+    transceiver_command_t tcmd;
+
+    tcmd.transceivers = interfaces[if_id].transceivers;
+    tcmd.data = (char *)data;
+    msg.content.ptr = (char *)&tcmd;
+    msg.type = op_type;
+    msg_send_receive(&msg, &msg, transceiver_pid);
+
+    return msg.content.value;
+}
+
+int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode,
+                                 const void *payload, size_t payload_len)
+{
+    int if_id = -1;
+    int res = 0, res_prev = 0;
+
+    while ((if_id = net_if_iter_interfaces(if_id)) >= 0) {
+        if (interfaces[if_id].transceivers & (TRANSCEIVER_CC1100 | TRANSCEIVER_NATIVE)) {
+            res = net_if_send_packet(if_id, 0,
+                                     payload, payload_len);
+        }
+        else if (preferred_dest_mode == NET_IF_TRANS_ADDR_M_SHORT) {
+            res = net_if_send_packet(if_id, IEEE_802154_SHORT_MCAST_ADDR,
+                                     payload, payload_len);
+        }
+        else {
+            net_if_eui64_t mcast_addr = IEEE_802154_LONG_MCAST_ADDR;
+            res = net_if_send_packet_long(if_id, &mcast_addr, payload,
+                                          payload_len);
+        }
+
+        if (res_prev != 0) {
+            if (res != res_prev) {
+                return -1;
+            }
+        }
+        else {
+            if (res == 0) {
+                break;
+            }
+        }
+
+        res_prev = res;
+    }
+
+    return res;
+}
+
+int net_if_send_packet(int if_id, uint16_t target, const void *payload,
+                       size_t payload_len)
+{
+    DEBUG("net_if_send_packet: if_id = %d, target = %d, payload = %p, "
+          "payload_len = %d\n", if_id, target, payload, payload_len);
+    uint32_t response;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Send packet: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 | TRANSCEIVER_AT86RF231 | TRANSCEIVER_MC1322X)) {
+        ieee802154_packet_t p;
+
+        memset(&p, 0, sizeof(ieee802154_packet_t));
+
+        p.frame.payload = (uint8_t *)payload;
+        p.frame.payload_len = (uint8_t)payload_len;
+        p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m;
+        p.frame.fcf.dest_addr_m = IEEE_802154_SHORT_ADDR_M;
+        p.frame.fcf.ack_req = 0;
+        p.frame.fcf.sec_enb = 0;
+        p.frame.fcf.frame_type = 1;
+        p.frame.fcf.frame_pend = 0;
+
+        p.frame.dest_pan_id = net_if_get_pan_id(if_id);
+        memcpy(p.frame.dest_addr, &target, 2);
+        response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p);
+    }
+    else {
+        radio_packet_t p;
+        memset(&p, 0, sizeof(radio_packet_t));
+        p.data = (uint8_t *) payload;
+        p.length = payload_len;
+        p.dst = target;
+        response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p);
+    }
+
+
+    return (response > payload_len) ? (int)payload_len : (int)response;
+}
+
+int net_if_send_packet_long(int if_id, net_if_eui64_t *target,
+                            const void *payload, size_t payload_len)
+{
+    DEBUG("net_if_send_packet: if_id = %d, target = %016" PRIx64 ", "
+          "payload = %p, payload_len = %d\n", if_id, NTOHLL(target->uint64), payload,
+          payload_len);
+    uint32_t response;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Send packet: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 |
+                                          TRANSCEIVER_AT86RF231 |
+                                          TRANSCEIVER_MC1322X)) {
+        ieee802154_packet_t p;
+        memset(&p, 0, sizeof(ieee802154_packet_t));
+        p.frame.payload = (uint8_t *)payload;
+        p.frame.payload_len = (uint8_t)payload_len;
+        p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m;
+        p.frame.fcf.dest_addr_m = IEEE_802154_LONG_ADDR_M;
+        p.frame.fcf.ack_req = 0;
+        p.frame.fcf.sec_enb = 0;
+        p.frame.fcf.frame_type = 1;
+        p.frame.fcf.frame_pend = 0;
+        p.frame.dest_pan_id = net_if_get_pan_id(if_id);
+        memcpy(p.frame.dest_addr, target, 8);
+        response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p);
+    }
+    else {
+        radio_packet_t p;
+        memset(&p, 0, sizeof(radio_packet_t));
+        p.data = (uint8_t *) payload;
+        p.length = payload_len;
+        p.dst = NTOHS(target->uint16[3]);
+        response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p);
+    }
+
+
+    return (response > payload_len) ? (int)payload_len : (int)response;
+}
+
+int net_if_register(int if_id, int pid)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Register thread: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    return (int)transceiver_register(interfaces[if_id].transceivers, pid);
+}
+
+int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation)
+{
+    uint64_t tmp;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Get EUI-64: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    if (eui64 == NULL) {
+        DEBUG("Get EUI-64: parameter eui64 is a NULL pointer.\n");
+        return 0;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, GET_LONG_ADDR, &tmp);
+
+    eui64->uint64 = HTONLL(tmp);
+
+    if (eui64->uint64 == 0 || force_generation) {
+        uint16_t hwaddr = net_if_get_hardware_address(if_id);
+
+        if (hwaddr == 0) {
+            return 0;
+        }
+
+        /* RFC 6282 Section 3.2.2 / RFC 2464 Section 4 */
+        eui64->uint32[0] = HTONL(0x000000ff);
+        eui64->uint16[2] = HTONS(0xfe00);
+
+        if (sizeof(hwaddr) == 2) {
+            eui64->uint16[3] = HTONS(hwaddr);
+        }
+        else if (sizeof(hwaddr) == 1) {
+            eui64->uint8[6] = 0;
+            eui64->uint8[7] = (uint8_t)hwaddr;
+        }
+        else {
+            DEBUG("Error on EUI-64 generation: do not know what to do with "
+                  "hardware address of length %d\n", sizeof(hwaddr));
+            return 0;
+        }
+
+    }
+
+    return 1;
+}
+
+int net_if_set_eui64(int if_id, net_if_eui64_t *eui64)
+{
+    if (eui64 == NULL) {
+        return 0;
+    }
+
+    uint64_t tmp = NTOHLL(eui64->uint64);
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Set EUI-64: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, SET_LONG_ADDR, (void *) &tmp);
+
+    return eui64->uint64 != 0;
+}
+
+uint16_t net_if_get_hardware_address(int if_id)
+{
+    uint16_t addr;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Get hardware address: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, GET_ADDRESS, &addr);
+    return addr;
+}
+
+uint16_t net_if_set_hardware_address(int if_id, uint16_t addr)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Set hardware address: No interface initialized with ID %d.\n", if_id);
+        return 0;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, SET_ADDRESS, &addr);
+    return addr;
+}
+
+int32_t net_if_get_channel(int if_id)
+{
+    int32_t channel;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Get channel: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, GET_CHANNEL, &channel);
+    return channel;
+}
+
+int32_t net_if_set_channel(int if_id, uint16_t channel)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Set channel: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, SET_CHANNEL, &channel);
+    return channel;
+}
+
+int32_t net_if_get_pan_id(int if_id)
+{
+    int32_t pan_id;
+
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Get PAN ID: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, GET_PAN, &pan_id);
+    if (pan_id < 0) {
+        return 0;
+    }
+    else {
+        return pan_id;
+    }
+
+}
+
+int32_t net_if_set_pan_id(int if_id, uint16_t pan_id)
+{
+    if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) {
+        DEBUG("Set PAN ID: No interface initialized with ID %d.\n", if_id);
+        return -1;
+    }
+
+    net_if_transceiver_get_set_handler(if_id, SET_PAN, &pan_id);
+    return pan_id;
+}
+
+/**
+ * @}
+ */
diff --git a/sys/shell/commands/sc_transceiver.c b/sys/shell/commands/sc_transceiver.c
index f4029504faa4abffc8f9f58755a2d4b6adc3fa23..b5caa0a2682bc3127f1b5738e3bc4394c1861503 100644
--- a/sys/shell/commands/sc_transceiver.c
+++ b/sys/shell/commands/sc_transceiver.c
@@ -21,6 +21,9 @@
 #include <string.h>
 #include <inttypes.h>
 
+#ifdef MODULE_NET_IF
+#include "net_if.h"
+#endif
 #include "transceiver.h"
 #include "msg.h"
 
@@ -80,6 +83,56 @@ void _transceiver_get_set_address_handler(int argc, char **argv)
     printf("[transceiver] got address: %" PRIu16 "\n", a);
 }
 
+#ifndef MODULE_NET_IF
+uint8_t hex_to_dec(char c)
+{
+    if (c >= '0' && c <= '9') {
+        return (uint8_t)(c - '0');
+    }
+    else if (c >= 'A' && c <= 'F') {
+        return (uint8_t)(c - 55);
+    }
+    else if (c >= 'a' && c <= 'f') {
+        return (uint8_t)(c - 87);
+    }
+    else {
+        return 0xff;
+    }
+}
+
+uint64_t _str_to_eui64(const char *eui64_str)
+{
+    int i;
+    const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1];
+    uint64_t eui64 = 0;
+
+    for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) {
+        uint8_t digit;
+        eui64 <<= 8;
+
+        while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) {
+            if (--eui64_rev < eui64_str) {
+                return eui64;
+            }
+        }
+
+        eui64 = digit;
+        eui64_rev--;
+
+        while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) {
+            if (--eui64_rev < eui64_str) {
+                return eui64;
+            }
+        }
+
+        eui64 |= digit << 4;
+        eui64_rev--;
+    }
+
+    return eui64;
+}
+#endif
+
 /* checked for type safety */
 void _transceiver_get_set_long_addr_handler(int argc, char **argv)
 {
@@ -97,7 +150,13 @@ void _transceiver_get_set_long_addr_handler(int argc, char **argv)
     mesg.content.ptr = (char *) &tcmd;
 
     if (argc > 1) {
-        a = atoll(argv[1]);
+#ifdef MODULE_NET_IF
+        net_if_eui64_t eui64;
+        net_if_hex_to_eui64(&eui64, argv[1]);
+        a = eui64.uint64;
+#else
+        a = _str_to_eui64(argv[1]);
+#endif
         printf("[transceiver] trying to set EUI-64 %016"PRIx64"\n", a);
         mesg.type = SET_LONG_ADDR;
     }