Skip to content

Commit

Permalink
LINUX_SLL, netmask(), ether types
Browse files Browse the repository at this point in the history
- Add support for Pcap's LINUX_SLL link layer
- `packet_handler`: Clean up header parsing, size checks etc
- Fix up `netmask()` code and documentation
- Remove own defines of ether/proto types and don't overlap `struct in6_addr`
  • Loading branch information
jelu committed Jan 31, 2022
1 parent d847c97 commit ae211e6
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 103 deletions.
7 changes: 5 additions & 2 deletions FUNCTIONS.md
Expand Up @@ -42,9 +42,12 @@ Converts double precision number to integer.
Evaluates `condition` and executes `false_op` if the result is 0 (false)
otherwise `true_op` is executed.

### NETMASK (address[, v4_mask_length[, v6_mask_length]])
### NETMASK(address [, v4_mask_length [, v6_mask_length]])

Masks the specified address using the v4 and v6 mask lengths specified in number of bits. Defaults to 24 for IPv4 and 48 for IPv6 (/24 and /48 respectively)
Masks the specified address using the v4 and v6 mask lengths specified
in number of bits.

Defaults to 24 for IPv4 and 48 for IPv6 (/24 and /48 respectively)

## String operations

Expand Down
2 changes: 0 additions & 2 deletions src/dns.h
Expand Up @@ -31,8 +31,6 @@
#include "packet_handler.h"
#include "tcp.h"

#define IPPROTO_ICMP 1

namespace packetq {

extern char visible_char_map[256];
Expand Down
31 changes: 28 additions & 3 deletions src/packet_handler.cpp
Expand Up @@ -277,6 +277,8 @@ Packet::ParseResult Packet::parse(Packet_handler* handler, const std::vector<int
bool base_layers_parsed;
if (m_link_layer_type == 1)
base_layers_parsed = parse_ethernet();
else if (m_link_layer_type == 113)
base_layers_parsed = parse_sll();
else
base_layers_parsed = parse_ip(m_data, m_len, 0);

Expand All @@ -291,12 +293,13 @@ bool Packet::parse_ethernet()
{
unsigned char* data = m_data;
int len = m_len;
if (len < 14 + 5 * 4)
return false; // check for etherframe size + ipv4 header
if (len < 14)
return false; // check for etherframe size

int ethertype = data[13] | (data[12] << 8);
if (ethertype == 0x8100) {
// VLAN-tagged
if (len < 18)
return false; // check for etherframe size + VLAN tag
ethertype = data[17] | (data[16] << 8);
data += 18;
len -= 18;
Expand All @@ -308,6 +311,28 @@ bool Packet::parse_ethernet()
return parse_ip(data, len, ethertype);
}

bool Packet::parse_sll()
{
unsigned char* data = m_data;
int len = m_len;
if (len < 16)
return false; // check for LINUX_SLL size

int ethertype = data[15] | (data[14] << 8);
if (ethertype == 0x8100) {
if (len < 20)
return false; // check for etherframe size + VLAN tag
ethertype = data[19] | (data[18] << 8);
data += 20;
len -= 20;
} else {
data += 16;
len -= 16;
}

return parse_ip(data, len, ethertype);
}

bool Packet::parse_ip(unsigned char* data, int len, int ethertype)
{
if (len < 5 * 4)
Expand Down
5 changes: 1 addition & 4 deletions src/packet_handler.h
Expand Up @@ -33,10 +33,6 @@
#include "sql.h"
#include "tcp.h"

#ifndef IPPROTO_ICMP
#define IPPROTO_ICMP 1
#endif

namespace packetq {

class Table;
Expand Down Expand Up @@ -179,6 +175,7 @@ class Packet {

ParseResult parse(Packet_handler* handler, const std::vector<int>& columns, Row& destination_row, bool sample);
bool parse_ethernet();
bool parse_sll();
bool parse_ip(unsigned char* data, int len, int ether_type);
bool parse_transport(unsigned char* data, int len);

Expand Down
2 changes: 1 addition & 1 deletion src/pcap.cpp
Expand Up @@ -61,7 +61,7 @@ bool Pcap_file::get_header()
m_snapshot_length = get_int32();
// check for ethernet packets
m_link_layer_type = get_int32();
if (m_link_layer_type != 1 && m_link_layer_type != 101) {
if (m_link_layer_type != 1 && m_link_layer_type != 101 && m_link_layer_type != 113) {
fprintf(stderr, "PCAP file unsupported linklayer (%d)\n", m_link_layer_type);
return false;
}
Expand Down
74 changes: 0 additions & 74 deletions src/sql.cpp
Expand Up @@ -20,7 +20,6 @@
*/

#include "sql.h"
#include <arpa/inet.h>
#include "output.h"
#include "packet_handler.h"
#include "packetq.h"
Expand All @@ -39,79 +38,6 @@ bool verbose = false;

int g_allocs = 0;

class Netmask_func : public OP {
public:
Netmask_func (const OP& op) : OP(op) {}
void evaluate (Row **rows, Variant& v) {
Variant orig_ip;
struct in_addr a4;
struct in6_addr a6;
int ret = 0, isv4 = 1;

m_param[0]->evaluate (rows, orig_ip);
if (!valid_masks) set_masks (rows);

RefCountStringHandle src(orig_ip.get_text());
RefCountStringHandle dest(RefCountString::allocate(INET6_ADDRSTRLEN));

ret = inet_pton (AF_INET, (*src)->data, (void *)&a4);
if (ret == 0) {
isv4 = 0;
ret = inet_pton (AF_INET6, (*src)->data, (void *)&a6);
}
if (ret != 1) {
// Operation on non-IP address text
RefCountStringHandle empty(RefCountString::construct(""));
v = *empty;
return;
}
if (isv4) {
uint32_t *_x = (uint32_t *)&a4;
*_x = *_x & v4_mask;
(void) inet_ntop (AF_INET, (void *)&a4, (*dest)->data, INET6_ADDRSTRLEN);
} else {
uint32_t *_x = (uint32_t *)&a6;
for (int i=0; i < 4; i++)
_x[i] = _x[i] & v6_mask[i];
(void) inet_ntop (AF_INET6, (void *)&a6, (*dest)->data, INET6_ADDRSTRLEN);
}
v = *dest;
return;
}
private :
void set_masks (Row **rows) {
int v4size = 24;
int v6size = 48;
if (m_param[1] != NULL) {
Variant v4cidr;
m_param[1]->evaluate(rows, v4cidr);
v4size = v4cidr.get_int();
if (m_param[2] != NULL) {
Variant v6cidr;
m_param[2]->evaluate(rows, v6cidr);
v6size = v6cidr.get_int();
}
}
if (v4size > 0)
v4_mask = htonl ((int32_t) 0x80000000 >> (v4size - 1));
if (v6size > 0) {
for (int i = 0; i < 4; i++) {
if (v6size >= 32)
v6_mask[i] = 0xffffffff;
else
v6_mask[i] = htonl ((int32_t)0x80000000 >> (v6size - 1));
v6size -= 32;
if (v6size <= 0) break;
}
}
valid_masks = true;
return;
}
uint32_t v4_mask = 0;
uint32_t v6_mask[4] = {0,0,0,0};
bool valid_masks = false;
};

Column* Table::add_column(const char* name, const char* type, int id, bool hidden)
{
if (!type)
Expand Down
89 changes: 89 additions & 0 deletions src/sql.h
Expand Up @@ -38,6 +38,12 @@
#include <string>
#include <sys/types.h>
#include <vector>
#include <arpa/inet.h>
#include <netinet/in.h>
#ifndef s6_addr32 // For *BSD
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#include <sys/socket.h>

#include "refcountstring.h"
#include "variant.h"
Expand Down Expand Up @@ -796,6 +802,89 @@ class Static_text : public OP {
};

///////////////// Functions

class Netmask_func : public OP {
public:
Netmask_func(const OP& op)
: OP(op)
{
}
void evaluate(Row** rows, Variant& v)
{
Variant orig_ip;
m_param[0]->evaluate(rows, orig_ip);

if (!valid_masks)
set_masks(rows);

RefCountStringHandle src(orig_ip.get_text());
RefCountStringHandle dest(RefCountString::allocate(INET6_ADDRSTRLEN + 1));

if (strchr((*src)->data, ':')) {
struct in6_addr a6;
if (inet_pton(AF_INET6, (*src)->data, &a6) == 1) {
a6.s6_addr32[0] &= v6_mask[0];
a6.s6_addr32[1] &= v6_mask[1];
a6.s6_addr32[2] &= v6_mask[2];
a6.s6_addr32[3] &= v6_mask[3];
if (inet_ntop(AF_INET6, &a6, (*dest)->data, INET6_ADDRSTRLEN)) {
v = *dest;
return;
}
}
} else {
struct in_addr a4;
if (inet_pton(AF_INET, (*src)->data, &a4) == 1) {
a4.s_addr &= v4_mask;
if (inet_ntop(AF_INET, &a4, (*dest)->data, INET6_ADDRSTRLEN)) {
v = *dest;
return;
}
}
}

// Operation on non-IP address text
RefCountStringHandle empty(RefCountString::construct(""));
v = *empty;
}

private:
void set_masks(Row** rows)
{
if (m_param[1]) {
Variant v4cidr;
m_param[1]->evaluate(rows, v4cidr);
int v4size = v4cidr.get_int();
if (v4size > -1 && v4size < 33) {
v4_mask = htonl(0xffffffff << (32 - v4size));
}
}
if (m_param[2]) {
Variant v6cidr;
m_param[2]->evaluate(rows, v6cidr);
int v6size = v6cidr.get_int();
if (v6size > -1 && v6size < 129) {
for (int i = 0; i < 4; i++) {
if (v6size >= 32) {
v6_mask[i] = 0xffffffff;
v6size -= 32;
} else if (v6size) {
v6_mask[i] = htonl(0xffffffff << (32 - v6size));
v6size = 0;
} else {
v6_mask[i] = 0;
}
}
}
}
valid_masks = true;
}

uint32_t v4_mask = htonl(0xffffff00);
uint32_t v6_mask[4] = { 0xffffffff, htonl(0xffff0000), 0, 0 };
bool valid_masks = false;
};

class Truncate_func : public OP {
public:
Truncate_func(const OP& op)
Expand Down
22 changes: 6 additions & 16 deletions src/tcp.h
Expand Up @@ -23,29 +23,19 @@
#define __packetq_tcp_h

#include <stdio.h>

// Hack for Linux which does not include this in ethernet.h/ethertypes.h
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6 0x86dd
#endif
#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6
#endif
#ifndef IPPROTO_UDP
#define IPPROTO_UDP 17
#endif
#include <stdint.h>

namespace packetq {

struct in6_addr {
struct _in6_addr {
union {
unsigned char __u6_addr8[16];
unsigned short __u6_addr16[8];
unsigned int __u6_addr32[4];
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
} __in6_u; /* 128-bit IP6 address */
};

typedef struct in6_addr in6addr_t;
typedef struct _in6_addr in6addr_t;

class Payload;

Expand Down
3 changes: 2 additions & 1 deletion src/test/Makefile.am
Expand Up @@ -28,4 +28,5 @@ TESTS = test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh test7.sh \

EXTRA_DIST = $(TESTS) \
test1.gold test2.gold test3.gold test4.gold test5.gold test6.gold \
test7.gold sql.txt test8.gold
test7.gold sql.txt test8.gold \
dns.pcap dns6.pcap
Binary file added src/test/dns.pcap
Binary file not shown.
Binary file added src/test/dns6.pcap
Binary file not shown.

0 comments on commit ae211e6

Please sign in to comment.