Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netmask function #99

Merged
merged 3 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions FUNCTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ 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]])

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

### RSPLIT(string, n [, char])
Expand Down
2 changes: 0 additions & 2 deletions src/dns.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
3 changes: 1 addition & 2 deletions src/packet_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
#include "sql.h"
#include "tcp.h"

#define IPPROTO_ICMP 1

namespace packetq {

class Table;
Expand Down Expand Up @@ -177,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
Original file line number Diff line number Diff line change
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
3 changes: 3 additions & 0 deletions src/sql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1881,6 +1881,9 @@ OP* OP::compile(const std::vector<Table*>& tables, const std::vector<int>& searc
} else if (cmpi(get_token(), "rsplit") && m_param[1]) {
m_t = Coltype::_text;
ret = new Rsplit_func(*this);
} else if (cmpi(get_token(), "netmask")) {
m_t = Coltype::_text;
ret = new Netmask_func(*this);
} else if (cmpi(get_token(), "count")) {
m_t = Coltype::_int;
ret = new Count_func(*this, dest_table);
Expand Down
89 changes: 89 additions & 0 deletions src/sql.h
Original file line number Diff line number Diff line change
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
18 changes: 6 additions & 12 deletions src/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +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
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#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
Original file line number Diff line number Diff line change
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.
108 changes: 108 additions & 0 deletions src/test/test1.gold
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,111 @@
]
}
]
[
{
"table_name": "result-0",
"query": "select netmask(src_addr), netmask(dst_addr, 8, 16) from dns",
"head": [
{ "name": "netmask(src_addr)","type": "text" },
{ "name": "netmask(dst_addr,8,16)","type": "text" }
],
"data": [
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"],
["172.17.0.0","8.0.0.0"],
["8.8.8.0","172.0.0.0"]
]
}
]
[
{
"table_name": "result-0",
"query": "select netmask(src_addr), netmask(dst_addr, 8, 16) from dns",
"head": [
{ "name": "netmask(src_addr)","type": "text" },
{ "name": "netmask(dst_addr,8,16)","type": "text" }
],
"data": [
["2a01:3f0::","2001::"],
["2001:4860:4860::","2a01::"]
]
}
]
4 changes: 4 additions & 0 deletions src/test/test1.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@

../packetq -j -s "select s, dst_addr as Dst_addr, qtype as questiontype, lower(src_addr) as lower_src, if(1 and s < 1 or s <= 1 or s > 1 or s >= 1, 't', 'f'), trim(trim('foofoo' || rsplit(src_addr, 1) || 'foofoo', 'foo'), 'bar'), count(*), len(src_addr), sum(msg_size + -1 - 2 % 4 << 3 >> 2 | 3 & ~4) + 1, min(msg_size), max(msg_size), truncate(1.1) as integer, 1.1 as float, sum(src_port + 1.0 - 2.0 / 1.5 * -2.5) + 1.0, max(src_port + 1.0), min(src_port + 1.0), avg(src_port), stdev(src_port), name('rcode', 0) from dns where src_addr like '%' and (qr or not qr) group by src_addr, s having s >= 0 order by s, lower_src, integer, float" "$srcdir/../../pcap/sample.pcap.gz" > test1.out

../packetq -j -s "select netmask(src_addr), netmask(dst_addr, 8, 16) from dns" "$srcdir/dns.pcap" >>test1.out

../packetq -j -s "select netmask(src_addr), netmask(dst_addr, 8, 16) from dns" "$srcdir/dns6.pcap" >>test1.out

diff -uw "$srcdir/test1.gold" test1.out