diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj
index 9386127cf..1d7356a38 100644
--- a/etc/visual-studio/libopenthread.vcxproj
+++ b/etc/visual-studio/libopenthread.vcxproj
@@ -113,6 +113,7 @@
+
diff --git a/etc/visual-studio/libopenthread.vcxproj.filters b/etc/visual-studio/libopenthread.vcxproj.filters
index 8cee5ee62..2f64f57f1 100644
--- a/etc/visual-studio/libopenthread.vcxproj.filters
+++ b/etc/visual-studio/libopenthread.vcxproj.filters
@@ -180,6 +180,9 @@
Source Files\net
+
+ Source Files\net
+
Source Files\net
diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj
index e9ee136f7..db4763ee7 100644
--- a/etc/visual-studio/libopenthread_k.vcxproj
+++ b/etc/visual-studio/libopenthread_k.vcxproj
@@ -121,6 +121,7 @@
+
diff --git a/etc/visual-studio/libopenthread_k.vcxproj.filters b/etc/visual-studio/libopenthread_k.vcxproj.filters
index 7a245e0e0..536e40f2b 100644
--- a/etc/visual-studio/libopenthread_k.vcxproj.filters
+++ b/etc/visual-studio/libopenthread_k.vcxproj.filters
@@ -180,6 +180,9 @@
Source Files\net
+
+ Source Files\net
+
Source Files\net
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index c5fa42b87..0ca3b2083 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -156,6 +156,7 @@ SOURCES_COMMON = \
net/ip6.cpp \
net/ip6_address.cpp \
net/ip6_filter.cpp \
+ net/ip6_headers.cpp \
net/ip6_mpl.cpp \
net/ip6_routes.cpp \
net/netif.cpp \
diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp
index 04e1f5c0f..844815d0a 100644
--- a/src/core/net/ip6.cpp
+++ b/src/core/net/ip6.cpp
@@ -665,8 +665,7 @@ otError Ip6::SendRaw(Message &aMessage, int8_t aInterfaceId)
Header header;
MessageInfo messageInfo;
- // check aMessage length
- VerifyOrExit(aMessage.Read(0, sizeof(header), &header) == sizeof(header), error = OT_ERROR_DROP);
+ SuccessOrExit(error = header.Init(aMessage));
messageInfo.SetPeerAddr(header.GetSource());
messageInfo.SetSockAddr(header.GetDestination());
@@ -691,7 +690,6 @@ otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceI
otError error = OT_ERROR_NONE;
MessageInfo messageInfo;
Header header;
- uint16_t payloadLength;
bool receive = false;
bool forward = false;
bool tunnel = false;
@@ -708,16 +706,7 @@ otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceI
dump("handle datagram", buf, aMessage.GetLength());
#endif
- // check aMessage length
- VerifyOrExit(aMessage.Read(0, sizeof(header), &header) == sizeof(header), error = OT_ERROR_DROP);
- payloadLength = header.GetPayloadLength();
-
- // check Version
- VerifyOrExit(header.IsVersion6(), error = OT_ERROR_DROP);
-
- // check Payload Length
- VerifyOrExit(sizeof(header) + payloadLength == aMessage.GetLength() &&
- sizeof(header) + payloadLength <= Ip6::kMaxDatagramLength, error = OT_ERROR_DROP);
+ SuccessOrExit(error = header.Init(aMessage));
messageInfo.SetPeerAddr(header.GetSource());
messageInfo.SetSockAddr(header.GetDestination());
diff --git a/src/core/net/ip6_headers.cpp b/src/core/net/ip6_headers.cpp
new file mode 100644
index 000000000..5b087a271
--- /dev/null
+++ b/src/core/net/ip6_headers.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+/**
+ * @file
+ * This file implements IP6 header processing.
+ */
+
+#include
+
+#include "ip6_headers.hpp"
+
+#include "net/ip6.hpp"
+
+namespace ot {
+namespace Ip6 {
+
+otError Header::Init(const Message &aMessage)
+{
+ otError error = OT_ERROR_NONE;
+ uint16_t length;
+
+ // check aMessage length
+ VerifyOrExit(aMessage.Read(0, sizeof(*this), this) == sizeof(*this), error = OT_ERROR_PARSE);
+
+ // check Version
+ VerifyOrExit(IsVersion6(), error = OT_ERROR_PARSE);
+
+ // check Payload Length
+ length = sizeof(*this) + GetPayloadLength();
+ VerifyOrExit(length == aMessage.GetLength() && length <= Ip6::kMaxDatagramLength, error = OT_ERROR_PARSE);
+
+exit:
+ return error;
+}
+
+} // namespace Ip6
+} // namespace ot
diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp
index 3892c3619..b38ccae7e 100644
--- a/src/core/net/ip6_headers.hpp
+++ b/src/core/net/ip6_headers.hpp
@@ -146,6 +146,17 @@ public:
*/
void Init(uint32_t aVersionClassFlow) { mVersionClassFlow.m32[0] = HostSwap32(aVersionClassFlow); }
+ /**
+ * This method reads the IPv6 header from @p aMessage.
+ *
+ * @param[in] aMessage The IPv6 datagram.
+ *
+ * @retval OT_ERROR_NONE Successfully read the IPv6 header.
+ * @retval OT_ERROR_PARSE Malformed IPv6 header.
+ *
+ */
+ otError Init(const Message &aMessage);
+
/**
* This method indicates whether or not the IPv6 Version is set to 6.
*