You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2017/11/14 01:48:27 UTC

[13/25] nifi-minifi-cpp git commit: MINIFICPP-250: Initial implementation fo CapturePacket Processor that uses lipcap.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/IcmpLayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/IcmpLayer.cpp b/thirdparty/pcap++/Packet++/src/IcmpLayer.cpp
new file mode 100644
index 0000000..12bde7b
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/IcmpLayer.cpp
@@ -0,0 +1,721 @@
+#define LOG_MODULE PacketLogModuleIcmpLayer
+
+#include <IcmpLayer.h>
+#include <PayloadLayer.h>
+#include <Packet.h>
+#include <IpUtils.h>
+#include <Logger.h>
+#include <sstream>
+#include <string.h>
+#if defined(WIN32) || defined(WINx64) //for using ntohl, ntohs, etc.
+#include <winsock2.h>
+#elif LINUX
+#include <in.h> //for using ntohl, ntohs, etc.
+#elif MAC_OS_X
+#include <arpa/inet.h> //for using ntohl, ntohs, etc.
+#endif
+
+namespace pcpp
+{
+
+icmp_router_address_structure* icmp_router_advertisement::getRouterAddress(int index)
+{
+	if (index < 0 || index >= header->advertisementCount)
+		return NULL;
+
+	uint8_t* headerAsByteArr = (uint8_t*)header;
+	return (icmp_router_address_structure*)(headerAsByteArr + sizeof(icmp_router_advertisement_hdr) + index*sizeof(icmp_router_address_structure));
+}
+
+void icmp_router_address_structure::setRouterAddress(IPv4Address addr, uint32_t preference)
+{
+	routerAddress = addr.toInt();
+	preferenceLevel = htonl(preference);
+}
+
+IPv4Address icmp_router_address_structure::getAddress()
+{
+	return IPv4Address(routerAddress);
+}
+
+IcmpLayer::IcmpLayer() : Layer()
+{
+	m_DataLen = sizeof(icmphdr);
+	m_Data = new uint8_t[m_DataLen];
+	memset(m_Data, 0, m_DataLen);
+	m_Protocol = ICMP;
+}
+
+IcmpMessageType IcmpLayer::getMessageType()
+{
+	uint8_t type = getIcmpHeader()->type;
+	if (type > 18)
+		return ICMP_UNSUPPORTED;
+
+	return (IcmpMessageType)type;
+}
+
+bool IcmpLayer::isMessageOfType(IcmpMessageType type)
+{
+	return (getMessageType() == type);
+}
+
+bool IcmpLayer::cleanIcmpLayer()
+{
+	// remove all layers after
+
+	if (m_Packet != NULL)
+	{
+		Layer* layerToRemove = this->getNextLayer();
+		while (layerToRemove != NULL)
+		{
+			Layer* temp = layerToRemove->getNextLayer();
+			if (!m_Packet->removeLayer(layerToRemove))
+				return false;
+			layerToRemove = temp;
+		}
+	}
+
+
+	// shorten layer to size of icmphdr
+
+	size_t headerLen = this->getHeaderLen();
+	if (headerLen > sizeof(icmphdr))
+	{
+		if (!this->shortenLayer(sizeof(icmphdr), headerLen - sizeof(icmphdr)))
+			return false;
+	}
+
+	return true;
+}
+
+bool IcmpLayer::setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen)
+{
+	if (!cleanIcmpLayer())
+		return false;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_echo_hdr) - sizeof(icmphdr) + dataLen))
+		return false;
+
+	getIcmpHeader()->type = (uint8_t)echoType;
+
+	icmp_echo_request* header = NULL;
+	if (echoType == ICMP_ECHO_REQUEST)
+		header = getEchoRequestData();
+	else if (echoType == ICMP_ECHO_REPLY)
+		header = (icmp_echo_request*)getEchoReplyData();
+	else
+		return false;
+
+	header->header->code = 0;
+	header->header->checksum = 0;
+	header->header->id = htons(id);
+	header->header->sequence = htons(sequence);
+	header->header->timestamp = timestamp;
+	if (data != NULL && dataLen > 0)
+		memcpy(header->data, data, dataLen);
+
+	return true;
+}
+
+bool IcmpLayer::setIpAndL4Layers(IPv4Layer* ipLayer, Layer* l4Layer)
+{
+	if (m_Packet == NULL)
+	{
+		LOG_ERROR("Cannot set ICMP data that involves IP and L4 layers on a layer not attached to a packet. "
+				"Please add the ICMP layer to a packet and try again");
+		return false;
+	}
+
+	if (ipLayer != NULL && !m_Packet->addLayer(ipLayer))
+	{
+		LOG_ERROR("Couldn't add IP layer to ICMP packet");
+		return false;
+	}
+
+	if (l4Layer != NULL && !m_Packet->addLayer(l4Layer))
+	{
+		LOG_ERROR("Couldn't add L4 layer to ICMP packet");
+		return false;
+	}
+
+	return true;
+}
+
+icmp_echo_request* IcmpLayer::getEchoRequestData()
+{
+	if (!isMessageOfType(ICMP_ECHO_REQUEST))
+		return NULL;
+
+	m_EchoData.header = (icmp_echo_hdr*)m_Data;
+	m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr));
+	m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr);
+
+	return &m_EchoData;
+}
+
+icmp_echo_request* IcmpLayer::setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen)
+{
+	if (setEchoData(ICMP_ECHO_REQUEST, id, sequence, timestamp, data, dataLen))
+		return getEchoRequestData();
+	else
+		return NULL;
+}
+
+icmp_echo_reply* IcmpLayer::getEchoReplyData()
+{
+	if (!isMessageOfType(ICMP_ECHO_REPLY))
+		return NULL;
+
+	m_EchoData.header = (icmp_echo_hdr*)m_Data;
+	m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr));
+	m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr);
+
+	return &m_EchoData;
+}
+
+icmp_echo_reply* IcmpLayer::setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen)
+{
+	if (setEchoData(ICMP_ECHO_REPLY, id, sequence, timestamp, data, dataLen))
+		return getEchoReplyData();
+	else
+		return NULL;
+}
+
+
+icmp_timestamp_request* IcmpLayer::getTimestampRequestData()
+{
+	if (!isMessageOfType(ICMP_TIMESTAMP_REQUEST))
+		return NULL;
+
+	return (icmp_timestamp_request*)m_Data;
+}
+
+icmp_timestamp_request* IcmpLayer::setTimestampRequestData(uint16_t id, uint16_t sequence, timeval originateTimestamp)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_request) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REQUEST;
+
+	icmp_timestamp_request* header = getTimestampRequestData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+	header->originateTimestamp = htonl(originateTimestamp.tv_sec*1000 + originateTimestamp.tv_usec/1000);
+	header->receiveTimestamp = 0;
+	header->transmitTimestamp = 0;
+
+	return header;
+}
+
+icmp_timestamp_reply* IcmpLayer::getTimestampReplyData()
+{
+	if (!isMessageOfType(ICMP_TIMESTAMP_REPLY))
+		return NULL;
+
+	return (icmp_timestamp_reply*)m_Data;
+}
+
+icmp_timestamp_reply* IcmpLayer::setTimestampReplyData(uint16_t id, uint16_t sequence,
+		timeval originateTimestamp, timeval receiveTimestamp, timeval transmitTimestamp)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_reply) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REPLY;
+
+	icmp_timestamp_reply* header = getTimestampReplyData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+	header->originateTimestamp = htonl(originateTimestamp.tv_sec*1000 + originateTimestamp.tv_usec/1000);
+	header->receiveTimestamp = htonl(receiveTimestamp.tv_sec*1000 + receiveTimestamp.tv_usec/1000);
+	header->transmitTimestamp = htonl(transmitTimestamp.tv_sec*1000 + transmitTimestamp.tv_usec/1000);
+
+	return header;
+}
+
+icmp_destination_unreachable* IcmpLayer::getDestUnreachableData()
+{
+	if (!isMessageOfType(ICMP_DEST_UNREACHABLE))
+		return NULL;
+
+	return (icmp_destination_unreachable*)m_Data;
+}
+
+icmp_destination_unreachable* IcmpLayer::setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, IPv4Layer* ipHeader, Layer* l4Header)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_destination_unreachable) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_DEST_UNREACHABLE;
+
+	icmp_destination_unreachable* header = getDestUnreachableData();
+	header->code = code;
+	header->nextHopMTU = htons(nextHopMTU);
+	header->unused = 0;
+
+	if (!setIpAndL4Layers(ipHeader, l4Header))
+		return NULL;
+
+	return header;
+}
+
+icmp_source_quench* IcmpLayer::getSourceQuenchdata()
+{
+	if (!isMessageOfType(ICMP_SOURCE_QUENCH))
+		return NULL;
+
+	return (icmp_source_quench*)m_Data;
+
+}
+
+icmp_source_quench* IcmpLayer::setSourceQuenchdata(IPv4Layer* ipHeader, Layer* l4Header)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_source_quench) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_SOURCE_QUENCH;
+
+	icmp_source_quench* header = getSourceQuenchdata();
+	header->unused = 0;
+
+	if (!setIpAndL4Layers(ipHeader, l4Header))
+		return NULL;
+
+	return header;
+}
+
+icmp_redirect* IcmpLayer::getRedirectData()
+{
+	if (!isMessageOfType(ICMP_REDIRECT))
+		return NULL;
+
+	return (icmp_redirect*)m_Data;
+}
+
+icmp_redirect* IcmpLayer::setRedirectData(uint8_t code, IPv4Address gatewayAddress, IPv4Layer* ipHeader, Layer* l4Header)
+{
+	if (code > 3)
+	{
+		LOG_ERROR("Unknown code %d for ICMP redirect data", (int)code);
+		return NULL;
+	}
+
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_redirect) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_REDIRECT;
+
+	icmp_redirect* header = getRedirectData();
+	header->code = code;
+	header->gatewayAddress = gatewayAddress.toInt();
+
+	if (!setIpAndL4Layers(ipHeader, l4Header))
+		return NULL;
+
+	return header;
+}
+
+icmp_router_advertisement* IcmpLayer::getRouterAdvertisementData()
+{
+	if (!isMessageOfType(ICMP_ROUTER_ADV))
+		return NULL;
+
+	m_RouterAdvData.header = (icmp_router_advertisement_hdr*)m_Data;
+
+	return &m_RouterAdvData;
+}
+
+icmp_router_advertisement* IcmpLayer::setRouterAdvertisementData(uint8_t code, uint16_t lifetimeInSeconds, const std::vector<icmp_router_address_structure>& routerAddresses)
+{
+	if (code != 0 && code != 16)
+	{
+		LOG_ERROR("Unknown code %d for ICMP router advertisement data (only codes 0 and 16 are legal)", (int)code);
+		return NULL;
+	}
+
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_router_advertisement_hdr) + (routerAddresses.size()*sizeof(icmp_router_address_structure)) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_ADV;
+
+	icmp_router_advertisement* header = getRouterAdvertisementData();
+	header->header->code = code;
+	header->header->lifetime = htons(lifetimeInSeconds);
+	header->header->advertisementCount = (uint8_t)routerAddresses.size();
+	header->header->addressEntrySize = 2;
+
+	icmp_router_address_structure* curPos = (icmp_router_address_structure*)((uint8_t*)header->header + sizeof(icmp_router_advertisement_hdr));
+	for (std::vector<icmp_router_address_structure>::const_iterator iter = routerAddresses.begin(); iter != routerAddresses.end(); iter++)
+	{
+		curPos->routerAddress = iter->routerAddress;
+		curPos->preferenceLevel = iter->preferenceLevel;
+		curPos += 1;
+	}
+
+	return header;
+}
+
+icmp_router_solicitation* IcmpLayer::getRouterSolicitationData()
+{
+	if (!isMessageOfType(ICMP_ROUTER_SOL))
+		return NULL;
+
+	return (icmp_router_solicitation*)m_Data;
+}
+
+icmp_router_solicitation* IcmpLayer::setRouterSolicitationData()
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_SOL;
+
+	icmp_router_solicitation* header = getRouterSolicitationData();
+	header->code = 0;
+
+	return header;
+}
+
+icmp_time_exceeded* IcmpLayer::getTimeExceededData()
+{
+	if (!isMessageOfType(ICMP_TIME_EXCEEDED))
+		return NULL;
+
+	return (icmp_time_exceeded*)m_Data;
+}
+
+icmp_time_exceeded* IcmpLayer::setTimeExceededData(uint8_t code, IPv4Layer* ipHeader, Layer* l4Header)
+{
+	if (code > 1)
+	{
+		LOG_ERROR("Unknown code %d for ICMP time exceeded data", (int)code);
+		return NULL;
+	}
+
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_time_exceeded) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_TIME_EXCEEDED;
+
+	icmp_time_exceeded* header = getTimeExceededData();
+	header->code = code;
+	header->unused = 0;
+
+	if (!setIpAndL4Layers(ipHeader, l4Header))
+		return NULL;
+
+	return header;
+}
+
+icmp_param_problem* IcmpLayer::getParamProblemData()
+{
+	if (!isMessageOfType(ICMP_PARAM_PROBLEM))
+		return NULL;
+
+	return (icmp_param_problem*)m_Data;
+}
+
+icmp_param_problem* IcmpLayer::setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, Layer* l4Header)
+{
+	if (code > 2)
+	{
+		LOG_ERROR("Unknown code %d for ICMP parameter problem data", (int)code);
+		return NULL;
+	}
+
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_param_problem) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_PARAM_PROBLEM;
+
+	icmp_param_problem* header = getParamProblemData();
+	header->code = code;
+	header->unused1 = 0;
+	header->unused2 = 0;
+	header->pointer = errorOctetPointer;
+
+	if (!setIpAndL4Layers(ipHeader, l4Header))
+		return NULL;
+
+	return header;
+}
+
+icmp_address_mask_request* IcmpLayer::getAddressMaskRequestData()
+{
+	if (!isMessageOfType(ICMP_ADDRESS_MASK_REQUEST))
+		return NULL;
+
+	return (icmp_address_mask_request*)m_Data;
+}
+
+icmp_address_mask_request* IcmpLayer::setAddressMaskRequestData(uint16_t id, uint16_t sequence, IPv4Address mask)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_request) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REQUEST;
+
+	icmp_address_mask_request* header = getAddressMaskRequestData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+	header->addressMask = mask.toInt();
+
+	return header;
+}
+
+icmp_address_mask_reply* IcmpLayer::getAddressMaskReplyData()
+{
+	if (!isMessageOfType(ICMP_ADDRESS_MASK_REPLY))
+		return NULL;
+
+	return (icmp_address_mask_reply*)m_Data;
+}
+
+icmp_address_mask_reply* IcmpLayer::setAddressMaskReplyData(uint16_t id, uint16_t sequence, IPv4Address mask)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_reply) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REPLY;
+
+	icmp_address_mask_reply* header = getAddressMaskReplyData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+	header->addressMask = htonl(mask.toInt());
+
+	return header;
+}
+
+icmp_info_request* IcmpLayer::getInfoRequestData()
+{
+	if (!isMessageOfType(ICMP_INFO_REQUEST))
+		return NULL;
+
+	return (icmp_info_request*)m_Data;
+}
+
+icmp_info_request* IcmpLayer::setInfoRequestData(uint16_t id, uint16_t sequence)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_info_request) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_INFO_REQUEST;
+
+	icmp_info_request* header = getInfoRequestData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+
+	return header;
+}
+
+icmp_info_reply* IcmpLayer::getInfoReplyData()
+{
+	if (!isMessageOfType(ICMP_INFO_REPLY))
+		return NULL;
+
+	return (icmp_info_reply*)m_Data;
+}
+
+icmp_info_reply* IcmpLayer::setInfoReplyData(uint16_t id, uint16_t sequence)
+{
+	if (!cleanIcmpLayer())
+		return NULL;
+
+	if (!this->extendLayer(m_DataLen, sizeof(icmp_info_reply) - sizeof(icmphdr)))
+		return NULL;
+
+	getIcmpHeader()->type = (uint8_t)ICMP_INFO_REPLY;
+
+	icmp_info_reply* header = getInfoReplyData();
+	header->code = 0;
+	header->id = htons(id);
+	header->sequence = htons(sequence);
+
+	return header;
+}
+
+
+void IcmpLayer::parseNextLayer()
+{
+	IcmpMessageType type = getMessageType();
+	size_t headerLen = 0;
+
+	switch (type)
+	{
+	case ICMP_DEST_UNREACHABLE:
+	case ICMP_SOURCE_QUENCH:
+	case ICMP_TIME_EXCEEDED:
+	case ICMP_REDIRECT:
+	case ICMP_PARAM_PROBLEM:
+		headerLen = getHeaderLen();
+		if (m_DataLen - headerLen >= sizeof(iphdr))
+			m_NextLayer = new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
+		return;
+	default:
+		headerLen = getHeaderLen();
+		if (m_DataLen > headerLen)
+			m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
+		return;
+	}
+}
+
+size_t IcmpLayer::getHeaderLen()
+{
+	IcmpMessageType type = getMessageType();
+	size_t routerAdvSize = 0;
+	switch (type)
+	{
+	case ICMP_ECHO_REQUEST:
+	case ICMP_ECHO_REPLY:
+		return m_DataLen;
+	case ICMP_TIMESTAMP_REQUEST:
+	case ICMP_TIMESTAMP_REPLY:
+		return sizeof(icmp_timestamp_request);
+	case ICMP_ROUTER_SOL:
+	case ICMP_INFO_REQUEST:
+	case ICMP_INFO_REPLY:
+	case ICMP_UNSUPPORTED:
+		return sizeof(icmphdr);
+	case ICMP_ADDRESS_MASK_REPLY:
+	case ICMP_ADDRESS_MASK_REQUEST:
+		return sizeof(icmp_address_mask_request);
+	case ICMP_DEST_UNREACHABLE:
+		return sizeof(icmp_destination_unreachable);
+	case ICMP_REDIRECT:
+		return sizeof(icmp_redirect);
+	case ICMP_TIME_EXCEEDED:
+	case ICMP_SOURCE_QUENCH:
+		return sizeof(icmp_time_exceeded);
+	case ICMP_PARAM_PROBLEM:
+		return sizeof(icmp_param_problem);
+	case ICMP_ROUTER_ADV:
+		routerAdvSize = sizeof(icmp_router_advertisement_hdr) + (getRouterAdvertisementData()->header->advertisementCount*sizeof(icmp_router_address_structure));
+		return routerAdvSize;
+	default:
+		return sizeof(icmphdr);
+	}
+}
+
+void IcmpLayer::computeCalculateFields()
+{
+	// calculate checksum
+	getIcmpHeader()->checksum = 0;
+
+	size_t icmpLen = 0;
+	Layer* curLayer = this;
+	while (curLayer != NULL)
+	{
+		icmpLen += curLayer->getHeaderLen();
+		curLayer = curLayer->getNextLayer();
+	}
+
+	ScalarBuffer<uint16_t> buffer;
+	buffer.buffer = (uint16_t*)getIcmpHeader();
+	buffer.len = icmpLen;
+	size_t checksum = compute_checksum(&buffer, 1);
+
+	getIcmpHeader()->checksum = htons(checksum);
+}
+
+std::string IcmpLayer::toString()
+{
+	std::string messageTypeAsString;
+	IcmpMessageType type = getMessageType();
+	switch (type)
+	{
+	case ICMP_ECHO_REPLY:
+		messageTypeAsString = "Echo (ping) reply";
+		break;
+	case ICMP_DEST_UNREACHABLE:
+		messageTypeAsString = "Destination unreachable";
+		break;
+	case ICMP_SOURCE_QUENCH:
+		messageTypeAsString = "Source quench (flow control)";
+		break;
+	case ICMP_REDIRECT:
+		messageTypeAsString = "Redirect";
+		break;
+	case ICMP_ECHO_REQUEST:
+		messageTypeAsString = "Echo (ping) request";
+		break;
+	case ICMP_ROUTER_ADV:
+		messageTypeAsString = "Router advertisement";
+		break;
+	case ICMP_ROUTER_SOL:
+		messageTypeAsString = "Router solicitation";
+		break;
+	case ICMP_TIME_EXCEEDED:
+		messageTypeAsString = "Time-to-live exceeded";
+		break;
+	case ICMP_PARAM_PROBLEM:
+		messageTypeAsString = "Parameter problem: bad IP header";
+		break;
+	case ICMP_TIMESTAMP_REQUEST:
+		messageTypeAsString = "Timestamp request";
+		break;
+	case ICMP_TIMESTAMP_REPLY:
+		messageTypeAsString = "Timestamp reply";
+		break;
+	case ICMP_INFO_REQUEST:
+		messageTypeAsString = "Information request";
+		break;
+	case ICMP_INFO_REPLY:
+		messageTypeAsString = "Information reply";
+		break;
+	case ICMP_ADDRESS_MASK_REQUEST:
+		messageTypeAsString = "Address mask request";
+		break;
+	case ICMP_ADDRESS_MASK_REPLY:
+		messageTypeAsString = "Address mask reply";
+		break;
+	default:
+		messageTypeAsString = "Unknown";
+		break;
+	}
+
+	std::ostringstream typeStream;
+	typeStream << (int)getIcmpHeader()->type;
+
+	return "ICMP Layer, " + messageTypeAsString + " (type: " + typeStream.str() + ")";
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/IgmpLayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/IgmpLayer.cpp b/thirdparty/pcap++/Packet++/src/IgmpLayer.cpp
new file mode 100644
index 0000000..c4dab29
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/IgmpLayer.cpp
@@ -0,0 +1,600 @@
+#define LOG_MODULE PacketLogModuleIgmpLayer
+
+#include <IgmpLayer.h>
+#include <IpUtils.h>
+#include <Logger.h>
+#include <string.h>
+#ifdef WIN32 //for using ntohl, ntohs, etc.
+#include <winsock2.h>
+#elif LINUX
+#include <in.h> //for using ntohl, ntohs, etc.
+#elif MAC_OS_X
+#include <arpa/inet.h> //for using ntohl, ntohs, etc.
+#endif
+
+namespace pcpp
+{
+
+/*************
+ * IgmpLayer
+ *************/
+
+IgmpLayer::IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer)
+{
+	m_DataLen = getHeaderSizeByVerAndType(igmpVer, type);
+	m_Data = new uint8_t[m_DataLen];
+	memset(m_Data, 0, m_DataLen);
+	m_Protocol = igmpVer;
+
+	setType(type);
+	if (groupAddr != IPv4Address::Zero)
+		setGroupAddress(groupAddr);
+
+	getIgmpHeader()->maxResponseTime = maxResponseTime;
+}
+
+void IgmpLayer::setGroupAddress(const IPv4Address& groupAddr)
+{
+	igmp_header* hdr = getIgmpHeader();
+	hdr->groupAddress = groupAddr.toInt();
+}
+
+IgmpType IgmpLayer::getType()
+{
+	uint8_t type = getIgmpHeader()->type;
+	if (type < (uint8_t)IgmpType_MembershipQuery ||
+			(type > (uint8_t)IgmpType_LeaveGroup && type < (uint8_t)IgmpType_MulticastTracerouteResponse) ||
+			(type > (uint8_t)IgmpType_MulticastTraceroute && type < (uint8_t)IgmpType_MembershipReportV3) ||
+			(type > (uint8_t)IgmpType_MembershipReportV3 && type < (uint8_t)IgmpType_MulticastRouterAdvertisement) ||
+			type > IgmpType_MulticastRouterTermination)
+		return IgmpType_Unknown;
+
+	return (IgmpType)type;
+}
+
+void IgmpLayer::setType(IgmpType type)
+{
+	if (type == IgmpType_Unknown)
+		return;
+
+	igmp_header* hdr = getIgmpHeader();
+	hdr->type = type;
+}
+
+ProtocolType IgmpLayer::getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery)
+{
+	isQuery = false;
+
+	if (dataLen < 8 || data == NULL)
+		return UnknownProtocol;
+
+	switch ((int)data[0])
+	{
+	case IgmpType_MembershipReportV2:
+	case IgmpType_LeaveGroup:
+		return IGMPv2;
+	case IgmpType_MembershipReportV1:
+		return IGMPv1;
+	case IgmpType_MembershipReportV3:
+		return IGMPv3;
+	case IgmpType_MembershipQuery:
+	{
+		isQuery = true;
+
+		if (dataLen >= sizeof(igmpv3_query_header))
+			return IGMPv3;
+
+		if (data[1] == 0)
+			return IGMPv1;
+		else
+			return IGMPv2;
+	}
+	default:
+		return UnknownProtocol;
+	}
+}
+
+uint16_t IgmpLayer::calculateChecksum()
+{
+	ScalarBuffer<uint16_t> buffer;
+	buffer.buffer = (uint16_t*)getIgmpHeader();
+	buffer.len = getHeaderLen();
+	return compute_checksum(&buffer, 1);
+}
+
+size_t IgmpLayer::getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType)
+{
+	if (igmpVer == IGMPv1 || igmpVer == IGMPv2)
+		return sizeof(igmp_header);
+
+	if (igmpVer == IGMPv3)
+	{
+		if (igmpType == IgmpType_MembershipQuery)
+			return sizeof(igmpv3_query_header);
+		else if (igmpType == IgmpType_MembershipReportV3)
+			return sizeof(igmpv3_report_header);
+	}
+
+	return 0;
+}
+
+std::string IgmpLayer::toString()
+{
+	std::string igmpVer = "";
+	switch (getProtocol())
+	{
+	case IGMPv1:
+		igmpVer = "1";
+		break;
+	case IGMPv2:
+		igmpVer = "2";
+		break;
+	default:
+		igmpVer = "3";
+	}
+
+	std::string msgType;
+
+	switch (getType())
+	{
+	case IgmpType_MembershipQuery:
+		msgType = "Membership Query";
+		break;
+	case IgmpType_MembershipReportV1:
+		msgType = "Membership Report";
+		break;
+	case IgmpType_DVMRP:
+		msgType = "DVMRP";
+		break;
+	case IgmpType_P1Mv1:
+		msgType = "PIMv1";
+		break;
+	case IgmpType_CiscoTrace:
+		msgType = "Cisco Trace";
+		break;
+	case IgmpType_MembershipReportV2:
+		msgType = "Membership Report";
+		break;
+	case IgmpType_LeaveGroup:
+		msgType = "Leave Group";
+		break;
+	case IgmpType_MulticastTracerouteResponse:
+		msgType = "Multicast Traceroute Response";
+		break;
+	case IgmpType_MulticastTraceroute:
+		msgType = "Multicast Traceroute";
+		break;
+	case IgmpType_MembershipReportV3:
+		msgType = "Membership Report";
+		break;
+	case IgmpType_MulticastRouterAdvertisement:
+		msgType = "Multicast Router Advertisement";
+		break;
+	case IgmpType_MulticastRouterSolicitation:
+		msgType = "Multicast Router Solicitation";
+		break;
+	case IgmpType_MulticastRouterTermination:
+		msgType = "Multicast Router Termination";
+		break;
+	default:
+		msgType = "Unknown";
+		break;
+	}
+
+	std::string result = "IGMPv" + igmpVer + " Layer, " + msgType + " message";
+	return result;
+}
+
+
+
+
+/*************
+ * IgmpV1Layer
+ *************/
+
+IgmpV1Layer::IgmpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) :
+		IgmpLayer(data, dataLen, prevLayer, packet, IGMPv1)
+{
+}
+
+IgmpV1Layer::IgmpV1Layer(IgmpType type, const IPv4Address& groupAddr) :
+		IgmpLayer(type, groupAddr, 0, IGMPv1)
+{
+}
+
+void IgmpV1Layer::computeCalculateFields()
+{
+	igmp_header* hdr = getIgmpHeader();
+	hdr->checksum = 0;
+	hdr->checksum = htons(calculateChecksum());
+	hdr->maxResponseTime = 0;
+}
+
+
+
+
+
+/*************
+ * IgmpV2Layer
+ *************/
+
+IgmpV2Layer::IgmpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) :
+		IgmpLayer(data, dataLen, prevLayer, packet, IGMPv2)
+{
+}
+
+IgmpV2Layer::IgmpV2Layer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime) :
+		IgmpLayer(type, groupAddr, maxResponseTime, IGMPv2)
+{
+}
+
+void IgmpV2Layer::computeCalculateFields()
+{
+	igmp_header* hdr = getIgmpHeader();
+	hdr->checksum = 0;
+	hdr->checksum = htons(calculateChecksum());
+}
+
+
+
+
+
+/******************
+ * IgmpV3QueryLayer
+ ******************/
+
+
+IgmpV3QueryLayer::IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) :
+		IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3)
+{
+}
+
+IgmpV3QueryLayer::IgmpV3QueryLayer(const IPv4Address& multicastAddr, uint8_t maxResponseTime, uint8_t s_qrv) :
+		IgmpLayer(IgmpType_MembershipQuery, multicastAddr, maxResponseTime, IGMPv3)
+{
+	getIgmpV3QueryHeader()->s_qrv = s_qrv;
+}
+
+uint16_t IgmpV3QueryLayer::getSourceAddressCount()
+{
+	return ntohs(getIgmpV3QueryHeader()->numOfSources);
+}
+
+IPv4Address IgmpV3QueryLayer::getSourceAddressAtIndex(int index)
+{
+	uint16_t numOfSources = getSourceAddressCount();
+	if (index < 0 || index >= numOfSources)
+		return IPv4Address::Zero;
+
+	// verify numOfRecords is a reasonable number that points to data within the packet
+	int ptrOffset = index * sizeof(uint32_t) + sizeof(igmpv3_query_header);
+	if (ptrOffset + sizeof(uint32_t) > getDataLen())
+		return IPv4Address::Zero;
+
+	uint8_t* ptr = m_Data + ptrOffset;
+	return IPv4Address(*(uint32_t*)ptr);
+}
+
+size_t IgmpV3QueryLayer::getHeaderLen()
+{
+	uint16_t numOfSources = getSourceAddressCount();
+
+	int headerLen = numOfSources * sizeof(uint32_t) + sizeof(igmpv3_query_header);
+
+	// verify numOfRecords is a reasonable number that points to data within the packet
+	if ((size_t)headerLen > getDataLen())
+		return getDataLen();
+
+	return (size_t)headerLen;
+}
+
+void IgmpV3QueryLayer::computeCalculateFields()
+{
+	igmpv3_query_header* hdr = getIgmpV3QueryHeader();
+	hdr->checksum = 0;
+	hdr->checksum = htons(calculateChecksum());
+}
+
+bool IgmpV3QueryLayer::addSourceAddress(const IPv4Address& addr)
+{
+	return addSourceAddressAtIndex(addr, getSourceAddressCount());
+}
+
+bool IgmpV3QueryLayer::addSourceAddressAtIndex(const IPv4Address& addr, int index)
+{
+	uint16_t sourceAddrCount = getSourceAddressCount();
+
+	if (index < 0 || index > (int)sourceAddrCount)
+	{
+		LOG_ERROR("Cannot add source address at index %d, index is out of bounds", index);
+		return false;
+	}
+
+	size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t);
+	if (offset > getHeaderLen())
+	{
+		LOG_ERROR("Cannot add source address at index %d, index is out of packet bounds", index);
+		return false;
+	}
+
+	if (!extendLayer(offset, sizeof(uint32_t)))
+	{
+		LOG_ERROR("Cannot add source address at index %d, didn't manage to extend layer", index);
+		return false;
+	}
+
+	uint32_t addrAsInt = addr.toInt();
+	memcpy(m_Data + offset, &addrAsInt, sizeof(uint32_t));
+
+	getIgmpV3QueryHeader()->numOfSources = htons(sourceAddrCount+1);
+
+	return true;
+}
+
+bool IgmpV3QueryLayer::removeSourceAddressAtIndex(int index)
+{
+	uint16_t sourceAddrCount = getSourceAddressCount();
+
+	if (index < 0 || index > (int)sourceAddrCount-1)
+	{
+		LOG_ERROR("Cannot remove source address at index %d, index is out of bounds", index);
+		return false;
+	}
+
+	size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t);
+	if (offset >= getHeaderLen())
+	{
+		LOG_ERROR("Cannot remove source address at index %d, index is out of packet bounds", index);
+		return false;
+	}
+
+	if (!shortenLayer(offset, sizeof(uint32_t)))
+	{
+		LOG_ERROR("Cannot remove source address at index %d, didn't manage to shorten layer", index);
+		return false;
+	}
+
+	getIgmpV3QueryHeader()->numOfSources = htons(sourceAddrCount-1);
+
+	return true;
+}
+
+bool IgmpV3QueryLayer::removeAllSourceAddresses()
+{
+	size_t offset = sizeof(igmpv3_query_header);
+	size_t numOfBytesToShorted = getHeaderLen() - offset;
+
+	if (!shortenLayer(offset, numOfBytesToShorted))
+	{
+		LOG_ERROR("Cannot remove all source addresses, didn't manage to shorten layer");
+		return false;
+	}
+
+	getIgmpV3QueryHeader()->numOfSources = 0;
+
+	return true;
+}
+
+
+
+
+
+/*******************
+ * IgmpV3ReportLayer
+ *******************/
+
+IgmpV3ReportLayer::IgmpV3ReportLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) :
+		IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3)
+{
+}
+
+IgmpV3ReportLayer::IgmpV3ReportLayer() :
+		IgmpLayer(IgmpType_MembershipReportV3, IPv4Address::Zero, 0, IGMPv3)
+{
+}
+
+uint16_t IgmpV3ReportLayer::getGroupRecordCount()
+{
+	return ntohs(getReportHeader()->numOfGroupRecords);
+
+}
+
+igmpv3_group_record* IgmpV3ReportLayer::getFirstGroupRecord()
+{
+	// check if there are group records at all
+	if (getHeaderLen() <= sizeof(igmpv3_report_header))
+		return NULL;
+
+	uint8_t* curGroupPtr = m_Data + sizeof(igmpv3_report_header);
+	return (igmpv3_group_record*)curGroupPtr;
+}
+
+igmpv3_group_record* IgmpV3ReportLayer::getNextGroupRecord(igmpv3_group_record* groupRecord)
+{
+	if (groupRecord == NULL)
+		return NULL;
+
+	// prev group was the last group
+	if ((uint8_t*)groupRecord + groupRecord->getRecordLen() - m_Data >= (int)getHeaderLen())
+		return NULL;
+
+	igmpv3_group_record* nextGroup = (igmpv3_group_record*)((uint8_t*)groupRecord + groupRecord->getRecordLen());
+
+	return nextGroup;
+}
+
+size_t IgmpV3ReportLayer::getHeaderLen()
+{
+	return m_DataLen;
+}
+
+void IgmpV3ReportLayer::computeCalculateFields()
+{
+	igmpv3_report_header* hdr = getReportHeader();
+	hdr->checksum = 0;
+	hdr->checksum = htons(calculateChecksum());
+}
+
+igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses, int offset)
+{
+	if (offset > (int)getHeaderLen())
+	{
+		LOG_ERROR("Cannot add group record, offset is out of layer bounds");
+		return NULL;
+	}
+
+	size_t groupRecordSize = sizeof(igmpv3_group_record) + sizeof(uint32_t)*sourceAddresses.size();
+
+	if (!extendLayer(offset, groupRecordSize))
+	{
+		LOG_ERROR("Cannot add group record, cannot extend layer");
+		return NULL;
+	}
+
+	uint8_t* groupRecordBuffer = new uint8_t[groupRecordSize];
+	memset(groupRecordBuffer, 0, groupRecordSize);
+	igmpv3_group_record* newGroupRecord = (igmpv3_group_record*)groupRecordBuffer;
+	newGroupRecord->multicastAddress = multicastAddress.toInt();
+	newGroupRecord->recordType = recordType;
+	newGroupRecord->auxDataLen = 0;
+	newGroupRecord->numOfSources = htons(sourceAddresses.size());
+
+	int srcAddrOffset = 0;
+	for (std::vector<IPv4Address>::const_iterator iter = sourceAddresses.begin(); iter != sourceAddresses.end(); iter++)
+	{
+		uint32_t addrAsInt = iter->toInt();
+		memcpy(newGroupRecord->sourceAddresses + srcAddrOffset, &addrAsInt, sizeof(uint32_t));
+		srcAddrOffset += sizeof(uint32_t);
+	}
+
+	memcpy(m_Data + offset, groupRecordBuffer, groupRecordSize);
+
+	delete[] groupRecordBuffer;
+
+	getReportHeader()->numOfGroupRecords = htons(getGroupRecordCount() + 1);
+
+	return (igmpv3_group_record*)(m_Data + offset);
+}
+
+igmpv3_group_record* IgmpV3ReportLayer::addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses)
+{
+	return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)getHeaderLen());
+}
+
+igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAtIndex(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector<IPv4Address>& sourceAddresses, int index)
+{
+	int groupCnt = (int)getGroupRecordCount();
+
+	if (index < 0 || index > groupCnt)
+	{
+		LOG_ERROR("Cannot add group record, index %d out of bounds", index);
+		return NULL;
+	}
+
+	size_t offset = sizeof(igmpv3_report_header);
+
+	igmpv3_group_record* curRecord = getFirstGroupRecord();
+	for (int i = 0; i < index; i++)
+	{
+		if (curRecord == NULL)
+		{
+			LOG_ERROR("Cannot add group record, cannot find group record at index %d", i);
+			return NULL;
+		}
+
+		offset += curRecord->getRecordLen();
+		curRecord = getNextGroupRecord(curRecord);
+	}
+
+	return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)offset);
+}
+
+bool IgmpV3ReportLayer::removeGroupRecordAtIndex(int index)
+{
+	int groupCnt = (int)getGroupRecordCount();
+
+	if (index < 0 || index >= groupCnt)
+	{
+		LOG_ERROR("Cannot remove group record, index %d is out of bounds", index);
+		return false;
+	}
+
+	size_t offset = sizeof(igmpv3_report_header);
+
+	igmpv3_group_record* curRecord = getFirstGroupRecord();
+	for (int i = 0; i < index; i++)
+	{
+		if (curRecord == NULL)
+		{
+			LOG_ERROR("Cannot remove group record at index %d, cannot find group record at index %d", index, i);
+			return false;
+		}
+
+		offset += curRecord->getRecordLen();
+		curRecord = getNextGroupRecord(curRecord);
+	}
+
+	if (!shortenLayer((int)offset, curRecord->getRecordLen()))
+	{
+		LOG_ERROR("Cannot remove group record at index %d, cannot shorted layer", index);
+		return false;
+	}
+
+	getReportHeader()->numOfGroupRecords = htons(groupCnt-1);
+
+	return true;
+}
+
+bool IgmpV3ReportLayer::removeAllGroupRecords()
+{
+	int offset = (int)sizeof(igmpv3_report_header);
+
+	if (!shortenLayer(offset, getHeaderLen()-offset))
+	{
+		LOG_ERROR("Cannot remove all group records, cannot shorted layer");
+		return false;
+	}
+
+	getReportHeader()->numOfGroupRecords = 0;
+	return true;
+}
+
+
+
+
+
+
+/*********************
+ * igmpv3_group_record
+ *********************/
+
+IPv4Address igmpv3_group_record::getMulticastAddress()
+{
+	return IPv4Address(multicastAddress);
+}
+
+uint16_t igmpv3_group_record::getSourceAdressCount()
+{
+	return ntohs(numOfSources);
+}
+
+IPv4Address igmpv3_group_record::getSoruceAddressAtIndex(int index)
+{
+	uint16_t numOfRecords = getSourceAdressCount();
+	if (index < 0 || index >= numOfRecords)
+		return IPv4Address::Zero;
+
+	int offset = index * sizeof(uint32_t);
+	uint8_t* ptr = sourceAddresses + offset;
+	return IPv4Address(*(uint32_t*)ptr);
+}
+
+size_t igmpv3_group_record::getRecordLen()
+{
+	uint16_t numOfRecords = getSourceAdressCount();
+
+	int headerLen = numOfRecords * sizeof(uint32_t) + sizeof(igmpv3_group_record);
+	return (size_t)headerLen;
+}
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/Layer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/Layer.cpp b/thirdparty/pcap++/Packet++/src/Layer.cpp
new file mode 100644
index 0000000..f6ca822
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/Layer.cpp
@@ -0,0 +1,103 @@
+#define LOG_MODULE PacketLogModuleLayer
+
+#include <Layer.h>
+#include <string.h>
+#include "Logger.h"
+#include "Packet.h"
+
+namespace pcpp
+{
+
+Layer::~Layer()
+{
+	if (!isAllocatedToPacket())
+		delete [] m_Data;
+}
+
+Layer::Layer(const Layer& other) : m_DataLen(other.m_DataLen), m_Packet(NULL), m_Protocol(other.m_Protocol), m_NextLayer(NULL), m_PrevLayer(NULL)
+{
+	m_Data = new uint8_t[other.m_DataLen];
+	memcpy(m_Data, other.m_Data, other.m_DataLen);
+}
+
+Layer& Layer::operator=(const Layer& other)
+{
+	if (this == &other)
+		return *this;
+
+	if (m_Data != NULL)
+		delete [] m_Data;
+
+	m_DataLen = other.m_DataLen;
+	m_Packet = NULL;
+	m_Protocol = other.m_Protocol;
+	m_NextLayer = NULL;
+	m_PrevLayer = NULL;
+	m_Data = new uint8_t[other.m_DataLen];
+	memcpy(m_Data, other.m_Data, other.m_DataLen);
+
+	return *this;
+}
+
+void Layer::copyData(uint8_t* toArr)
+{
+	memcpy(toArr, m_Data, m_DataLen);
+}
+
+bool Layer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend)
+{
+	if (m_Data == NULL)
+	{
+		LOG_ERROR("Layer's data is NULL");
+		return false;
+	}
+
+	if (m_Packet == NULL)
+	{
+		if ((size_t)offsetInLayer > m_DataLen)
+		{
+			LOG_ERROR("Requested offset is larger than data length");
+			return false;
+		}
+
+		uint8_t* newData = new uint8_t[m_DataLen + numOfBytesToExtend];
+		memcpy(newData, m_Data, offsetInLayer);
+		memcpy(newData + offsetInLayer + numOfBytesToExtend, m_Data + offsetInLayer, m_DataLen - offsetInLayer);
+		delete [] m_Data;
+		m_Data = newData;
+		m_DataLen += numOfBytesToExtend;
+		return true;
+	}
+
+	return m_Packet->extendLayer(this, offsetInLayer, numOfBytesToExtend);
+}
+
+bool Layer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten)
+{
+	if (m_Data == NULL)
+	{
+		LOG_ERROR("Layer's data is NULL");
+		return false;
+	}
+
+	if (m_Packet == NULL)
+	{
+		if ((size_t)offsetInLayer >= m_DataLen)
+		{
+			LOG_ERROR("Requested offset is larget than data length");
+			return false;
+		}
+
+		uint8_t* newData = new uint8_t[m_DataLen - numOfBytesToShorten];
+		memcpy(newData, m_Data, offsetInLayer);
+		memcpy(newData + offsetInLayer, m_Data + offsetInLayer + numOfBytesToShorten, m_DataLen - offsetInLayer - numOfBytesToShorten);
+		delete [] m_Data;
+		m_Data = newData;
+		m_DataLen -= numOfBytesToShorten;
+		return true;
+	}
+
+	return m_Packet->shortenLayer(this, offsetInLayer, numOfBytesToShorten);
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/MplsLayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/MplsLayer.cpp b/thirdparty/pcap++/Packet++/src/MplsLayer.cpp
new file mode 100644
index 0000000..eb0c5ac
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/MplsLayer.cpp
@@ -0,0 +1,151 @@
+#define LOG_MODULE PacketLogModuleMplsLayer
+
+#include <MplsLayer.h>
+#include <IPv4Layer.h>
+#include <IPv6Layer.h>
+#include <PayloadLayer.h>
+#include <Logger.h>
+#include <string.h>
+#include <sstream>
+#if defined(WIN32) || defined(WINx64)
+#include <winsock2.h>
+#elif LINUX
+#include <in.h>
+#endif
+
+namespace pcpp
+{
+
+MplsLayer::MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t expermentalUseValue, bool bottomOfStack)
+{
+	m_DataLen = sizeof(mpls_header);
+	m_Data = new uint8_t[m_DataLen];
+	memset(m_Data, 0, m_DataLen);
+	m_Protocol = MPLS;
+
+	setMplsLabel(mplsLabel);
+	setTTL(ttl);
+	setExperimentalUseValue(expermentalUseValue);
+	setBottomOfStack(bottomOfStack);
+}
+
+bool MplsLayer::isBottomOfStack()
+{
+	return (getMplsHeader()->misc & 0x01);
+}
+
+void MplsLayer::setBottomOfStack(bool val)
+{
+	if (!val)
+		getMplsHeader()->misc &= 0xFE;
+	else
+		getMplsHeader()->misc |= 0xFF;
+}
+
+uint8_t MplsLayer::getExperimentalUseValue()
+{
+	return ((getMplsHeader()->misc & 0x0E) >> 1);
+}
+
+bool MplsLayer::setExperimentalUseValue(uint8_t val)
+{
+	// exp value is only 3 bits
+	if (val > 7)
+	{
+		LOG_ERROR("Set ExperimentalUse value got an illegal value: %d. Value must be lower than 8", val);
+		return false;
+	}
+
+	mpls_header* hdr = getMplsHeader();
+
+	// clear the 3 exp bits
+	hdr->misc &= 0xF1;
+
+	// move the 3 bits to their place
+	val = val << 1;
+
+	hdr->misc |= val;
+
+	return true;
+}
+
+uint32_t MplsLayer::getMplsLabel()
+{
+	return (htons(getMplsHeader()->hiLabel) << 4) | ((getMplsHeader()->misc & 0xF0) >> 4);
+}
+
+bool MplsLayer::setMplsLabel(uint32_t label)
+{
+	if (label > 0xFFFFF)
+	{
+		LOG_ERROR("MPLS label mustn't exceed 20 bits which is the value %d. Got a parameter with the value %d", 0xFFFFF, label);
+		return false;
+	}
+
+	mpls_header* hdr = getMplsHeader();
+
+	// clear the 4 label bits in misc field
+	hdr->misc &= 0x0F;
+
+	// take the last nibble of the label value and move this nibble to its place in misc
+	uint8_t miscVal = (label & 0x0F) << 4;
+
+	// update misc field
+	hdr->misc |= miscVal;
+
+	// get rid of the nibble that went to misc
+	label = label >> 4;
+
+	// set the high 2 bytes of the label
+	hdr->hiLabel = (uint16_t)htons(label);
+
+	return true;
+}
+
+
+void MplsLayer::parseNextLayer()
+{
+	size_t headerLen = getHeaderLen();
+	if (m_DataLen < headerLen + 1)
+		return;
+
+	if (!isBottomOfStack())
+	{
+		m_NextLayer = new MplsLayer(m_Data + sizeof(mpls_header), m_DataLen - sizeof(mpls_header), this, m_Packet);
+		return;
+	}
+
+	uint8_t nextNibble = (*((uint8_t*)(m_Data + headerLen)) & 0xF0) >> 4;
+
+	if (nextNibble == 4)
+		m_NextLayer = new IPv4Layer(m_Data + sizeof(mpls_header), m_DataLen - sizeof(mpls_header), this, m_Packet);
+	else if (nextNibble == 6)
+		m_NextLayer = new IPv6Layer(m_Data + sizeof(mpls_header), m_DataLen - sizeof(mpls_header), this, m_Packet);
+	else
+		m_NextLayer = new PayloadLayer(m_Data + sizeof(mpls_header), m_DataLen - sizeof(mpls_header), this, m_Packet);
+}
+
+void MplsLayer::computeCalculateFields()
+{
+	Layer* nextLayer = getNextLayer();
+	if (nextLayer != NULL)
+	{
+		setBottomOfStack((nextLayer->getProtocol() == MPLS));
+	}
+}
+
+std::string MplsLayer::toString()
+{
+	std::ostringstream labelStream;
+	labelStream << getMplsLabel();
+	std::ostringstream expStream;
+	expStream << (int)getExperimentalUseValue();
+	std::ostringstream ttlStream;
+	ttlStream << (int)getTTL();
+	std::string bottomOfStack = isBottomOfStack() ? "true" : "false";
+
+	return "MPLS Layer, Label: " + labelStream.str() + ", Exp: " + expStream.str() + ", TTL: " + ttlStream.str() +
+			", Bottom of stack: " + bottomOfStack;
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/NullLoopbackLayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/NullLoopbackLayer.cpp b/thirdparty/pcap++/Packet++/src/NullLoopbackLayer.cpp
new file mode 100644
index 0000000..cab1578
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/NullLoopbackLayer.cpp
@@ -0,0 +1,79 @@
+#include <NullLoopbackLayer.h>
+#include <IPv4Layer.h>
+#include <IPv6Layer.h>
+#include <PayloadLayer.h>
+#include <string.h>
+
+namespace pcpp
+{
+
+#define BSWAP16(x) (((x) >> 8) | ((x) << 8))
+#define BSWAP32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) \
+                  | (((x) & 0x0000FF00) << 8) | ((x) << 24))
+
+
+NullLoopbackLayer::NullLoopbackLayer(uint32_t family)
+{
+	m_DataLen = sizeof(uint32_t);
+	m_Data = new uint8_t[m_DataLen];
+	memset(m_Data, 0, m_DataLen);
+	m_Protocol = NULL_LOOPBACK;
+
+	setFamily(family);
+}
+
+uint32_t NullLoopbackLayer::getFamily()
+{
+	uint32_t family = *(uint32_t*)m_Data;
+    if ((family & 0xFFFF0000) != 0)
+    {
+		if ((family & 0xFF000000) == 0 && (family & 0x00FF0000) < 0x00060000)
+		{
+		  family >>= 16;
+		}
+		else
+		{
+		  family = BSWAP32(family);
+		}
+    }
+    else
+    {
+		if ((family & 0x000000FF) == 0 && (family & 0x0000FF00) < 0x00000600)
+		{
+			family = BSWAP16(family & 0xFFFF);
+		}
+    }
+
+    return family;
+}
+
+void NullLoopbackLayer::setFamily(uint32_t family)
+{
+	*m_Data = family;
+}
+
+void NullLoopbackLayer::parseNextLayer()
+{
+	uint32_t family = getFamily();
+	switch (family)
+	{
+	case PCPP_BSD_AF_INET:
+		m_NextLayer = new IPv4Layer(m_Data + sizeof(uint32_t), m_DataLen - sizeof(uint32_t), this, m_Packet);
+		break;
+    case PCPP_BSD_AF_INET6_BSD:
+    case PCPP_BSD_AF_INET6_FREEBSD:
+    case PCPP_BSD_AF_INET6_DARWIN:
+		m_NextLayer = new IPv6Layer(m_Data + sizeof(uint32_t), m_DataLen - sizeof(uint32_t), this, m_Packet);
+		break;
+    default:
+    	m_NextLayer = new PayloadLayer(m_Data + sizeof(uint32_t), m_DataLen - sizeof(uint32_t), this, m_Packet);
+	}
+}
+
+
+std::string NullLoopbackLayer::toString()
+{
+	return "Null/Loopback";
+}
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/PPPoELayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/PPPoELayer.cpp b/thirdparty/pcap++/Packet++/src/PPPoELayer.cpp
new file mode 100644
index 0000000..aca584f
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/PPPoELayer.cpp
@@ -0,0 +1,414 @@
+#define LOG_MODULE PacketLogModulePPPoELayer
+
+#include <PPPoELayer.h>
+#include <IPv4Layer.h>
+#include <IPv6Layer.h>
+#include <PayloadLayer.h>
+#include <Logger.h>
+#include <map>
+#include <sstream>
+#if defined(WIN32) || defined(WINx64)
+#include <winsock2.h>
+#elif LINUX
+#include <in.h>
+#endif
+
+namespace pcpp
+{
+
+/// PPPoELayer
+/// ~~~~~~~~~~
+
+PPPoELayer::PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, size_t additionalBytesToAllocate)
+{
+	m_DataLen = sizeof(pppoe_header) + additionalBytesToAllocate;
+	m_Data = new uint8_t[m_DataLen + additionalBytesToAllocate];
+	memset(m_Data, 0, m_DataLen + additionalBytesToAllocate);
+
+	pppoe_header* pppoeHdr = getPPPoEHeader();
+	pppoeHdr->version = (version & 0xf);
+	pppoeHdr->type = (type & 0x0f);
+	pppoeHdr->code = code;
+	pppoeHdr->sessionId = htons(sessionId);
+	pppoeHdr->payloadLength = 0;
+}
+
+void PPPoELayer::computeCalculateFields()
+{
+	pppoe_header* pppoeHdr = (pppoe_header*)m_Data;
+	pppoeHdr->payloadLength = htons(m_DataLen - sizeof(pppoe_header));
+}
+
+
+
+/// PPPoESessionLayer
+/// ~~~~~~~~~~~~~~~~~
+
+
+void PPPoESessionLayer::parseNextLayer()
+{
+	size_t headerLen = getHeaderLen();
+	if (m_DataLen <= headerLen)
+		return;
+
+	switch (getPPPNextProtocol())
+	{
+	case PCPP_PPP_IP:
+		m_NextLayer = new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
+		break;
+	case PCPP_PPP_IPV6:
+		m_NextLayer = new IPv6Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
+		break;
+	default:
+		m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
+		break;
+	}
+
+}
+
+uint16_t PPPoESessionLayer::getPPPNextProtocol()
+{
+	if (m_DataLen < getHeaderLen())
+	{
+		LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header");
+		return 0;
+	}
+
+	uint16_t pppNextProto = *(uint16_t*)(m_Data + sizeof(pppoe_header));
+	return ntohs(pppNextProto);
+}
+
+void PPPoESessionLayer::setPPPNextProtocol(uint16_t nextProtocol)
+{
+	if (m_DataLen < getHeaderLen())
+	{
+		LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header");
+		return;
+	}
+
+	uint16_t* pppProto = (uint16_t*)(m_Data + sizeof(pppoe_header));
+	*pppProto = htons(nextProtocol);
+}
+
+std::map<uint16_t, std::string> createPPPNextProtoToStringMap()
+{
+	std::map<uint16_t, std::string> tempMap;
+	tempMap[PCPP_PPP_PADDING] =     "Padding Protocol";
+	tempMap[PCPP_PPP_ROHC_SCID] =   "ROHC small-CID";
+	tempMap[PCPP_PPP_ROHC_LCID] =   "ROHC large-CID";
+	tempMap[PCPP_PPP_IP] =          "Internet Protocol version 4";
+	tempMap[PCPP_PPP_OSI] =         "OSI Network Layer";
+	tempMap[PCPP_PPP_XNSIDP] =      "Xerox NS IDP";
+	tempMap[PCPP_PPP_DEC4] =        "DECnet Phase IV";
+	tempMap[PCPP_PPP_AT] =          "Appletalk";
+	tempMap[PCPP_PPP_IPX] =         "Novell IPX";
+	tempMap[PCPP_PPP_VJC_COMP] =    "Van Jacobson Compressed TCP/IP";
+	tempMap[PCPP_PPP_VJC_UNCOMP] =  "Van Jacobson Uncompressed TCP/IP";
+	tempMap[PCPP_PPP_BCP] =         "Bridging PDU";
+	tempMap[PCPP_PPP_ST] =          "Stream Protocol (ST-II)";
+	tempMap[PCPP_PPP_VINES] =       "Banyan Vines";
+	tempMap[PCPP_PPP_AT_EDDP] =     "AppleTalk EDDP";
+	tempMap[PCPP_PPP_AT_SB] =       "AppleTalk SmartBuffered";
+	tempMap[PCPP_PPP_MP] =          "Multi-Link";
+	tempMap[PCPP_PPP_NB] =          "NETBIOS Framing";
+	tempMap[PCPP_PPP_CISCO] =       "Cisco Systems";
+	tempMap[PCPP_PPP_ASCOM] =       "Ascom Timeplex";
+	tempMap[PCPP_PPP_LBLB] =        "Fujitsu Link Backup and Load Balancing (LBLB)";
+	tempMap[PCPP_PPP_RL] =          "DCA Remote Lan";
+	tempMap[PCPP_PPP_SDTP] =        "Serial Data Transport Protocol (PPP-SDTP)";
+	tempMap[PCPP_PPP_LLC] =         "SNA over 802.2";
+	tempMap[PCPP_PPP_SNA] =         "SNA";
+	tempMap[PCPP_PPP_IPV6HC] =      "IPv6 Header Compression ";
+    tempMap[PCPP_PPP_KNX] =         "KNX Bridging Data";
+    tempMap[PCPP_PPP_ENCRYPT] =     "Encryption";
+    tempMap[PCPP_PPP_ILE] =         "Individual Link Encryption";
+    tempMap[PCPP_PPP_IPV6] =        "Internet Protocol version 6";
+    tempMap[PCPP_PPP_MUX] =         "PPP Muxing";
+    tempMap[PCPP_PPP_VSNP] =        "Vendor-Specific Network Protocol (VSNP)";
+    tempMap[PCPP_PPP_TNP] =         "TRILL Network Protocol (TNP)";
+    tempMap[PCPP_PPP_RTP_FH] =      "RTP IPHC Full Header";
+    tempMap[PCPP_PPP_RTP_CTCP] =    "RTP IPHC Compressed TCP";
+    tempMap[PCPP_PPP_RTP_CNTCP] =   "RTP IPHC Compressed Non TCP";
+    tempMap[PCPP_PPP_RTP_CUDP8] =   "RTP IPHC Compressed UDP 8";
+    tempMap[PCPP_PPP_RTP_CRTP8] =   "RTP IPHC Compressed RTP 8";
+    tempMap[PCPP_PPP_STAMPEDE] =    "Stampede Bridging";
+    tempMap[PCPP_PPP_MPPLUS] =      "MP+ Protocol";
+    tempMap[PCPP_PPP_NTCITS_IPI] =  "NTCITS IPI";
+    tempMap[PCPP_PPP_ML_SLCOMP] =   "Single link compression in multilink";
+    tempMap[PCPP_PPP_COMP] =        "Compressed datagram";
+    tempMap[PCPP_PPP_STP_HELLO] =   "802.1d Hello Packets";
+    tempMap[PCPP_PPP_IBM_SR] =      "IBM Source Routing BPDU";
+    tempMap[PCPP_PPP_DEC_LB] =      "DEC LANBridge100 Spanning Tree";
+    tempMap[PCPP_PPP_CDP] =         "Cisco Discovery Protocol";
+    tempMap[PCPP_PPP_NETCS] =       "Netcs Twin Routing";
+    tempMap[PCPP_PPP_STP] =         "STP - Scheduled Transfer Protocol";
+    tempMap[PCPP_PPP_EDP] =         "EDP - Extreme Discovery Protocol";
+    tempMap[PCPP_PPP_OSCP] =        "Optical Supervisory Channel Protocol (OSCP)";
+    tempMap[PCPP_PPP_OSCP2] =       "Optical Supervisory Channel Protocol (OSCP)";
+    tempMap[PCPP_PPP_LUXCOM] =      "Luxcom";
+    tempMap[PCPP_PPP_SIGMA] =       "Sigma Network Systems";
+    tempMap[PCPP_PPP_ACSP] =        "Apple Client Server Protocol";
+    tempMap[PCPP_PPP_MPLS_UNI] =    "MPLS Unicast";
+    tempMap[PCPP_PPP_MPLS_MULTI] =  "MPLS Multicast";
+    tempMap[PCPP_PPP_P12844] =      "IEEE p1284.4 standard - data packets";
+    tempMap[PCPP_PPP_TETRA] =       "ETSI TETRA Network Protocol Type 1";
+    tempMap[PCPP_PPP_MFTP] =        "Multichannel Flow Treatment Protocol";
+    tempMap[PCPP_PPP_RTP_CTCPND] =  "RTP IPHC Compressed TCP No Delta";
+    tempMap[PCPP_PPP_RTP_CS] =      "RTP IPHC Context State";
+    tempMap[PCPP_PPP_RTP_CUDP16] =  "RTP IPHC Compressed UDP 16";
+    tempMap[PCPP_PPP_RTP_CRDP16] =  "RTP IPHC Compressed RTP 16";
+    tempMap[PCPP_PPP_CCCP] =        "Cray Communications Control Protocol";
+    tempMap[PCPP_PPP_CDPD_MNRP] =   "CDPD Mobile Network Registration Protocol";
+    tempMap[PCPP_PPP_EXPANDAP] =    "Expand accelerator protocol";
+    tempMap[PCPP_PPP_ODSICP] =      "ODSICP NCP";
+    tempMap[PCPP_PPP_DOCSIS] =      "DOCSIS DLL";
+    tempMap[PCPP_PPP_CETACEANNDP] = "Cetacean Network Detection Protocol";
+    tempMap[PCPP_PPP_LZS] =         "Stacker LZS";
+    tempMap[PCPP_PPP_REFTEK] =      "RefTek Protocol";
+    tempMap[PCPP_PPP_FC] =          "Fibre Channel";
+    tempMap[PCPP_PPP_EMIT] =        "EMIT Protocols";
+    tempMap[PCPP_PPP_VSP] =         "Vendor-Specific Protocol (VSP)";
+    tempMap[PCPP_PPP_TLSP] =        "TRILL Link State Protocol (TLSP)";
+    tempMap[PCPP_PPP_IPCP] =        "Internet Protocol Control Protocol";
+    tempMap[PCPP_PPP_OSINLCP] =     "OSI Network Layer Control Protocol";
+    tempMap[PCPP_PPP_XNSIDPCP] =    "Xerox NS IDP Control Protocol";
+    tempMap[PCPP_PPP_DECNETCP] =    "DECnet Phase IV Control Protocol";
+    tempMap[PCPP_PPP_ATCP] =        "AppleTalk Control Protocol";
+    tempMap[PCPP_PPP_IPXCP] =       "Novell IPX Control Protocol";
+    tempMap[PCPP_PPP_BRIDGENCP] =   "Bridging NCP";
+    tempMap[PCPP_PPP_SPCP] =        "Stream Protocol Control Protocol";
+    tempMap[PCPP_PPP_BVCP] =        "Banyan Vines Control Protocol";
+    tempMap[PCPP_PPP_MLCP] =        "Multi-Link Control Protocol";
+    tempMap[PCPP_PPP_NBCP] =        "NETBIOS Framing Control Protocol";
+    tempMap[PCPP_PPP_CISCOCP] =     "Cisco Systems Control Protocol";
+    tempMap[PCPP_PPP_ASCOMCP] =     "Ascom Timeplex";
+    tempMap[PCPP_PPP_LBLBCP] =      "Fujitsu LBLB Control Protocol";
+    tempMap[PCPP_PPP_RLNCP] =       "DCA Remote Lan Network Control Protocol (RLNCP)";
+    tempMap[PCPP_PPP_SDCP] =        "Serial Data Control Protocol (PPP-SDCP)";
+    tempMap[PCPP_PPP_LLCCP] =       "SNA over 802.2 Control Protocol";
+    tempMap[PCPP_PPP_SNACP] =       "SNA Control Protocol";
+    tempMap[PCPP_PPP_IP6HCCP] =     "IP6 Header Compression Control Protocol";
+    tempMap[PCPP_PPP_KNXCP] =       "KNX Bridging Control Protocol";
+    tempMap[PCPP_PPP_ECP] =         "Encryption Control Protocol";
+    tempMap[PCPP_PPP_ILECP] =       "Individual Link Encryption Control Protocol";
+    tempMap[PCPP_PPP_IPV6CP] =      "IPv6 Control Protocol";
+    tempMap[PCPP_PPP_MUXCP] =       "PPP Muxing Control Protocol";
+    tempMap[PCPP_PPP_VSNCP] =       "Vendor-Specific Network Control Protocol (VSNCP)";
+    tempMap[PCPP_PPP_TNCP] =        "TRILL Network Control Protocol";
+    tempMap[PCPP_PPP_STAMPEDECP] =  "Stampede Bridging Control Protocol";
+    tempMap[PCPP_PPP_MPPCP] =       "MP+ Control Protocol";
+    tempMap[PCPP_PPP_IPICP] =       "NTCITS IPI Control Protocol";
+    tempMap[PCPP_PPP_SLCC] =        "Single link compression in multilink control";
+    tempMap[PCPP_PPP_CCP] =         "Compression Control Protocol";
+    tempMap[PCPP_PPP_CDPCP] =       "Cisco Discovery Protocol Control Protocol";
+    tempMap[PCPP_PPP_NETCSCP] =     "Netcs Twin Routing";
+    tempMap[PCPP_PPP_STPCP] =       "STP - Control Protocol";
+    tempMap[PCPP_PPP_EDPCP] =       "EDPCP - Extreme Discovery Protocol Control Protocol";
+    tempMap[PCPP_PPP_ACSPC] =       "Apple Client Server Protocol Control";
+    tempMap[PCPP_PPP_MPLSCP] =      "MPLS Control Protocol";
+    tempMap[PCPP_PPP_P12844CP] =    "IEEE p1284.4 standard - Protocol Control";
+    tempMap[PCPP_PPP_TETRACP] =     "ETSI TETRA TNP1 Control Protocol";
+    tempMap[PCPP_PPP_MFTPCP] =      "Multichannel Flow Treatment Protocol";
+    tempMap[PCPP_PPP_LCP] =         "Link Control Protocol";
+    tempMap[PCPP_PPP_PAP] =         "Password Authentication Protocol";
+    tempMap[PCPP_PPP_LQR] =         "Link Quality Report";
+    tempMap[PCPP_PPP_SPAP] =        "Shiva Password Authentication Protocol";
+    tempMap[PCPP_PPP_CBCP] =        "Callback Control Protocol (CBCP)";
+    tempMap[PCPP_PPP_BACP] =        "BACP Bandwidth Allocation Control Protocol";
+    tempMap[PCPP_PPP_BAP] =         "BAP Bandwidth Allocation Protocol";
+    tempMap[PCPP_PPP_VSAP] =        "Vendor-Specific Authentication Protocol (VSAP)";
+    tempMap[PCPP_PPP_CONTCP] =      "Container Control Protocol";
+    tempMap[PCPP_PPP_CHAP] =        "Challenge Handshake Authentication Protocol";
+    tempMap[PCPP_PPP_RSAAP] =       "RSA Authentication Protocol";
+    tempMap[PCPP_PPP_EAP] =         "Extensible Authentication Protocol";
+    tempMap[PCPP_PPP_SIEP] =        "Mitsubishi Security Information Exchange Protocol (SIEP)";
+    tempMap[PCPP_PPP_SBAP] =        "Stampede Bridging Authorization Protocol";
+    tempMap[PCPP_PPP_PRPAP] =       "Proprietary Authentication Protocol";
+    tempMap[PCPP_PPP_PRPAP2] =      "Proprietary Authentication Protocol";
+    tempMap[PCPP_PPP_PRPNIAP] =     "Proprietary Node ID Authentication Protocol";
+	return tempMap;
+}
+
+const std::map<uint16_t, std::string> PPPNextProtoToString = createPPPNextProtoToStringMap();
+
+std::string PPPoESessionLayer::toString()
+{
+	std::map<uint16_t, std::string>::const_iterator iter = PPPNextProtoToString.find(getPPPNextProtocol());
+	std::string nextProtocol;
+	if (iter != PPPNextProtoToString.end())
+		nextProtocol = iter->second;
+	else
+	{
+		std::ostringstream stream;
+		stream << "Unknown (0x" << std::hex << getPPPNextProtocol() << ")";
+		nextProtocol = stream.str();
+	}
+
+	return "PPP-over-Ethernet Session (followed by '" + nextProtocol +  "')";
+}
+
+
+
+/// PPPoEDiscoveryLayer
+/// ~~~~~~~~~~~~~~~~~~~
+
+
+PPPoEDiscoveryLayer::PPPoETagTypes PPPoEDiscoveryLayer::PPPoETag::getType()
+{
+	return (PPPoEDiscoveryLayer::PPPoETagTypes)ntohs(tagType);
+}
+
+size_t PPPoEDiscoveryLayer::PPPoETag::getTagTotalSize() const
+{
+	return 2*sizeof(uint16_t) + ntohs(tagDataLength);
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType)
+{
+	// check if there are tags at all
+	if (m_DataLen <= sizeof(pppoe_header))
+		return NULL;
+
+	uint8_t* curTagPtr = m_Data + sizeof(pppoe_header);
+	while ((curTagPtr - m_Data) < (int)m_DataLen)
+	{
+		PPPoEDiscoveryLayer::PPPoETag* curTag = castPtrToPPPoETag(curTagPtr);
+		if (curTag->tagType == htons(tagType))
+			return curTag;
+
+		curTagPtr += curTag->getTagTotalSize();
+	}
+
+	return NULL;
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::getFirstTag()
+{
+	// check if there are tags at all
+	if (m_DataLen <= sizeof(pppoe_header))
+		return NULL;
+
+	uint8_t* curTagPtr = m_Data + sizeof(pppoe_header);
+	return castPtrToPPPoETag(curTagPtr);
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::getNextTag(PPPoEDiscoveryLayer::PPPoETag* tag)
+{
+	if (tag == NULL)
+		return NULL;
+
+	// prev tag was the last tag
+	if ((uint8_t*)tag + tag->getTagTotalSize() - m_Data >= (int)m_DataLen)
+		return NULL;
+
+	return castPtrToPPPoETag((uint8_t*)tag + tag->getTagTotalSize());
+}
+
+int PPPoEDiscoveryLayer::getTagCount()
+{
+	if (m_TagCount != -1)
+		return m_TagCount;
+
+	m_TagCount = 0;
+	PPPoEDiscoveryLayer::PPPoETag* curTag = getFirstTag();
+	while (curTag != NULL)
+	{
+		m_TagCount++;
+		curTag = getNextTag(curTag);
+	}
+
+	return m_TagCount;
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::addTagAt(PPPoETagTypes tagType, uint16_t tagLength, const uint8_t* tagData, int offset)
+{
+	size_t tagTotalLength = 2*sizeof(uint16_t) + tagLength;
+	if (!extendLayer(offset, tagTotalLength))
+	{
+		LOG_ERROR("Could not extend PPPoEDiscoveryLayer in [%d] bytes", (int)tagTotalLength);
+		return NULL;
+	}
+
+	uint16_t tagTypeVal = htons((uint16_t)tagType);
+	tagLength = htons(tagLength);
+	memcpy(m_Data + offset, &tagTypeVal, sizeof(uint16_t));
+	memcpy(m_Data + offset + sizeof(uint16_t), &tagLength, sizeof(uint16_t));
+	if (tagLength > 0 && tagData != NULL)
+		memcpy(m_Data + offset + 2*sizeof(uint16_t), tagData, ntohs(tagLength));
+
+	uint8_t* newTagPtr = m_Data + offset;
+
+	getPPPoEHeader()->payloadLength += htons(tagTotalLength);
+	m_TagCount++;
+
+	return castPtrToPPPoETag(newTagPtr);
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::addTagAfter(PPPoETagTypes tagType, uint16_t tagLength, const uint8_t* tagData, PPPoEDiscoveryLayer::PPPoETag* prevTag)
+{
+	if (prevTag == NULL)
+	{
+		LOG_ERROR("prevTag is NULL");
+		return NULL;
+	}
+
+	int offset = (uint8_t*)prevTag + prevTag->getTagTotalSize() - m_Data;
+
+	return addTagAt(tagType, tagLength, tagData, offset);
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::addTag(PPPoETagTypes tagType, uint16_t tagLength, const uint8_t* tagData)
+{
+	return addTagAt(tagType, tagLength, tagData, getHeaderLen());
+}
+
+size_t PPPoEDiscoveryLayer::getHeaderLen()
+{
+	return sizeof(pppoe_header) + ntohs(getPPPoEHeader()->payloadLength);
+}
+
+PPPoEDiscoveryLayer::PPPoETag* PPPoEDiscoveryLayer::castPtrToPPPoETag(uint8_t* ptr)
+{
+	return (PPPoEDiscoveryLayer::PPPoETag*)ptr;
+}
+
+bool PPPoEDiscoveryLayer::removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType)
+{
+	PPPoEDiscoveryLayer::PPPoETag* tag = getTag(tagType);
+	if (tag == NULL)
+	{
+		LOG_ERROR("Couldn't find tag");
+		return false;
+	}
+
+	int offset = (uint8_t*)tag - m_Data;
+
+	return shortenLayer(offset, tag->getTagTotalSize());
+}
+
+bool PPPoEDiscoveryLayer::removeAllTags()
+{
+	int offset = sizeof(pppoe_header);
+	return shortenLayer(offset, m_DataLen-offset);
+}
+
+std::string PPPoEDiscoveryLayer::codeToString(PPPoECode code)
+{
+	switch (code)
+	{
+	case PPPoELayer::PPPOE_CODE_SESSION:return std::string("PPPoE Session");
+	case PPPoELayer::PPPOE_CODE_PADO:	return std::string("PADO");
+	case PPPoELayer::PPPOE_CODE_PADI:	return std::string("PADI");
+	case PPPoELayer::PPPOE_CODE_PADG:	return std::string("PADG");
+	case PPPoELayer::PPPOE_CODE_PADC:	return std::string("PADC");
+	case PPPoELayer::PPPOE_CODE_PADQ:	return std::string("PADQ");
+	case PPPoELayer::PPPOE_CODE_PADR:	return std::string("PADR");
+	case PPPoELayer::PPPOE_CODE_PADS:	return std::string("PADS");
+	case PPPoELayer::PPPOE_CODE_PADT:	return std::string("PADT");
+	case PPPoELayer::PPPOE_CODE_PADM:	return std::string("PADM");
+	case PPPoELayer::PPPOE_CODE_PADN:	return std::string("PADN");
+	default:							return std::string("Unknown PPPoE code");
+	}
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/Packet.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/Packet.cpp b/thirdparty/pcap++/Packet++/src/Packet.cpp
new file mode 100644
index 0000000..81ad805
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/Packet.cpp
@@ -0,0 +1,504 @@
+#define LOG_MODULE PacketLogModulePacket
+
+#include <Packet.h>
+#include <EthLayer.h>
+#include <SllLayer.h>
+#include <NullLoopbackLayer.h>
+#include <IPv4Layer.h>
+#include <IPv6Layer.h>
+#include <PayloadLayer.h>
+#include <Logger.h>
+#include <string.h>
+#include <typeinfo>
+#include <sstream>
+#ifdef _MSC_VER
+#include <time.h>
+#include <SystemUtils.h>
+#endif
+
+
+namespace pcpp
+{
+
+Packet::Packet(size_t maxPacketLen) :
+	m_RawPacket(NULL),
+	m_FirstLayer(NULL),
+	m_LastLayer(NULL),
+	m_ProtocolTypes(UnknownProtocol),
+	m_MaxPacketLen(maxPacketLen),
+	m_FreeRawPacket(true)
+{
+	timeval time;
+	gettimeofday(&time, NULL);
+	uint8_t* data = new uint8_t[m_MaxPacketLen];
+	memset(data, 0, m_MaxPacketLen);
+	m_RawPacket = new RawPacket((const uint8_t*)data, 0, time, true, LINKTYPE_ETHERNET);
+}
+
+void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
+{
+	destructPacketData();
+
+	m_FirstLayer = NULL;
+	m_LastLayer = NULL;
+	m_ProtocolTypes = UnknownProtocol;
+	m_MaxPacketLen = rawPacket->getRawDataLen();
+	m_FreeRawPacket = freeRawPacket;
+	m_RawPacket = rawPacket;
+	if (m_RawPacket && m_RawPacket->getLinkLayerType() == LINKTYPE_LINUX_SLL)
+	{
+		m_FirstLayer = new SllLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
+	}
+	else if (m_RawPacket && m_RawPacket->getLinkLayerType() == LINKTYPE_NULL)
+	{
+		m_FirstLayer = new NullLoopbackLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
+	}
+	else if (m_RawPacket && (m_RawPacket->getLinkLayerType() == LINKTYPE_RAW || m_RawPacket->getLinkLayerType() == LINKTYPE_DLT_RAW1 || m_RawPacket->getLinkLayerType() == LINKTYPE_DLT_RAW2))
+	{
+		uint8_t ipVer = m_RawPacket->getRawData()[0] & 0xf0;
+		if (ipVer == 0x40)
+			m_FirstLayer = new IPv4Layer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
+		else if (ipVer == 0x60)
+			m_FirstLayer = new IPv6Layer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
+		else
+			m_FirstLayer = new PayloadLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), NULL, this);
+	}
+	else
+	{
+		m_FirstLayer = new EthLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
+	}
+
+	m_LastLayer = m_FirstLayer;
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL && (curLayer->getProtocol() & parseUntil) == 0 && curLayer->getOsiModelLayer() <= parseUntilLayer)
+	{
+		m_ProtocolTypes |= curLayer->getProtocol();
+		curLayer->parseNextLayer();
+		m_LayersAllocatedInPacket.push_back(curLayer);
+		curLayer = curLayer->getNextLayer();
+		if (curLayer != NULL)
+			m_LastLayer = curLayer;
+	}
+
+	if (curLayer != NULL && (curLayer->getProtocol() & parseUntil) != 0)
+	{
+		m_ProtocolTypes |= curLayer->getProtocol();
+		m_LayersAllocatedInPacket.push_back(curLayer);
+	}
+
+	if (curLayer != NULL &&  curLayer->getOsiModelLayer() > parseUntilLayer)
+	{
+		m_LastLayer = curLayer->getPrevLayer();
+		delete curLayer;
+		m_LastLayer->m_NextLayer = NULL;
+	}
+}
+
+Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
+{
+	m_FreeRawPacket = false;
+	m_RawPacket = NULL;
+	setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
+}
+
+Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
+{
+	m_FreeRawPacket = false;
+	m_RawPacket = NULL;
+	setRawPacket(rawPacket, false, parseUntil, OsiModelLayerUnknown);
+}
+
+Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
+{
+	m_FreeRawPacket = false;
+	m_RawPacket = NULL;
+	setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
+}
+
+Packet::Packet(const Packet& other)
+{
+	copyDataFrom(other);
+}
+
+void Packet::destructPacketData()
+{
+	std::vector<Layer*>::iterator iter = m_LayersAllocatedInPacket.begin();
+	while (iter != m_LayersAllocatedInPacket.end())
+	{
+		delete (*iter);
+		iter = m_LayersAllocatedInPacket.erase(iter);
+	}
+
+	if (m_RawPacket != NULL && m_FreeRawPacket)
+	{
+		delete m_RawPacket;
+	}
+}
+
+Packet& Packet::operator=(const Packet& other)
+{
+	destructPacketData();
+
+	copyDataFrom(other);
+
+	return *this;
+}
+
+void Packet::copyDataFrom(const Packet& other)
+{
+	m_RawPacket = new RawPacket(*(other.m_RawPacket));
+	m_FreeRawPacket = true;
+	m_MaxPacketLen = other.m_MaxPacketLen;
+	m_ProtocolTypes = other.m_ProtocolTypes;
+	m_FirstLayer = new EthLayer((uint8_t*)m_RawPacket->getRawData(), m_RawPacket->getRawDataLen(), this);
+	m_LastLayer = m_FirstLayer;
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		curLayer->parseNextLayer();
+		m_LayersAllocatedInPacket.push_back(curLayer);
+		curLayer = curLayer->getNextLayer();
+		if (curLayer != NULL)
+			m_LastLayer = curLayer;
+	}
+}
+
+void Packet::reallocateRawData(size_t newSize)
+{
+	LOG_DEBUG("Allocating packet to new size: %d", (int)newSize);
+
+	// allocate a new array with size newSize
+	m_MaxPacketLen = newSize;
+
+	// set the new array to RawPacket
+	if (!m_RawPacket->reallocateData(m_MaxPacketLen))
+	{
+		LOG_ERROR("Couldn't reallocate data of raw packet to %d bytes", (int)m_MaxPacketLen);
+		return;
+	}
+
+	// set all data pointers in layers to the new array address
+	const uint8_t* dataPtr = m_RawPacket->getRawData();
+
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		LOG_DEBUG("Setting new data pointer to layer '%s'", typeid(curLayer).name());
+		curLayer->m_Data = (uint8_t*)dataPtr;
+		dataPtr += curLayer->getHeaderLen();
+		curLayer = curLayer->getNextLayer();
+	}
+}
+
+bool Packet::addLayer(Layer* newLayer)
+{
+	return insertLayer(m_LastLayer, newLayer);
+}
+
+bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer)
+{
+	if (newLayer == NULL)
+	{
+		LOG_ERROR("Layer to add is NULL");
+		return false;
+	}
+
+	if (newLayer->isAllocatedToPacket())
+	{
+		LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
+		return false;
+	}
+
+	if (m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() > m_MaxPacketLen)
+	{
+		// reallocate to maximum value of: twice the max size of the packet or max size + new required length
+		if (m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() > m_MaxPacketLen*2)
+			reallocateRawData(m_RawPacket->getRawDataLen() + newLayer->getHeaderLen() + m_MaxPacketLen);
+		else
+			reallocateRawData(m_MaxPacketLen*2);
+	}
+
+	size_t appendDataLen = newLayer->getHeaderLen();
+
+	// insert layer data to raw packet
+	int indexToInsertData = 0;
+	if (prevLayer != NULL)
+		indexToInsertData = prevLayer->m_Data+prevLayer->getHeaderLen() - m_RawPacket->getRawData();
+	m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, appendDataLen);
+
+	//delete previous layer data
+	delete[] newLayer->m_Data;
+
+	// add layer to layers linked list
+	if (prevLayer != NULL)
+	{
+		newLayer->setNextLayer(prevLayer->getNextLayer());
+		newLayer->setPrevLayer(prevLayer);
+		prevLayer->setNextLayer(newLayer);
+	}
+	else //prevLayer == NULL
+	{
+		newLayer->setNextLayer(m_FirstLayer);
+		if (m_FirstLayer != NULL)
+			m_FirstLayer->setPrevLayer(newLayer);
+		m_FirstLayer = newLayer;
+	}
+
+	if (newLayer->getNextLayer() == NULL)
+		m_LastLayer = newLayer;
+
+	// assign layer with this packet only
+	newLayer->m_Packet = this;
+
+	// re-calculate all layers data ptr and data length
+	const uint8_t* dataPtr = m_RawPacket->getRawData();
+	int dataLen = m_RawPacket->getRawDataLen();
+
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		curLayer->m_Data = (uint8_t*)dataPtr;
+		curLayer->m_DataLen = dataLen;
+		dataPtr += curLayer->getHeaderLen();
+		dataLen -= curLayer->getHeaderLen();
+		curLayer = curLayer->getNextLayer();
+	}
+
+	// add layer protocol to protocol collection
+	m_ProtocolTypes |= newLayer->getProtocol();
+	return true;
+}
+
+bool Packet::removeLayer(Layer* layer)
+{
+	if (layer == NULL)
+	{
+		LOG_ERROR("Layer is NULL");
+		return false;
+	}
+
+	// verify layer is allocated to a packet
+	if (!layer->isAllocatedToPacket())
+	{
+		LOG_ERROR("Layer isn't allocated to any packet");
+		return false;
+	}
+
+	// verify layer is allocated to *this* packet
+	Layer* curLayer = layer;
+	while (curLayer->m_PrevLayer != NULL)
+		curLayer = curLayer->m_PrevLayer;
+	if (curLayer != m_FirstLayer)
+	{
+		LOG_ERROR("Layer isn't allocated to this packet");
+		return false;
+	}
+
+	// remove data from raw packet
+	size_t numOfBytesToRemove = layer->getHeaderLen();
+	int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
+	if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
+	{
+		LOG_ERROR("Couldn't remove data from packet");
+		return false;
+	}
+
+	// remove layer from layers linked list
+	if (layer->m_PrevLayer != NULL)
+		layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
+	if (layer->m_NextLayer != NULL)
+		layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
+
+	// take care of head and tail ptrs
+	if (m_FirstLayer == layer)
+		m_FirstLayer = layer->m_NextLayer;
+	if (m_LastLayer == layer)
+		m_LastLayer = layer->m_PrevLayer;
+	layer->setNextLayer(NULL);
+	layer->setPrevLayer(NULL);
+
+	// re-calculate all layers data ptr and data length
+	const uint8_t* dataPtr = m_RawPacket->getRawData();
+	int dataLen = m_RawPacket->getRawDataLen();
+
+	curLayer = m_FirstLayer;
+	bool anotherLayerWithSameProtocolExists = false;
+	while (curLayer != NULL)
+	{
+		curLayer->m_Data = (uint8_t*)dataPtr;
+		curLayer->m_DataLen = dataLen;
+		if (curLayer->getProtocol() == layer->getProtocol())
+			anotherLayerWithSameProtocolExists = true;
+		dataPtr += curLayer->getHeaderLen();
+		dataLen -= curLayer->getHeaderLen();
+		curLayer = curLayer->getNextLayer();
+	}
+
+	// remove layer protocol from protocol list if necessary
+	if (!anotherLayerWithSameProtocolExists)
+		m_ProtocolTypes &= ~((uint64_t)layer->getProtocol());
+
+	return true;
+}
+
+bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
+{
+	if (layer == NULL)
+	{
+		LOG_ERROR("Layer is NULL");
+		return false;
+	}
+
+	// verify layer is allocated to this packet
+	if (!(layer->m_Packet == this))
+	{
+		LOG_ERROR("Layer isn't allocated to this packet");
+		return false;
+	}
+
+	if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
+	{
+		// reallocate to maximum value of: twice the max size of the packet or max size + new required length
+		if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen*2)
+			reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
+		else
+			reallocateRawData(m_MaxPacketLen*2);
+	}
+
+	// insert layer data to raw packet
+	int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
+	uint8_t* tempData = new uint8_t[numOfBytesToExtend];
+	m_RawPacket->insertData(indexToInsertData, tempData, numOfBytesToExtend);
+	delete[] tempData;
+
+	// re-calculate all layers data ptr and data length
+	const uint8_t* dataPtr = m_RawPacket->getRawData();
+	int dataLen = m_RawPacket->getRawDataLen();
+
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		curLayer->m_Data = (uint8_t*)dataPtr;
+		curLayer->m_DataLen = dataLen;
+		// assuming header length of the layer that requested to be extended hasn't been enlarged yet
+		size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
+		dataPtr += headerLen;
+		dataLen -= headerLen;
+		curLayer = curLayer->getNextLayer();
+	}
+
+	return true;
+}
+
+bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
+{
+	if (layer == NULL)
+	{
+		LOG_ERROR("Layer is NULL");
+		return false;
+	}
+
+	// verify layer is allocated to this packet
+	if (!(layer->m_Packet == this))
+	{
+		LOG_ERROR("Layer isn't allocated to this packet");
+		return false;
+	}
+
+	// remove data from raw packet
+	int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
+	if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
+	{
+		LOG_ERROR("Couldn't remove data from packet");
+		return false;
+	}
+
+	// re-calculate all layers data ptr and data length
+	const uint8_t* dataPtr = m_RawPacket->getRawData();
+	int dataLen = m_RawPacket->getRawDataLen();
+
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		curLayer->m_Data = (uint8_t*)dataPtr;
+		curLayer->m_DataLen = dataLen;
+		// assuming header length of the layer that requested to be extended hasn't been enlarged yet
+		size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0);
+		dataPtr += headerLen;
+		dataLen -= headerLen;
+		curLayer = curLayer->getNextLayer();
+	}
+
+	return true;
+}
+
+
+void Packet::computeCalculateFields()
+{
+	// calculated fields should be calculated from top layer to bottom layer
+
+	Layer* curLayer = m_LastLayer;
+	while (curLayer != NULL)
+	{
+		curLayer->computeCalculateFields();
+		curLayer = curLayer->getPrevLayer();
+	}
+}
+
+Packet::~Packet()
+{
+	destructPacketData();
+}
+
+std::string Packet::printPacketInfo(bool timeAsLocalTime)
+{
+	std::ostringstream dataLenStream;
+	dataLenStream << m_RawPacket->getRawDataLen();
+
+	// convert raw packet timestamp to printable format
+	timeval timestamp = m_RawPacket->getPacketTimeStamp();
+	time_t nowtime = timestamp.tv_sec;
+	struct tm *nowtm = NULL;
+	if (timeAsLocalTime)
+		nowtm = localtime(&nowtime);
+	else
+		nowtm = gmtime(&nowtime);
+
+	char tmbuf[64], buf[64];
+	if (nowtm != NULL)
+	{
+		strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
+		snprintf(buf, sizeof(buf), "%s.%06lu", tmbuf, timestamp.tv_usec);
+	}
+	else
+		snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000");
+	
+	return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
+}
+
+std::string Packet::printToString(bool timeAsLocalTime)
+{
+	std::vector<std::string> stringList;
+	std::string result;
+	printToStringList(stringList, timeAsLocalTime);
+	for (std::vector<std::string>::iterator iter = stringList.begin(); iter != stringList.end(); iter++)
+	{
+		result += *iter + "\n";
+	}
+
+	return result;
+}
+
+void Packet::printToStringList(std::vector<std::string>& result, bool timeAsLocalTime)
+{
+	result.clear();
+	result.push_back(printPacketInfo(timeAsLocalTime));
+	Layer* curLayer = m_FirstLayer;
+	while (curLayer != NULL)
+	{
+		result.push_back(curLayer->toString());
+		curLayer = curLayer->getNextLayer();
+	}
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/PacketUtils.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/PacketUtils.cpp b/thirdparty/pcap++/Packet++/src/PacketUtils.cpp
new file mode 100644
index 0000000..224184e
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/PacketUtils.cpp
@@ -0,0 +1,118 @@
+#include <string.h>
+#include "PacketUtils.h"
+#include "IpUtils.h"
+#include "IPv4Layer.h"
+#include "IPv6Layer.h"
+#include "TcpLayer.h"
+#include "UdpLayer.h"
+
+namespace pcpp
+{
+
+uint32_t hash5Tuple(Packet* packet)
+{
+	if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6))
+		return 0;
+
+	if (packet->isPacketOfType(ICMP))
+		return 0;
+
+	if (!(packet->isPacketOfType(TCP)) && (!packet->isPacketOfType(UDP)))
+		return 0;
+
+	ScalarBuffer<uint8_t> vec[5];
+
+	uint16_t portSrc = 0;
+	uint16_t portDst = 0;
+	int srcPosition = 0;
+
+	TcpLayer* tcpLayer = packet->getLayerOfType<TcpLayer>();
+	if (tcpLayer != NULL)
+	{
+		portSrc = tcpLayer->getTcpHeader()->portSrc;
+		portDst = tcpLayer->getTcpHeader()->portDst;
+	}
+	else
+	{
+		UdpLayer* udpLayer = packet->getLayerOfType<UdpLayer>();
+		portSrc = udpLayer->getUdpHeader()->portSrc;
+		portDst = udpLayer->getUdpHeader()->portDst;
+	}
+
+	if (portDst < portSrc)
+		srcPosition = 1;
+
+	vec[0 + srcPosition].buffer = (uint8_t*)&portSrc;
+	vec[0 + srcPosition].len = 2;
+	vec[1 - srcPosition].buffer = (uint8_t*)&portDst;
+	vec[1 - srcPosition].len = 2;
+
+
+	IPv4Layer* ipv4Layer = packet->getLayerOfType<IPv4Layer>();
+	if (ipv4Layer != NULL)
+	{
+		if (portSrc == portDst && ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc)
+			srcPosition = 1;
+
+		vec[2 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc;
+		vec[2 + srcPosition].len = 4;
+		vec[3 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst;
+		vec[3 - srcPosition].len = 4;
+		vec[4].buffer = &(ipv4Layer->getIPv4Header()->protocol);
+		vec[4].len = 1;
+	}
+	else
+	{
+		IPv6Layer* ipv6Layer = packet->getLayerOfType<IPv6Layer>();
+		if (portSrc == portDst && (uint64_t)ipv6Layer->getIPv6Header()->ipDst < (uint64_t)ipv6Layer->getIPv6Header()->ipSrc)
+			srcPosition = 1;
+
+		vec[2 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc;
+		vec[2 + srcPosition].len = 16;
+		vec[3 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst;
+		vec[3 - srcPosition].len = 16;
+		vec[4].buffer = &(ipv6Layer->getIPv6Header()->nextHeader);
+		vec[4].len = 1;
+	}
+
+	return pcpp::fnv_hash(vec, 5);
+}
+
+
+uint32_t hash2Tuple(Packet* packet)
+{
+	if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6))
+		return 0;
+
+	ScalarBuffer<uint8_t> vec[2];
+
+	IPv4Layer* ipv4Layer = packet->getLayerOfType<IPv4Layer>();
+	if (ipv4Layer != NULL)
+	{
+		int srcPosition = 0;
+		if (ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc)
+			srcPosition = 1;
+
+		vec[0 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc;
+		vec[0 + srcPosition].len = 4;
+		vec[1 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst;
+		vec[1 - srcPosition].len = 4;
+	}
+	else
+	{
+		IPv6Layer* ipv6Layer = packet->getLayerOfType<IPv6Layer>();
+		int srcPosition = 0;
+		if ((uint64_t)ipv6Layer->getIPv6Header()->ipDst < (uint64_t)ipv6Layer->getIPv6Header()->ipSrc
+				&& (uint64_t)(ipv6Layer->getIPv6Header()->ipDst+8) < (uint64_t)(ipv6Layer->getIPv6Header()->ipSrc+8))
+			srcPosition = 1;
+
+		vec[0 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc;
+		vec[0 + srcPosition].len = 16;
+		vec[1 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst;
+		vec[1 - srcPosition].len = 16;
+	}
+
+	return pcpp::fnv_hash(vec, 2);
+}
+
+}  // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/PayloadLayer.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/PayloadLayer.cpp b/thirdparty/pcap++/Packet++/src/PayloadLayer.cpp
new file mode 100644
index 0000000..ddeb47e
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/PayloadLayer.cpp
@@ -0,0 +1,26 @@
+#define LOG_MODULE PacketLogModulePayloadLayer
+
+#include <PayloadLayer.h>
+#include <string.h>
+#include <sstream>
+
+namespace pcpp
+{
+
+PayloadLayer::PayloadLayer(const uint8_t* data, size_t dataLen, bool dummy) : Layer()
+{
+	m_Data = new uint8_t[dataLen];
+	memcpy(m_Data, data, dataLen);
+	m_DataLen = dataLen;
+	m_Protocol = GenericPayolad;
+}
+
+std::string PayloadLayer::toString()
+{
+	std::ostringstream dataLenStream;
+	dataLenStream << m_DataLen;
+
+	return "Payload Layer, Data length: " + dataLenStream.str() + " [Bytes]";
+}
+
+} // namespace pcpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c0a788b3/thirdparty/pcap++/Packet++/src/RawPacket.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/pcap++/Packet++/src/RawPacket.cpp b/thirdparty/pcap++/Packet++/src/RawPacket.cpp
new file mode 100644
index 0000000..17d73a8
--- /dev/null
+++ b/thirdparty/pcap++/Packet++/src/RawPacket.cpp
@@ -0,0 +1,200 @@
+#define LOG_MODULE PacketLogModuleRawPacket
+
+#include <RawPacket.h>
+#include <string.h>
+#include <Logger.h>
+
+namespace pcpp
+{
+
+void RawPacket::Init()
+{
+	m_pRawData = 0;
+	m_RawDataLen = 0;
+	m_DeleteRawDataAtDestructor = true;
+	m_RawPacketSet = false;
+	m_linkLayerType = LINKTYPE_ETHERNET;
+}
+
+RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType)
+{
+	Init();
+	m_DeleteRawDataAtDestructor = deleteRawDataAtDestructor;
+	setRawData(pRawData, rawDataLen, timestamp, layerType);
+}
+
+RawPacket::RawPacket()
+{
+	Init();
+}
+
+RawPacket::~RawPacket()
+{
+	if (m_DeleteRawDataAtDestructor)
+	{
+		delete[] m_pRawData;
+	}
+}
+
+RawPacket::RawPacket(const RawPacket& other)
+{
+	copyDataFrom(other);
+}
+
+RawPacket& RawPacket::operator=(const RawPacket& other)
+{
+	if (m_pRawData != NULL)
+		delete [] m_pRawData;
+
+	m_RawPacketSet = false;
+
+	copyDataFrom(other);
+
+	return *this;
+}
+
+
+void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData)
+{
+	if (!other.m_RawPacketSet)
+		return;
+
+	m_TimeStamp = other.m_TimeStamp;
+
+	if (allocateData)
+	{
+		m_DeleteRawDataAtDestructor = true;
+		m_pRawData = new uint8_t[other.m_RawDataLen];
+		m_RawDataLen = other.m_RawDataLen;
+	}
+
+	memcpy(m_pRawData, other.m_pRawData, other.m_RawDataLen);
+	m_linkLayerType = other.m_linkLayerType;
+	m_FrameLength = other.m_FrameLength;
+	m_RawPacketSet = true;
+}
+
+bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType, int frameLength)
+{
+	if(frameLength == -1)
+		frameLength = rawDataLen;
+	m_FrameLength = frameLength;
+	if (m_pRawData != 0 && m_DeleteRawDataAtDestructor)
+	{
+		delete[] m_pRawData;
+	}
+
+	m_pRawData = (uint8_t*)pRawData;
+	m_RawDataLen = rawDataLen;
+	m_TimeStamp = timestamp;
+	m_RawPacketSet = true;
+	m_linkLayerType = layerType;
+	return true;
+}
+
+const uint8_t* RawPacket::getRawData()
+{
+	return m_pRawData;
+}
+
+const uint8_t* RawPacket::getRawDataReadOnly() const
+{
+	return m_pRawData;
+}
+		
+LinkLayerType RawPacket::getLinkLayerType() const
+{
+	return m_linkLayerType;
+}
+
+int RawPacket::getRawDataLen() const
+{
+	return m_RawDataLen;
+}
+
+int RawPacket::getFrameLength() const
+{
+	return m_FrameLength;
+}
+
+timeval RawPacket::getPacketTimeStamp()
+{
+	return m_TimeStamp;
+}
+
+void RawPacket::clear()
+{
+	if (m_pRawData != 0)
+		delete[] m_pRawData;
+
+	m_pRawData = 0;
+	m_RawDataLen = 0;
+	m_FrameLength = 0;
+	m_RawPacketSet = false;
+}
+
+void RawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen)
+{
+	memcpy((uint8_t*)m_pRawData+m_RawDataLen, dataToAppend, dataToAppendLen);
+	m_RawDataLen += dataToAppendLen;
+	m_FrameLength = m_RawDataLen;
+}
+
+void RawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen)
+{
+	int index = m_RawDataLen-1;
+	while (index >= atIndex)
+	{
+		m_pRawData[index+dataToInsertLen] = m_pRawData[index];
+		index--;
+	}
+
+	memcpy((uint8_t*)m_pRawData+atIndex, dataToInsert, dataToInsertLen);
+	m_RawDataLen += dataToInsertLen;
+	m_FrameLength = m_RawDataLen;
+}
+
+bool RawPacket::reallocateData(size_t newBufferLength)
+{
+	if ((int)newBufferLength == m_RawDataLen)
+		return true;
+
+	if ((int)newBufferLength < m_RawDataLen)
+	{
+		LOG_ERROR("Cannot reallocate raw packet to a smaller size. Current data length: %d; requested length: %d", m_RawDataLen, (int)newBufferLength);
+		return false;
+	}
+
+	uint8_t* newBuffer = new uint8_t[newBufferLength];
+	memset(newBuffer, 0, newBufferLength);
+	memcpy(newBuffer, m_pRawData, m_RawDataLen);
+	if (m_DeleteRawDataAtDestructor)
+		delete [] m_pRawData;
+
+	m_DeleteRawDataAtDestructor = true;
+	m_pRawData = newBuffer;
+
+	return true;
+}
+
+bool RawPacket::removeData(int atIndex, size_t numOfBytesToRemove)
+{
+	if ((atIndex + (int)numOfBytesToRemove) > m_RawDataLen)
+	{
+		LOG_ERROR("Remove section is out of raw packet bound");
+		return false;
+	}
+
+	int index = atIndex;
+	while (index < (m_RawDataLen - (int)numOfBytesToRemove))
+	{
+		m_pRawData[index] = m_pRawData[index+numOfBytesToRemove];
+		index++;
+	}
+
+	m_RawDataLen -= numOfBytesToRemove;
+	m_FrameLength = m_RawDataLen;
+	return true;
+}
+
+} // namespace pcpp