1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color:/*
// Copyright (c) 2010-2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include <pcap.h>
#include <inttypes.h>
#include <cstring>
#include <arpa/inet.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include "allocator.hpp"
#include "pcappkt.hpp"
Allocator *PcapPkt::allocator = NULL;
void* PcapPkt::operator new(size_t size)
{
if (allocator)
return allocator->alloc(size);
else
return ::operator new(size);
}
void PcapPkt::operator delete(void *pointer)
{
if (!allocator)
:: operator delete(pointer);
}
PcapPkt::PcapPkt(uint8_t *mem)
{
header = *(struct pcap_pkthdr *)mem;
mem += sizeof(header);
buf = new uint8_t[header.len];
memcpy(buf, mem, header.len);
}
PcapPkt::PcapPkt()
{
buf = new uint8_t[1514];
memset(&header, 0, sizeof(header));
}
PcapPkt::PcapPkt(const PcapPkt& other)
{
if (!allocator) {
buf = new uint8_t[other.len()];
}
else {
buf = (uint8_t *)allocator->alloc(other.len());
}
memcpy(buf, other.buf, other.len());
header = other.header;
}
PcapPkt::~PcapPkt()
{
if (!allocator)
delete[] buf;
}
#define ETYPE_IPv4 0x0008 /* IPv4 in little endian */
#define ETYPE_IPv6 0xDD86 /* IPv6 in little endian */
#define ETYPE_ARP 0x0608 /* ARP in little endian */
#define ETYPE_VLAN 0x0081 /* 802-1aq - VLAN */
#define ETYPE_MPLSU 0x4788 /* MPLS unicast */
#define ETYPE_MPLSM 0x4888 /* MPLS multicast */
#define ETYPE_8021ad 0xA888 /* Q-in-Q */
#define ETYPE_LLDP 0xCC88 /* Link Layer Discovery Protocol (LLDP) */
#define ETYPE_EoGRE 0x5865 /* EoGRE in little endian */
struct ipv4_hdr {
uint8_t version_ihl; /**< version and header length */
uint8_t type_of_service; /**< type of service */
uint16_t total_length; /**< length of packet */
uint16_t packet_id; /**< packet ID */
uint16_t fragment_offset; /**< fragmentation offset */
uint8_t time_to_live; /**< time to live */
uint8_t next_proto_id; /**< protocol ID */
uint16_t hdr_checksum; /**< header checksum */
uint32_t src_addr; /**< source address */
uint32_t dst_addr; /**< destination address */
} __attribute__((__packed__));
struct ether_addr {
uint8_t addr_bytes[6]; /**< Address bytes in transmission order */
} __attribute__((__packed__));
struct ether_hdr {
struct ether_addr d_addr; /**< Destination address. */
struct ether_addr s_addr; /**< Source address. */
uint16_t ether_type; /**< Frame type. */
} __attribute__((__packed__));
struct vlan_hdr {
uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */
uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */
} __attribute__((__packed__));
struct udp_hdr {
uint16_t src_port; /**< UDP source port. */
uint16_t dst_port; /**< UDP destination port. */
uint16_t dgram_len; /**< UDP datagram length */
uint16_t dgram_cksum; /**< UDP datagram checksum */
} __attribute__((__packed__));
struct pkt_tuple PcapPkt::parsePkt(const uint8_t **l4_hdr, uint16_t *hdr_len, const uint8_t **l5, uint32_t *l5_len) const
{
struct pkt_tuple pt = {0};
const struct ether_hdr *peth = (struct ether_hdr *)buf;
int l2_types_count = 0;
const struct ipv4_hdr* pip = 0;
switch (peth->ether_type) {
case ETYPE_IPv4:
pip = (const struct ipv4_hdr *)(peth + 1);
break;
case ETYPE_VLAN: {
const struct vlan_hdr *vlan = (const struct vlan_hdr *)(peth + 1);
if (vlan->eth_proto == ETYPE_IPv4) {
pip = (const struct ipv4_hdr *)(peth + 1);
}
else if (vlan->eth_proto == ETYPE_VLAN) {
const struct vlan_hdr *vlan = (const struct vlan_hdr *)(peth + 1);
if (vlan->eth_proto == ETYPE_IPv4) {
pip = (const struct ipv4_hdr *)(peth + 1);
}
else if (vlan->eth_proto == ETYPE_IPv6) {
throw 0;
}
else {
/* TODO: handle BAD PACKET */
throw 0;
}
}
}
break;
case ETYPE_8021ad: {
const struct vlan_hdr *vlan = (const struct vlan_hdr *)(peth + 1);
if (vlan->eth_proto == ETYPE_VLAN) {
const struct vlan_hdr *vlan = (const struct vlan_hdr *)(peth + 1);
if (vlan->eth_proto == ETYPE_IPv4) {
pip = (const struct ipv4_hdr *)(peth + 1);
}
else {
throw 0;
}
}
else {
throw 0;
}
}
break;
case ETYPE_MPLSU:
break;
default:
break;
}
/* L3 */
if ((pip->version_ihl >> 4) == 4) {
if ((pip->version_ihl & 0x0f) != 0x05) {
/* TODO: optional fields */
throw 0;
}
pt.proto_id = pip->next_proto_id;
pt.src_addr = pip->src_addr;
pt.dst_addr = pip->dst_addr;
}
else {
/* TODO: IPv6 and bad packets */
throw 0;
}
/* L4 parser */
if (pt.proto_id == IPPROTO_UDP) {
const struct udp_hdr *udp = (const struct udp_hdr*)(pip + 1);
if (l4_hdr)
*l4_hdr = (const uint8_t*)udp;
if (hdr_len)
*hdr_len = (const uint8_t*)udp - buf;
pt.src_port = udp->src_port;
pt.dst_port = udp->dst_port;
if (l5)
*l5 = ((const uint8_t*)udp) + sizeof(struct udp_hdr);
if (l5_len)
*l5_len = ntohs(udp->dgram_len) - sizeof(struct udp_hdr);
}
else if (pt.proto_id == IPPROTO_TCP) {
const struct tcp_hdr *tcp = (const struct tcp_hdr *)(pip + 1);
if (l4_hdr)
*l4_hdr = (const uint8_t*)tcp;
if (hdr_len)
*hdr_len = (const uint8_t*)tcp - buf;
pt.src_port = tcp->src_port;
pt.dst_port = tcp->dst_port;
if (l5)
*l5 = ((const uint8_t*)tcp) + ((tcp->data_off >> 4)*4);
if (l5_len)
*l5_len = ntohs(pip->total_length) - sizeof(struct ipv4_hdr) - ((tcp->data_off >> 4)*4);
}
else {
fprintf(stderr, "unsupported protocol %d\n", pt.proto_id);
throw 0;
}
return pt;
}
void PcapPkt::toMem(uint8_t *mem) const
{
memcpy(mem, &header, sizeof(header));
mem += sizeof(header);
memcpy(mem, buf, header.len);
}
void PcapPkt::fromMem(uint8_t *mem)
{
memcpy(&header, mem, sizeof(header));
mem += sizeof(header);
memcpy(buf, mem, header.len);
}
void PcapPkt::toFile(ofstream *file) const
{
file->write(reinterpret_cast<const char *>(&header), sizeof(header));
file->write(reinterpret_cast<const char *>(buf), header.len);
}
size_t PcapPkt::memSize() const
{
return sizeof(header) + header.len;
}
PcapPkt::L4Proto PcapPkt::getProto() const
{
struct pkt_tuple pt = parsePkt();
return pt.proto_id == IPPROTO_TCP? PROTO_TCP : PROTO_UDP;
}
ostream& operator<<(ostream& stream, const pkt_tuple &other)
{
stream << other.src_addr << ","
<< other.dst_addr << ","
<< (int)other.proto_id << ","
<< other.src_port << ","
<< other.dst_port;
return stream;
}
|