#include "net.hpp"
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
// for convenience
typedef struct ether_header eth_hdr_t;
typedef struct ip ip_hdr_t;
typedef struct tcphdr tcp_hdr_t;
bool packet_s::parse(const struct timeval& t, const unsigned char* b, size_t l) {
// get ethernet hdr & skip to ip
if (l < sizeof(eth_hdr_t)) return false;
const eth_hdr_t* eth_hdr = (const eth_hdr_t*)b;
l -= sizeof(eth_hdr_t);
b += sizeof(eth_hdr_t);
// get src & dst from ip header and skip to tcp
if (ntohs(eth_hdr->ether_type) != ETHERTYPE_IP) return false;
if (l < sizeof(ip_hdr_t)) return false;
const ip_hdr_t* ip_hdr = (const ip_hdr_t*)b;
if (ip_hdr->ip_p != IPPROTO_TCP) return false;
l -= sizeof(ip_hdr_t);
b += sizeof(ip_hdr_t);
conn.src = ip_hdr->ip_src;
conn.dst = ip_hdr->ip_dst;
// tcp
if (l < sizeof(tcp_hdr_t)) return false;
const tcp_hdr_t* tcp_hdr = (const tcp_hdr_t*)b;
unsigned hdrlen = tcp_hdr->doff * 4; // specifies the size of the TCP header in 32-bit words
if (hdrlen < sizeof(tcp_hdr_t) || hdrlen > l || hdrlen > 60) { // 20 normal + max 40 options
LOG("invalid tcp options length %u (%zu)", hdrlen, l);
return false;
}
l -= hdrlen;
b += hdrlen;
conn.src_port = ntohs(tcp_hdr->source); // th_sport
conn.dst_port = ntohs(tcp_hdr->dest); // th_dport
// payload & done
conn.ts = (t.tv_sec * 1000 * 1000) + t.tv_usec;
syn = tcp_hdr->syn; // TODO: reassemble acc. to seq and frag
ack = tcp_hdr->ack;
fin = tcp_hdr->fin;
seq = htonl(tcp_hdr->seq);
buf = b;
len = l;
return true;
}