1

In PCap++, I want to detect if a payload is an HTTP request or not. For this, I am trying to parse the string and expect the library to allows me to check if this was done successfully.

Unfortunately, I was unable to achieve this:

  • I can create a RawPacket with the message
  • I can create a Packet with the message, but it does not contains any HttpRequestLayer, in consequence, the parsing is useless to detect the validity of the message.
  • I cannot create an HttpRequestLayer directly from the message.

Some examples:

std::string msg= "GET /index.html HTTP/1.1\nHost: example.com\n\n";

// Try to get a RawPacket: works, but does not helps a lot
struct timeval tp; // requires <time.h>
gettimeofday(&tp, nullptr);
RawPacket rp(static_cast<const uint8_t*>(msg.data()), static_cast<int>(msg.size()), tp, false);

// Trying to parse it: works but detect generic Newtork layer only, no HTTP
Packet p(&rp, false, HTTP);

// Trying to create an HttpRequestLayer directly: crash
HttpRequestLayer http(static_cast<const uint8_t*>(msg.data()), static_cast<int>(msg.size()), nullptr, nullptr);

My question is:

How to detect if a message is a valid HTTP message with PCap++?

Note: I am looking for an efficient solution (very sub-optimal solutions, like generating TCP layers is not an option).

Adrian Maire
  • 14,354
  • 9
  • 45
  • 85

2 Answers2

0

PcapPlusPlus can parse packets, not messages. A RawPacket object expects a stream of bytes that represent a network packet, typically with a data link layer (e.g Ethernet), network layer (e.g IP), transport layer (e.g TCP) and application layer (HTTP in this case). PcapPlusPlus will parse this byte stream into the a list of layers/protocols you can look into.

HTTP is an application protocol, hence any HTTP packet will contain the other layers mentioned above. So providing just the HTTP message is not enough and PcapPlusPlus won't be able to parse it as a packet.

You can learn more about PcapPlusPlus from the tutorials: https://pcapplusplus.github.io/docs/tutorials

Specifically you can look into the packet parsing tutorial: https://pcapplusplus.github.io/docs/tutorials/packet-parsing

seladb
  • 852
  • 1
  • 13
  • 29
0

pcpp::Packet has a method of getting layer you need - getLayerOfType. You could detect HTTP message using it. Example:

timeval tm;
gettimeofday(&tm, NULL);
pcpp::RawPacket rawPacket((uint8_t*)rawPacketFromNet.data(), rawPacketFromNet.size(), tm, false, pcpp::LinkLayerType::LINKTYPE_RAW);
    
pcpp::Packet parsedPacket(&rawPacket);

pcpp::HttpRequestLayer* httpLayer = parsedPacket.getLayerOfType<pcpp::HttpRequestLayer>();

if (httpLayer)
{
// you have this layer in your packet
 uint8_t* dataPtr = httpLayer->getData();
 size_t size = httpLayer->getDataLen(); 
}

I think your example could have worked if you'd start with pcpp::Packet and then add to it http layer. For constructing http layer in your case try to use HttpRequestLayer(HttpMethod method, std::string uri, HttpVersion version);

Ophir Carmi
  • 2,701
  • 1
  • 23
  • 42
olle
  • 61
  • 1
  • 1
  • 4
  • getLayerOfType just return the existing layer of the given type right? The problem is that, parsedPacket contains only the generic network layer. (This is because the rawPacket is an HTTP payload, without wrapping network layers, so PCPP cannot parse it correctly) – Adrian Maire Nov 26 '20 at 08:58