Add active scan to API and CLI. (#27)

* Add active scan functions and definitions to core C api.
* Add active scan command to CLI.
* Add emulation of PHY channel isolation.
diff --git a/examples/platform/posix/radio.cpp b/examples/platform/posix/radio.cpp
index 5aebbee..40a9ffc 100644
--- a/examples/platform/posix/radio.cpp
+++ b/examples/platform/posix/radio.cpp
@@ -61,8 +61,15 @@
     kStateListen = 3,
     kStateReceive = 4,
     kStateTransmit = 5,
+    kStateAckWait = 6,
 };
 
+struct RadioMessage
+{
+    uint8_t mChannel;
+    uint8_t mPsdu[Mac::Frame::kMTU];
+} __attribute__((packed));
+
 static void *phy_receive_thread(void *arg);
 
 static PhyState s_state = kStateDisabled;
@@ -171,6 +178,7 @@
 
     case kStateListen:
     case kStateTransmit:
+    case kStateAckWait:
         s_state = kStateIdle;
         pthread_cond_signal(&s_condition_variable);
         break;
@@ -205,6 +213,7 @@
 {
     ThreadError error = kThreadError_None;
     struct sockaddr_in sockaddr;
+    RadioMessage message;
 
     pthread_mutex_lock(&s_mutex);
     VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
@@ -218,6 +227,9 @@
     sockaddr.sin_family = AF_INET;
     inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
 
+    message.mChannel = s_transmit_frame->mChannel;
+    memcpy(message.mPsdu, s_transmit_frame->mPsdu, s_transmit_frame->mLength);
+
     for (int i = 1; i < 34; i++)
     {
         if (args_info.nodeid_arg == i)
@@ -226,11 +238,14 @@
         }
 
         sockaddr.sin_port = htons(9000 + i);
-        sendto(s_sockfd, s_transmit_frame->mPsdu, s_transmit_frame->mLength, 0,
-               (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+        sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
     }
 
-    if (!reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
+    if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
+    {
+        s_state = kStateAckWait;
+    }
+    else
     {
         otPlatRadioSignalTransmitDone();
     }
@@ -249,7 +264,7 @@
 {
     ThreadError error = kThreadError_None;
 
-    VerifyOrExit(s_state == kStateTransmit, error = kThreadError_InvalidState);
+    VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
 
     pthread_mutex_lock(&s_mutex);
     s_state = kStateIdle;
@@ -273,6 +288,7 @@
     int length;
     uint8_t tx_sequence, rx_sequence;
     uint8_t command_id;
+    RadioMessage message;
 
     while (1)
     {
@@ -288,7 +304,7 @@
 
         pthread_mutex_lock(&s_mutex);
 
-        while (s_state == kStateIdle)
+        while (s_state == kStateIdle || s_state == kStateTransmit)
         {
             pthread_cond_wait(&s_condition_variable, &s_mutex);
         }
@@ -302,7 +318,12 @@
             break;
 
         case kStateTransmit:
-            length = recvfrom(s_sockfd, receive_frame.mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
+            break;
+
+        case kStateAckWait:
+            length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
+            receive_frame.mLength = length - 1;
+            memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
 
             if (length < 0)
             {
@@ -337,7 +358,17 @@
             break;
 
         case kStateListen:
+            length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
+
+            if (s_receive_frame->mChannel != message.mChannel)
+            {
+                break;
+            }
+
             s_state = kStateReceive;
+            s_receive_frame->mLength = length - 1;
+            memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
+
             otPlatRadioSignalReceiveDone();
 
             while (s_state == kStateReceive)
@@ -361,6 +392,7 @@
 void send_ack()
 {
     Mac::Frame *ack_frame;
+    RadioMessage message;
     uint8_t sequence;
     struct sockaddr_in sockaddr;
 
@@ -374,6 +406,9 @@
     sockaddr.sin_family = AF_INET;
     inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
 
+    message.mChannel = s_receive_frame->mChannel;
+    memcpy(message.mPsdu, m_ack_packet.mPsdu, m_ack_packet.mLength);
+
     for (int i = 1; i < 34; i++)
     {
         if (args_info.nodeid_arg == i)
@@ -382,8 +417,7 @@
         }
 
         sockaddr.sin_port = htons(9000 + i);
-        sendto(s_sockfd, m_ack_packet.mPsdu, m_ack_packet.mLength, 0,
-               (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+        sendto(s_sockfd, &message, 1 + m_ack_packet.mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
     }
 }
 
@@ -393,11 +427,9 @@
     Mac::Frame *receive_frame;
     uint16_t dstpan;
     Mac::Address dstaddr;
-    int length;
 
     VerifyOrExit(s_state == kStateReceive, error = kThreadError_InvalidState);
 
-    length = recvfrom(s_sockfd, s_receive_frame->mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
     receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
 
     receive_frame->GetDstAddr(dstaddr);
@@ -425,7 +457,6 @@
         ExitNow(error = kThreadError_Abort);
     }
 
-    s_receive_frame->mLength = length;
     s_receive_frame->mPower = -20;
 
     // generate acknowledgment
diff --git a/include/openthread-types.h b/include/openthread-types.h
index b4eba39..792ef92 100644
--- a/include/openthread-types.h
+++ b/include/openthread-types.h
@@ -65,6 +65,49 @@
     kThreadError_Error = 255,
 } ThreadError;
 
+
+#define OT_EXT_ADDRESS_SIZE   8   ///< Size of an IEEE 802.15.4 Extended Address (bytes)
+#define OT_EXT_PAN_ID_SIZE    8   ///< Size of a Thread PAN ID (bytes)
+#define OT_NETWORK_NAME_SIZE  16  ///< Size of the Thread Network Name field (bytes)
+
+/**
+ * This type represents the IEEE 802.15.4 PAN ID.
+ *
+ */
+typedef uint16_t otPanId;
+
+/**
+ * This type represents the IEEE 802.15.4 Short Address.
+ *
+ */
+typedef uint16_t otShortAddress;
+
+/**
+ * This type represents the IEEE 802.15.4 Extended Address.
+ *
+ */
+typedef struct otExtAddress
+{
+    uint8_t m8[OT_EXT_ADDRESS_SIZE];  ///< IEEE 802.15.4 Extended Address bytes
+} otExtAddress;
+
+/**
+ * This struct represents a received IEEE 802.15.4 Beacon.
+ *
+ */
+typedef struct otActiveScanResult
+{
+    otExtAddress   mExtAddress;      ///< IEEE 802.15.4 Extended Address
+    const char    *mNetworkName;     ///< Thread Network Name
+    const uint8_t *mExtPanId;        ///< Thread Extended PAN ID
+    uint16_t       mPanId;           ///< IEEE 802.15.4 PAN ID
+    uint8_t        mChannel;         ///< IEEE 802.15.4 Channel
+    int8_t         mRssi;            ///< RSSI (dBm)
+    uint8_t        mVersion : 4;     ///< Version
+    bool           mIsNative : 1;    ///< Native Commissioner flag
+    bool           mIsJoinable : 1;  ///< Joining Permitted flag
+} otActiveScanResult;
+
 /**
  * @addtogroup config  Configuration
  *
diff --git a/include/openthread.h b/include/openthread.h
index 98c937b..0729507 100644
--- a/include/openthread.h
+++ b/include/openthread.h
@@ -51,6 +51,7 @@
  * @{
  *
  * @defgroup execution Execution
+ * @defgroup commands Commands
  * @defgroup config Configuration
  * @defgroup diags Diagnostics
  * @defgroup messages Message Buffers
@@ -136,6 +137,57 @@
  */
 
 /**
+ * @addtogroup commands  Commands
+ *
+ * @brief
+ *   This module includes functions for OpenThread commands.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Enable the Thread interface.
+ *
+ * @retval kThreadErrorNone  Successfully enabled the Thread interface.
+ */
+ThreadError otEnable(void);
+
+/**
+ * Disable the Thread interface.
+ *
+ * @retval kThreadErrorNone  Successfully disabled the Thread interface.
+ */
+ThreadError otDisable(void);
+
+/**
+ * This function pointer is called during an IEEE 802.15.4 Active Scan when an IEEE 802.15.4 Beacon is received or
+ * the scan completes.
+ *
+ * @param[in]  aResult  A valid pointer to the beacon information or NULL when the active scan completes.
+ *
+ */
+typedef void (*otHandleActiveScanResult)(otActiveScanResult *aResult);
+
+/**
+ * This function starts an IEEE 802.15.4 Active Scan
+ *
+ * @param[in]  aScanChannels  A bit vector indicating which channels to scan.
+ * @param[in]  aScanDuration  The time in milliseconds to spend scanning each channel.
+ * @param[in]  aCallback      A pointer to a function that is called when a beacon is received or the scan completes.
+ *
+ * @retval kThreadError_None  Accepted the Active Scan request.
+ * @retval kThreadError_Busy  Already performing an Active Scan.
+ *
+ */
+ThreadError otActiveScan(uint16_t aScanChannels, uint16_t aScanDuration, otHandleActiveScanResult aCallback);
+
+/**
+ * @}
+ *
+ */
+
+/**
  * @addtogroup config  Configuration
  *
  * @brief
@@ -289,7 +341,7 @@
  *
  * @sa otSetPanId
  */
-uint16_t otGetPanId(void);
+otPanId otGetPanId(void);
 
 /**
  * Set the IEEE 802.15.4 PAN ID.
@@ -301,7 +353,34 @@
  *
  * @sa otGetPanId
  */
-ThreadError otSetPanId(uint16_t aPanId);
+ThreadError otSetPanId(otPanId aPanId);
+
+/**
+ * Get the list of IPv6 addresses assigned to the Thread interface.
+ *
+ * @returns A pointer to the first Network Inteface Address.
+ */
+const otNetifAddress *otGetUnicastAddresses();
+
+/**
+ * Add a Network Interface Address to the Thread interface.
+ *
+ * @param[in]  aAddress  A pointer to a Network Interface Address.
+ *
+ * @retval kThreadErrorNone  Successfully added the Network Interface Address.
+ * @retval kThreadErrorBusy  The Network Interface Address pointed to by @p aAddress is already added.
+ */
+ThreadError otAddUnicastAddress(otNetifAddress *aAddress);
+
+/**
+ * Remove a Network Interface Address from the Thread interface.
+ *
+ * @param[in]  aAddress  A pointer to a Network Interface Address.
+ *
+ * @retval kThreadErrorNone      Successfully removed the Network Interface Address.
+ * @retval kThreadErrorNotFound  The Network Interface Address point to by @p aAddress was not added.
+ */
+ThreadError otRemoveUnicastAddress(otNetifAddress *aAddress);
 
 /**
  * @}
@@ -731,47 +810,6 @@
 ThreadError otIp6AddressFromString(const char *aString, otIp6Address *aAddress);
 
 /**
- * Get the list of IPv6 addresses assigned to the Thread interface.
- *
- * @returns A pointer to the first Network Inteface Address.
- */
-const otNetifAddress *otGetUnicastAddresses();
-
-/**
- * Add a Network Interface Address to the Thread interface.
- *
- * @param[in]  aAddress  A pointer to a Network Interface Address.
- *
- * @retval kThreadErrorNone  Successfully added the Network Interface Address.
- * @retval kThreadErrorBusy  The Network Interface Address pointed to by @p aAddress is already added.
- */
-ThreadError otAddUnicastAddress(otNetifAddress *aAddress);
-
-/**
- * Remove a Network Interface Address from the Thread interface.
- *
- * @param[in]  aAddress  A pointer to a Network Interface Address.
- *
- * @retval kThreadErrorNone      Successfully removed the Network Interface Address.
- * @retval kThreadErrorNotFound  The Network Interface Address point to by @p aAddress was not added.
- */
-ThreadError otRemoveUnicastAddress(otNetifAddress *aAddress);
-
-/**
- * Enable the Thread interface.
- *
- * @retval kThreadErrorNone  Successfully enabled the Thread interface.
- */
-ThreadError otEnable(void);
-
-/**
- * Disable the Thread interface.
- *
- * @retval kThreadErrorNone  Successfully disabled the Thread interface.
- */
-ThreadError otDisable(void);
-
-/**
  * @addtogroup messages  Message Buffers
  *
  * @brief
diff --git a/src/cli/README.md b/src/cli/README.md
index 080a71c..2063a10 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -27,6 +27,7 @@
 * [rloc16](#rloc16)
 * [route](#route)
 * [routerupgradethreshold](#routerupgradethreshold)
+* [scan](#scan)
 * [start](#start)
 * [state](#state)
 * [stop](#stop)
@@ -396,6 +397,20 @@
 Done
 ```
 
+### scan \[channel\]
+
+Perform an IEEE 802.15.4 Active Scan.
+
+* channel: The channel to scan on.  If no channel is provided, the active scan will cover all valid channels.
+
+```bash
+$ scan
+| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm |
++---+------------------+------------------+------+------------------+----+-----+
+| 0 | OpenThread       | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 |
+Done
+```
+
 ### start
 
 Enable OpenThread.
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index 626c6df..10a6ac8 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -69,6 +69,7 @@
     { "rloc16", &ProcessRloc16 },
     { "route", &ProcessRoute },
     { "routerupgradethreshold", &ProcessRouterUpgradeThreshold },
+    { "scan", &ProcessScan },
     { "shutdown", &ProcessShutdown },
     { "start", &ProcessStart },
     { "state", &ProcessState },
@@ -167,7 +168,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessChildTimeout(int argc, char *argv[])
@@ -187,7 +188,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessContextIdReuseDelay(int argc, char *argv[])
@@ -207,7 +208,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessExtAddress(int argc, char *argv[])
@@ -240,7 +241,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 ThreadError Interpreter::ProcessIpAddrAdd(int argc, char *argv[])
@@ -302,7 +303,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessKeySequence(int argc, char *argv[])
@@ -322,7 +323,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessLeaderWeight(int argc, char *argv[])
@@ -342,7 +343,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessMasterKey(int argc, char *argv[])
@@ -371,7 +372,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessMode(int argc, char *argv[])
@@ -437,7 +438,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessNetworkDataRegister(int argc, char *argv[])
@@ -446,7 +447,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessNetworkIdTimeout(int argc, char *argv[])
@@ -466,7 +467,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessNetworkName(int argc, char *argv[])
@@ -483,7 +484,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessPanId(int argc, char *argv[])
@@ -503,7 +504,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
@@ -544,7 +545,7 @@
     sResponse.Init();
 
 exit:
-    {}
+    return;
 }
 
 ThreadError Interpreter::ProcessPrefixAdd(int argc, char *argv[])
@@ -685,7 +686,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessReleaseRouterId(int argc, char *argv[])
@@ -700,7 +701,7 @@
     }
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessRloc16(int argc, char *argv[])
@@ -819,7 +820,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessRouterUpgradeThreshold(int argc, char *argv[])
@@ -839,7 +840,72 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
+}
+
+void Interpreter::ProcessScan(int argc, char *argv[])
+{
+    uint16_t scanChannels = 0;
+    long value;
+
+    if (argc > 0)
+    {
+        SuccessOrExit(ParseLong(argv[0], value));
+        scanChannels = 1 << (value - kPhyMinChannel);
+    }
+
+    SuccessOrExit(otActiveScan(scanChannels, 0, &HandleActiveScanResult));
+    sResponse.Append("| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm |\r\n");
+    sResponse.Append("+---+------------------+------------------+------+------------------+----+-----+\r\n");
+
+exit:
+    return;
+}
+
+void Interpreter::HandleActiveScanResult(otActiveScanResult *aResult)
+{
+    const uint8_t *bytes;
+
+    sResponse.Init();
+
+    if (aResult == NULL)
+    {
+        sResponse.Append("Done\r\n");
+        ExitNow();
+    }
+
+    sResponse.Append("| %d ", aResult->mIsJoinable);
+
+    if (aResult->mNetworkName != NULL)
+    {
+        sResponse.Append("| %-16s ", aResult->mNetworkName);
+    }
+    else
+    {
+        sResponse.Append("| ---------------- ");
+    }
+
+    if (aResult->mExtPanId != NULL)
+    {
+        bytes = aResult->mExtPanId;
+        sResponse.Append("| %02x%02x%02x%02x%02x%02x%02x%02x ",
+                         bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]);
+    }
+    else
+    {
+        sResponse.Append("| ---------------- ");
+    }
+
+    sResponse.Append("| %04x ", aResult->mPanId);
+
+    bytes = aResult->mExtAddress.m8;
+    sResponse.Append("| %02x%02x%02x%02x%02x%02x%02x%02x ",
+                     bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]);
+    sResponse.Append("| %02d ", aResult->mChannel);
+    sResponse.Append("| %03d |\r\n", aResult->mRssi);
+
+exit:
+    sServer->Output(sResponse.GetResponse(), sResponse.GetResponseLength());
 }
 
 void Interpreter::ProcessShutdown(int argc, char *argv[])
@@ -856,7 +922,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessState(int argc, char *argv[])
@@ -913,7 +979,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessStop(int argc, char *argv[])
@@ -922,7 +988,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessWhitelist(int argc, char *argv[])
@@ -973,7 +1039,7 @@
     sResponse.Append("Done\r\n");
 
 exit:
-    {}
+    return;
 }
 
 void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer)
@@ -1012,7 +1078,7 @@
     }
 
 exit:
-    {}
+    return;
 }
 
 }  // namespace Cli
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index a34990d..f7b78cb 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -159,6 +159,7 @@
     static ThreadError ProcessRouteRemove(int argc, char *argv[]);
     static void ProcessRouterUpgradeThreshold(int argc, char *argv[]);
     static void ProcessRloc16(int argc, char *argv[]);
+    static void ProcessScan(int argc, char *argv[]);
     static void ProcessShutdown(int argc, char *argv[]);
     static void ProcessStart(int argc, char *argv[]);
     static void ProcessState(int argc, char *argv[]);
@@ -166,6 +167,7 @@
     static void ProcessWhitelist(int argc, char *argv[]);
 
     static void HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+    static void HandleActiveScanResult(otActiveScanResult *aResult);
     static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength);
     static ThreadError ParseLong(char *argv, long &value);
 
diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp
index 499db7b..f847db3 100644
--- a/src/core/mac/mac.cpp
+++ b/src/core/mac/mac.cpp
@@ -85,11 +85,12 @@
     mRxOnWhenIdle = true;
     mCsmaAttempts = 0;
     mTransmitBeacon = false;
+    mBeacon.Init();
 
     mActiveScanRequest = false;
     mScanChannel = kPhyMinChannel;
-    mScanChannelMask = 0xff;
-    mScanIntervalPerChannel = 0;
+    mScanChannels = 0xff;
+    mScanDuration = 0;
     mActiveScanHandler = NULL;
     mActiveScanContext = NULL;
 
@@ -103,7 +104,7 @@
 
     for (size_t i = 0; i < sizeof(mExtAddress); i++)
     {
-        mExtAddress.mBytes[i] = otPlatRandomGet();
+        mExtAddress.m8[i] = otPlatRandomGet();
     }
 
     SetExtendedPanId(sExtendedPanidInit);
@@ -121,7 +122,7 @@
 
     SuccessOrExit(error = otPlatRadioEnable());
 
-    SetExtendedPanId(mExtendedPanid);
+    SetExtendedPanId(mBeacon.GetExtendedPanId());
     otPlatRadioSetPanId(mPanId);
     otPlatRadioSetShortAddress(mShortAddress);
     {
@@ -129,7 +130,7 @@
 
         for (size_t i = 0; i < sizeof(buf); i++)
         {
-            buf[i] = mExtAddress.mBytes[7 - i];
+            buf[i] = mExtAddress.m8[7 - i];
         }
 
         otPlatRadioSetExtendedAddress(buf);
@@ -174,8 +175,7 @@
     return error;
 }
 
-ThreadError Mac::ActiveScan(uint16_t aIntervalPerChannel, uint16_t aChannelMask,
-                            ActiveScanHandler aHandler, void *aContext)
+ThreadError Mac::ActiveScan(uint16_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext)
 {
     ThreadError error = kThreadError_None;
 
@@ -184,21 +184,21 @@
 
     mActiveScanHandler = aHandler;
     mActiveScanContext = aContext;
-    mScanChannelMask = (aChannelMask == 0) ? kScanChannelMaskAll : aChannelMask;
-    mScanIntervalPerChannel = (aIntervalPerChannel == 0) ? kScanDefaultInterval : aIntervalPerChannel;
+    mScanChannels = (aScanChannels == 0) ? kScanChannelsAll : aScanChannels;
+    mScanDuration = (aScanDuration == 0) ? kScanDurationDefault : aScanDuration;
 
     mScanChannel = kPhyMinChannel;
 
-    while ((mScanChannelMask & 1) == 0)
+    while ((mScanChannels & 1) == 0)
     {
-        mScanChannelMask >>= 1;
+        mScanChannels >>= 1;
         mScanChannel++;
     }
 
     if (mState == kStateIdle)
     {
         mState = kStateActiveScan;
-        mBeginTransmit.Post();
+        StartCsmaBackoff();
     }
     else
     {
@@ -266,22 +266,21 @@
 
 const char *Mac::GetNetworkName(void) const
 {
-    return mNetworkName;
+    return mBeacon.GetNetworkName();
 }
 
 ThreadError Mac::SetNetworkName(const char *aNetworkName)
 {
-    memset(mNetworkName, 0, sizeof(mNetworkName));
-    strncpy(mNetworkName, aNetworkName, sizeof(mNetworkName));
+    mBeacon.SetNetworkName(aNetworkName);
     return kThreadError_None;
 }
 
-uint16_t Mac::GetPanId(void) const
+PanId Mac::GetPanId(void) const
 {
     return mPanId;
 }
 
-ThreadError Mac::SetPanId(uint16_t aPanId)
+ThreadError Mac::SetPanId(PanId aPanId)
 {
     mPanId = aPanId;
     return otPlatRadioSetPanId(mPanId);
@@ -289,13 +288,13 @@
 
 const uint8_t *Mac::GetExtendedPanId(void) const
 {
-    return mExtendedPanid;
+    return mBeacon.GetExtendedPanId();
 }
 
 ThreadError Mac::SetExtendedPanId(const uint8_t *aExtPanId)
 {
-    memcpy(mExtendedPanid, aExtPanId, sizeof(mExtendedPanid));
-    mMle.SetMeshLocalPrefix(mExtendedPanid);
+    mBeacon.SetExtendedPanId(aExtPanId);
+    mMle.SetMeshLocalPrefix(aExtPanId);
     return kThreadError_None;
 }
 
@@ -366,7 +365,6 @@
     else if (mTransmitBeacon)
     {
         mTransmitBeacon = false;
-        assert(false);
         mState = kStateTransmitBeacon;
         StartCsmaBackoff();
     }
@@ -386,7 +384,7 @@
     // source address
     for (int i = 0; i < 8; i++)
     {
-        aNonce[i] = aAddress.mBytes[i];
+        aNonce[i] = aAddress.m8[i];
     }
 
     aNonce += 8;
@@ -416,7 +414,6 @@
 
 void Mac::SendBeacon(Frame &aFrame)
 {
-    uint8_t *payload;
     uint16_t fcf;
 
     // initialize MAC header
@@ -426,38 +423,8 @@
     aFrame.SetSrcAddr(mExtAddress);
 
     // write payload
-    payload = aFrame.GetPayload();
-
-    // Superframe Specification
-    payload[0] = 0xff;
-    payload[1] = 0x0f;
-    payload += 2;
-
-    // GTS Fields
-    payload[0] = 0x00;
-    payload++;
-
-    // Pending Address Fields
-    payload[0] = 0x00;
-    payload++;
-
-    // Protocol ID
-    payload[0] = 0x03;
-    payload++;
-
-    // Version and Flags
-    payload[0] = 0x1 << 4 | 0x1;
-    payload++;
-
-    // Network Name
-    memcpy(payload, mNetworkName, sizeof(mNetworkName));
-    payload += sizeof(mNetworkName);
-
-    // Extended PAN
-    memcpy(payload, mExtendedPanid, sizeof(mExtendedPanid));
-    payload += sizeof(mExtendedPanid);
-
-    aFrame.SetPayloadLength(payload - aFrame.GetPayload());
+    memcpy(aFrame.GetPayload(), &mBeacon, sizeof(mBeacon));
+    aFrame.SetPayloadLength(sizeof(mBeacon));
 
     otLogInfoMac("Sent Beacon\n");
 }
@@ -590,7 +557,7 @@
     switch (mState)
     {
     case kStateActiveScan:
-        mAckTimer.Start(mScanIntervalPerChannel);
+        mAckTimer.Start(mScanDuration);
         break;
 
     case kStateTransmitBeacon:
@@ -634,17 +601,17 @@
     case kStateActiveScan:
         do
         {
-            mScanChannelMask >>= 1;
+            mScanChannels >>= 1;
             mScanChannel++;
 
-            if (mScanChannelMask == 0 || mScanChannel > kPhyMaxChannel)
+            if (mScanChannels == 0 || mScanChannel > kPhyMaxChannel)
             {
                 mActiveScanHandler(mActiveScanContext, NULL);
                 ScheduleNextTransmission();
                 ExitNow();
             }
         }
-        while ((mScanChannelMask & 1) == 0);
+        while ((mScanChannels & 1) == 0);
 
         StartCsmaBackoff();
         break;
@@ -684,7 +651,7 @@
     switch (mState)
     {
     case kStateActiveScan:
-        mAckTimer.Start(mScanIntervalPerChannel);
+        mAckTimer.Start(mScanDuration);
         break;
 
     case kStateTransmitBeacon:
@@ -908,7 +875,7 @@
     switch (mState)
     {
     case kStateActiveScan:
-        HandleBeaconFrame();
+        mActiveScanHandler(mActiveScanContext, &mReceiveFrame);
         break;
 
     default:
@@ -934,71 +901,6 @@
     NextOperation();
 }
 
-void Mac::HandleBeaconFrame(void)
-{
-    uint8_t *payload = mReceiveFrame.GetPayload();
-    uint8_t payloadLength = mReceiveFrame.GetPayloadLength();
-    ActiveScanResult result;
-    Address address;
-
-    if (mReceiveFrame.GetType() != Frame::kFcfFrameBeacon)
-    {
-        ExitNow();
-    }
-
-#if 0
-
-    // Superframe Specification, GTS fields, and Pending Address fields
-    if (payloadLength < 4 || payload[0] != 0xff || payload[1] != 0x0f || payload[2] != 0x00 || payload[3] != 0x00)
-    {
-        ExitNow();
-    }
-
-#endif
-    payload += 4;
-    payloadLength -= 4;
-
-#if 0
-
-    // Protocol ID
-    if (payload[0] != 3)
-    {
-        ExitNow();
-    }
-
-#endif
-    payload++;
-
-    // skip Version and Flags
-    payload++;
-
-    // network name
-    strncpy(result.mNetworkName, reinterpret_cast<char*>(payload), kNetworkNameSize);
-    payload += kNetworkNameSize;
-
-    // extended panid
-    memcpy(result.mExtPanid, payload, kExtPanIdSize);
-    payload += kExtPanIdSize;
-
-    // extended address
-    mReceiveFrame.GetSrcAddr(address);
-    memcpy(result.mExtAddr, &address.mExtAddress, sizeof(result.mExtAddr));
-
-    // panid
-    mReceiveFrame.GetSrcPanId(result.mPanId);
-
-    // channel
-    result.mChannel = mReceiveFrame.GetChannel();
-
-    // rssi
-    result.mRssi = mReceiveFrame.GetPower();
-
-    mActiveScanHandler(mActiveScanContext, &result);
-
-exit:
-    {}
-}
-
 ThreadError Mac::HandleMacCommand(void)
 {
     ThreadError error = kThreadError_None;
@@ -1012,10 +914,9 @@
 
         if (mState == kStateIdle)
         {
-            assert(false);
             mState = kStateTransmitBeacon;
             mTransmitBeacon = false;
-            mBeginTransmit.Post();
+            StartCsmaBackoff();
         }
 
         ExitNow(error = kThreadError_Drop);
diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp
index e6118c7..9215074 100644
--- a/src/core/mac/mac.hpp
+++ b/src/core/mac/mac.hpp
@@ -65,36 +65,19 @@
  */
 enum
 {
-    kMinBE                = 3,    ///< macMinBE (IEEE 802.15.4-2006)
-    kMaxBE                = 6,    ///< macMaxBE (IEEE 802.15.4-2006)
-    kMaxCSMABackoffs      = 12,   ///< macMaxCSMABackoffs (IEEE 802.15.4-2006)
-    kUnitBackoffPeriod    = 20,   ///< Number of symbols (IEEE 802.15.4-2006)
+    kMinBE                = 3,       ///< macMinBE (IEEE 802.15.4-2006)
+    kMaxBE                = 6,       ///< macMaxBE (IEEE 802.15.4-2006)
+    kMaxCSMABackoffs      = 12,      ///< macMaxCSMABackoffs (IEEE 802.15.4-2006)
+    kUnitBackoffPeriod    = 20,      ///< Number of symbols (IEEE 802.15.4-2006)
 
-    kMinBackoff           = 16,   ///< Minimum backoff (milliseconds).
+    kMinBackoff           = 16,      ///< Minimum backoff (milliseconds).
 
-    kAckTimeout           = 16,   ///< Timeout for waiting on an ACK (milliseconds).
-    kDataPollTimeout      = 100,  ///< Timeout for receivint Data Frame (milliseconds).
-    kNonceSize            = 13,   ///< Size of IEEE 802.15.4 Nonce (bytes).
+    kAckTimeout           = 16,      ///< Timeout for waiting on an ACK (milliseconds).
+    kDataPollTimeout      = 100,     ///< Timeout for receivint Data Frame (milliseconds).
+    kNonceSize            = 13,      ///< Size of IEEE 802.15.4 Nonce (bytes).
 
-    kScanChannelMaskAll   = 0xffff,
-    kScanDefaultInterval  = 128,  ///< Default interval between channels (milliseconds).
-
-    kNetworkNameSize      = 16,   ///< Size of Thread Network Name (bytes).
-    kExtPanIdSize         = 8,    ///< Size of Thread Extended PAN ID.
-};
-
-/**
- * This structure represents an Active Scan result.
- *
- */
-struct ActiveScanResult
-{
-    char     mNetworkName[kNetworkNameSize];  ///<  The Thread Network Name.
-    uint8_t  mExtPanid[kExtPanIdSize];        ///<  The Thread Extended PAN ID.
-    uint8_t  mExtAddr[ExtAddress::kLength];   ///<  The IEEE 802.15.4 Extended Address.
-    uint16_t mPanId;                          ///<  The IEEE 802.15.4 PAN ID.
-    uint8_t  mChannel;                        ///<  The IEEE 802.15.4 Channel.
-    int8_t   mRssi;                           ///<  The RSSI in dBm.
+    kScanChannelsAll      = 0xffff,  ///< All channels.
+    kScanDurationDefault  = 200,     ///< Default interval between channels (milliseconds).
 };
 
 /**
@@ -225,23 +208,22 @@
     /**
      * This function pointer is called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
      *
-     * @param[in]  aContext  A pointer to arbitrary context information.
-     * @param[in]  aResult   A reference to the Active Scan result.
+     * @param[in]  aContext       A pointer to arbitrary context information.
+     * @param[in]  aBeaconFrame   A pointer to the Beacon frame.
      *
      */
-    typedef void (*ActiveScanHandler)(void *aContext, ActiveScanResult *aResult);
+    typedef void (*ActiveScanHandler)(void *aContext, Frame *aBeaconFrame);
 
     /**
      * This method starts an IEEE 802.15.4 Active Scan.
      *
-     * @param[in]  aIntervalPerChannel  The time in milliseconds to spend scanning each channel.
-     * @param[in]  aChannelMask         A bit vector indicating which channels to scan.
-     * @param[in]  aHandler             A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
-     * @param[in]  aContext             A pointer to arbitrary context information.
+     * @param[in]  aScanChannels  A bit vector indicating which channels to scan.
+     * @param[in]  aScanDuration  The time in milliseconds to spend scanning each channel.
+     * @param[in]  aHandler       A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
+     * @param[in]  aContext       A pointer to arbitrary context information.
      *
      */
-    ThreadError ActiveScan(uint16_t aIntervalPerChannel, uint16_t aChannelMask,
-                           ActiveScanHandler aHandler, void *aContext);
+    ThreadError ActiveScan(uint16_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
 
     /**
      * This method indicates whether or not rx-on-when-idle is enabled.
@@ -413,7 +395,6 @@
     void SendBeaconRequest(Frame &aFrame);
     void SendBeacon(Frame &aFrame);
     void StartBackoff(void);
-    void HandleBeaconFrame(void);
     ThreadError HandleMacCommand(void);
 
     static void HandleAckTimer(void *aContext);
@@ -438,11 +419,11 @@
 
     ExtAddress mExtAddress;
     ShortAddress mShortAddress;
-    uint16_t mPanId;
-    uint8_t mExtendedPanid[kExtPanIdSize];
-    char mNetworkName[kNetworkNameSize];
+    PanId mPanId;
     uint8_t mChannel;
 
+    Beacon mBeacon;
+
     Frame mSendFrame;
     Frame mReceiveFrame;
     Sender *mSendHead, *mSendTail;
@@ -466,8 +447,8 @@
 
     bool mActiveScanRequest;
     uint8_t mScanChannel;
-    uint16_t mScanChannelMask;
-    uint16_t mScanIntervalPerChannel;
+    uint16_t mScanChannels;
+    uint16_t mScanDuration;
     ActiveScanHandler mActiveScanHandler;
     void *mActiveScanContext;
 
diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp
index a766f94..16b5271 100644
--- a/src/core/mac/mac_frame.cpp
+++ b/src/core/mac/mac_frame.cpp
@@ -41,8 +41,8 @@
 
 void ExtAddress::Set(const Ip6::Address &aIpAddress)
 {
-    memcpy(mBytes, aIpAddress.GetIid(), kLength);
-    mBytes[0] ^= 0x02;
+    memcpy(m8, aIpAddress.GetIid(), sizeof(m8));
+    m8[0] ^= 0x02;
 }
 
 ThreadError Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
@@ -287,7 +287,7 @@
 
         for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
         {
-            aAddress.mExtAddress.mBytes[i] = buf[sizeof(ExtAddress) - 1 - i];
+            aAddress.mExtAddress.m8[i] = buf[sizeof(ExtAddress) - 1 - i];
         }
 
         break;
@@ -329,7 +329,7 @@
 
     for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
     {
-        buf[i] = aExtAddress.mBytes[sizeof(ExtAddress) - 1 - i];
+        buf[i] = aExtAddress.m8[sizeof(ExtAddress) - 1 - i];
     }
 
     return kThreadError_None;
@@ -444,7 +444,7 @@
 
         for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
         {
-            address.mExtAddress.mBytes[i] = buf[sizeof(ExtAddress) - 1 - i];
+            address.mExtAddress.m8[i] = buf[sizeof(ExtAddress) - 1 - i];
         }
 
         break;
@@ -486,7 +486,7 @@
 
     for (unsigned int i = 0; i < sizeof(aExtAddress); i++)
     {
-        buf[i] = aExtAddress.mBytes[sizeof(aExtAddress) - 1 - i];
+        buf[i] = aExtAddress.m8[sizeof(aExtAddress) - 1 - i];
     }
 
     return kThreadError_None;
diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp
index e153619..a88c5f6 100644
--- a/src/core/mac/mac_frame.hpp
+++ b/src/core/mac/mac_frame.hpp
@@ -36,7 +36,9 @@
 
 #include <limits.h>
 #include <stdint.h>
+#include <string.h>
 
+#include <common/encoding.hpp>
 #include <openthread-types.h>
 #include <platform/radio.h>
 
@@ -64,19 +66,19 @@
  * This type represents the IEEE 802.15.4 PAN ID.
  *
  */
-typedef uint16_t PanId;
+typedef otPanId PanId;
 
 /**
  * This type represents the IEEE 802.15.4 Short Address.
  *
  */
-typedef uint16_t ShortAddress;
+typedef otShortAddress ShortAddress;
 
 /**
  * This structure represents an IEEE 802.15.4 Extended Address.
  *
  */
-class ExtAddress
+class ExtAddress: public otExtAddress
 {
 public:
     /**
@@ -86,12 +88,6 @@
      *
      */
     void Set(const Ip6::Address &aIpAddress);
-
-    enum
-    {
-        kLength = 8,   ///< Size of IEEE 802.15.4 Extended Address in bytes.
-    };
-    uint8_t mBytes[kLength];  ///< The IEEE 802.15.4 Extended Address bytes.
 };
 
 /**
@@ -585,6 +581,157 @@
 };
 
 /**
+ * This class implements IEEE 802.15.4 Beacon generation and parsing.
+ *
+ */
+class Beacon
+{
+public:
+    enum
+    {
+        kSuperFrameSpec   = 0x0fff,                 ///< Superframe Specification value.
+        kProtocolId       = 3,                      ///< Thread Protocol ID.
+        kNetworkNameSize  = 16,                     ///< Size of Thread Network Name (bytes).
+        kExtPanIdSize     = 8,                      ///< Size of Thread Extended PAN ID.
+    };
+
+    enum
+    {
+        kProtocolVersion  = 1,                      ///< Thread Protocol version.
+        kVersionOffset    = 4,                      ///< Version field bit offset.
+        kVersionMask      = 0xf << kVersionOffset,  ///< Version field mask.
+        kNativeFlag       = 1 << 3,                 ///< Native Commissioner flag.
+        kJoiningFlag      = 1 << 0,                 ///< Joining Permitted flag.
+    };
+
+    /**
+     * This method initializes the Beacon message.
+     *
+     */
+    void Init(void) {
+        mSuperframeSpec = Thread::Encoding::LittleEndian::HostSwap16(kSuperFrameSpec);
+        mGtsSpec = 0;
+        mPendingAddressSpec = 0;
+        mProtocolId = kProtocolId;
+        mFlags = kProtocolVersion << kVersionOffset;
+    }
+
+    /**
+     * This method indicates whether or not the beacon appears to be a valid Thread Beacon message.
+     *
+     * @retval TRUE  if the beacon appears to be a valid Thread Beacon message.
+     * @retval FALSE if the beacon does not appear to be a valid Thread Beacon message.
+     *
+     */
+    bool IsValid(void) {
+        return (mSuperframeSpec == Thread::Encoding::LittleEndian::HostSwap16(kSuperFrameSpec)) &&
+               (mGtsSpec == 0) && (mPendingAddressSpec == 0) && (mProtocolId == kProtocolId);
+    }
+
+    /**
+     * This method returns the Protocol ID value.xs
+     *
+     * @returns the Protocol ID value.
+     *
+     */
+    uint8_t GetProtocolId(void) const { return mProtocolId; }
+
+    /**
+     * This method returns the Protocol Version value.
+     *
+     * @returns The Protocol Version value.
+     *
+     */
+    uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; }
+
+    /**
+     * This method indicates whether or not the Native Commissioner flag is set.
+     *
+     * @retval TRUE   if the Native Commissioner flag is set.
+     * @retval FALSE  if the Native Commissioner flag is not set.
+     *
+     */
+    bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; }
+
+    /**
+     * This method clears the Native Commissioner flag.
+     *
+     */
+    void ClearNative(void) { mFlags &= ~kNativeFlag; }
+
+    /**
+     * This method sets the Native Commissioner flag.
+     *
+     */
+    void SetNative(void) { mFlags |= kNativeFlag; }
+
+    /**
+     * This method indicates whether or not the Joining Permitted flag is set.
+     *
+     * @retval TRUE   if the Joining Permitted flag is set.
+     * @retval FALSE  if the Joining Permitted flag is not set.
+     *
+     */
+    bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; }
+
+    /**
+     * This method clears the Joining Permitted flag.
+     *
+     */
+    void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; }
+
+    /**
+     * This method sets the Joining Permitted flag.
+     *
+     */
+    void SetJoiningPermitted(void) { mFlags |= kJoiningFlag; }
+
+    /**
+     * This method returns a pointer to the Network Name field.
+     *
+     * @returns A pointer to the network name field.
+     *
+     */
+    const char *GetNetworkName(void) const { return mNetworkName; }
+
+    /**
+     * This method sets the Network Name field.
+     *
+     * @param[in]  aNetworkName  A pointer to the Network Name.
+     *
+     */
+    void SetNetworkName(const char *aNetworkName) {
+        memset(mNetworkName, 0, sizeof(mNetworkName));
+        strncpy(mNetworkName, aNetworkName, sizeof(mNetworkName));
+    }
+
+    /**
+     * This method returns a pointer to the Extended PAN ID field.
+     *
+     * @returns A pointer to the Extended PAN ID field.
+     *
+     */
+    const uint8_t *GetExtendedPanId(void) const { return mExtendedPanId; }
+
+    /**
+     * This method sets the Extended PAN ID field.
+     *
+     * @param[in]  aExtPanId  A pointer to the Extended PAN ID.
+     *
+     */
+    void SetExtendedPanId(const uint8_t *aExtPanId) { memcpy(mExtendedPanId, aExtPanId, sizeof(mExtendedPanId)); }
+
+private:
+    uint16_t mSuperframeSpec;
+    uint8_t  mGtsSpec;
+    uint8_t  mPendingAddressSpec;
+    uint8_t  mProtocolId;
+    uint8_t  mFlags;
+    char     mNetworkName[kNetworkNameSize];
+    uint8_t  mExtendedPanId[kExtPanIdSize];
+} __attribute__((packed));
+
+/**
  * @}
  *
  */
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index 89f0324..273287e 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -116,7 +116,7 @@
 
 void Address::SetIid(const Mac::ExtAddress &aEui64)
 {
-    memcpy(m8 + kInterfaceIdentifierOffset, aEui64.mBytes, kInterfaceIdentifierSize);
+    memcpy(m8 + kInterfaceIdentifierOffset, aEui64.m8, kInterfaceIdentifierSize);
     m8[kInterfaceIdentifierOffset] ^= 0x02;
 }
 
diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp
index a58d035..385ff80 100644
--- a/src/core/openthread.cpp
+++ b/src/core/openthread.cpp
@@ -45,6 +45,10 @@
 
 namespace Thread {
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Allocate the structure using "raw" storage.
 #define otDEFINE_ALIGNED_VAR(name, size, align_type)            \
     align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))]
@@ -53,9 +57,7 @@
 
 static ThreadNetif *sThreadNetif;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+static void HandleActiveScanResult(void *aContext, Mac::Frame *aFrame);
 
 void otInit()
 {
@@ -184,12 +186,12 @@
     return sThreadNetif->GetMac().SetNetworkName(aNetworkName);
 }
 
-uint16_t otGetPanId(void)
+otPanId otGetPanId(void)
 {
     return sThreadNetif->GetMac().GetPanId();
 }
 
-ThreadError otSetPanId(uint16_t aPanId)
+ThreadError otSetPanId(otPanId aPanId)
 {
     return sThreadNetif->GetMac().SetPanId(aPanId);
 }
@@ -470,6 +472,52 @@
     return sThreadNetif->Down();
 }
 
+ThreadError otActiveScan(uint16_t aScanChannels, uint16_t aScanDuration, otHandleActiveScanResult aCallback)
+{
+    return sThreadNetif->GetMac().ActiveScan(aScanChannels, aScanDuration, &HandleActiveScanResult,
+                                             reinterpret_cast<void *>(aCallback));
+}
+
+void HandleActiveScanResult(void *aContext, Mac::Frame *aFrame)
+{
+    otHandleActiveScanResult handler = reinterpret_cast<otHandleActiveScanResult>(aContext);
+    otActiveScanResult result = {};
+    Mac::Address address;
+    Mac::Beacon *beacon;
+    uint8_t payloadLength;
+
+    if (aFrame == NULL)
+    {
+        handler(NULL);
+        ExitNow();
+    }
+
+    SuccessOrExit(aFrame->GetSrcAddr(address));
+    VerifyOrExit(address.mLength == sizeof(address.mExtAddress), ;);
+    memcpy(&result.mExtAddress, &address.mExtAddress, sizeof(result.mExtAddress));
+
+    aFrame->GetSrcPanId(result.mPanId);
+    result.mChannel = aFrame->GetChannel();
+    result.mRssi = aFrame->GetPower();
+
+    payloadLength = aFrame->GetPayloadLength();
+    beacon = reinterpret_cast<Mac::Beacon *>(aFrame->GetPayload());
+
+    if (payloadLength >= sizeof(*beacon) && beacon->IsValid())
+    {
+        result.mVersion = beacon->GetProtocolVersion();
+        result.mIsJoinable = beacon->IsJoiningPermitted();
+        result.mIsNative = beacon->IsNative();
+        result.mNetworkName = beacon->GetNetworkName();
+        result.mExtPanId = beacon->GetExtendedPanId();
+    }
+
+    handler(&result);
+
+exit:
+    return;
+}
+
 otMessage otNewUdpMessage()
 {
     return Ip6::Udp::NewMessage(0);
diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp
index 3d184c1..446e8a0 100644
--- a/src/core/thread/address_resolver.cpp
+++ b/src/core/thread/address_resolver.cpp
@@ -409,7 +409,7 @@
     children = mMle.GetChildren(&numChildren);
 
     memcpy(&macAddr, mlIidTlv.GetIid(), sizeof(macAddr));
-    macAddr.mBytes[0] ^= 0x2;
+    macAddr.m8[0] ^= 0x2;
 
     for (int i = 0; i < Mle::kMaxChildren; i++)
     {
@@ -491,9 +491,9 @@
                 continue;
             }
 
-            children[i].mMacAddr.mBytes[0] ^= 0x2;
-            mlIidTlv.SetIid(children[i].mMacAddr.mBytes);
-            children[i].mMacAddr.mBytes[0] ^= 0x2;
+            children[i].mMacAddr.m8[0] ^= 0x2;
+            mlIidTlv.SetIid(children[i].mMacAddr.m8);
+            children[i].mMacAddr.m8[0] ^= 0x2;
             lastTransactionTimeTlv.SetTime(Timer::GetNow() - children[i].mLastHeard);
             SendAddressQueryResponse(targetTlv, mlIidTlv, &lastTransactionTimeTlv, aMessageInfo.GetPeerAddr());
             ExitNow();
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index 1b54463..c40ba2c 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -437,12 +437,8 @@
                         uint8_t *aNonce)
 {
     // source address
-    for (int i = 0; i < 8; i++)
-    {
-        aNonce[i] = aMacAddr.mBytes[i];
-    }
-
-    aNonce += 8;
+    memcpy(aNonce, aMacAddr.m8, sizeof(aMacAddr));
+    aNonce += sizeof(aMacAddr);
 
     // frame counter
     aNonce[0] = aFrameCounter >> 24;