1 /*
2  * Copyright (c) 2017, OARC, Inc.
3  * Copyright (c) 2011-2017, IIS - The Internet Foundation in Sweden
4  * All rights reserved.
5  *
6  * This file is part of PacketQ.
7  *
8  * PacketQ is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * PacketQ is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with PacketQ.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef __packetq_packet_handler_h
23 #define __packetq_packet_handler_h
24 
25 #include <assert.h>
26 #include <cctype>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <string>
31 #include <vector>
32 
33 #include "sql.h"
34 #include "tcp.h"
35 
36 #define IPPROTO_ICMP 1
37 
38 namespace packetq {
39 
40 class Table;
41 class Row;
42 
get_int_h(unsigned char * data)43 inline int get_int_h(unsigned char* data)
44 {
45     return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
46 }
47 
get_short_h(unsigned char * data)48 inline int get_short_h(unsigned char* data)
49 {
50     return data[0] | (data[1] << 8);
51 }
52 
get_int(unsigned char * data)53 inline int get_int(unsigned char* data)
54 {
55     return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
56 }
57 
get_short(unsigned char * data)58 inline int get_short(unsigned char* data)
59 {
60     return data[1] | (data[0] << 8);
61 }
62 
63 RefCountString* v4_addr2str(in6addr_t& addr);
64 RefCountString* v6_addr2str(in6addr_t& addr);
65 
66 class Payload {
67 public:
68     char m_p[0x10000];
69     int  m_size;
Payload()70     Payload()
71     {
72         m_size = sizeof(m_p);
73     }
alloc(int size)74     inline char* alloc(int size)
75     {
76         if (size > m_size)
77             return 0;
78         return m_p;
79     }
80 };
81 
82 class IP_header {
83 public:
IP_header()84     IP_header()
85         : s(0)
86         , us(0)
87         , ethertype(0)
88         , src_port(0)
89         , dst_port(0)
90         , proto(0)
91         , ip_ttl(0)
92         , ip_version(0)
93         , id(0)
94         , length(0)
95         , fragments(0)
96         , ident(0)
97         , offset(0)
98     {
99         memset(&src_ip, 0, sizeof(src_ip));
100         memset(&dst_ip, 0, sizeof(dst_ip));
101     }
102 
103     void reset();
104     int decode(unsigned char* data, int ether_type, int id);
105     unsigned int   s;
106     unsigned int   us;
107     unsigned short ethertype;
108     in6addr_t      src_ip;
109     in6addr_t      dst_ip;
110     unsigned short src_port;
111     unsigned short dst_port;
112     unsigned short proto;
113     unsigned short ip_ttl;
114     unsigned short ip_version;
115     unsigned int   id;
116     unsigned int   length;
117     unsigned int   fragments;
118     unsigned int   ident;
119     unsigned int   offset;
120 };
121 
122 class Packet_handler;
123 
124 class IP_header_to_table {
125 public:
126     enum {
127         COLUMN_ID,
128         COLUMN_S,
129         COLUMN_US,
130         COLUMN_ETHER_TYPE,
131         COLUMN_PROTOCOL,
132         COLUMN_IP_TTL,
133         COLUMN_IP_VERSION,
134         COLUMN_SRC_PORT,
135         COLUMN_DST_PORT,
136         COLUMN_SRC_ADDR,
137         COLUMN_DST_ADDR,
138         COLUMN_FRAGMENTS
139     };
140 
141     void add_packet_columns(Packet_handler& packet_handler);
142     void on_table_created(Table* table, const std::vector<int>& columns);
143     void assign(Row* row, IP_header* head, const std::vector<int>& columns);
144 
145 private:
146     Int_accessor  acc_id;
147     Int_accessor  acc_s;
148     Int_accessor  acc_us;
149     Int_accessor  acc_ether_type;
150     Int_accessor  acc_protocol;
151     Int_accessor  acc_ip_ttl;
152     Int_accessor  acc_ip_version;
153     Int_accessor  acc_src_port;
154     Int_accessor  acc_dst_port;
155     Int_accessor  acc_fragments;
156     Text_accessor acc_src_addr;
157     Text_accessor acc_dst_addr;
158 };
159 
160 class Packet {
161 public:
162     enum ParseResult {
163         ERROR,
164         OK,
165         NOT_SAMPLED
166     };
167 
Packet(unsigned char * data,int len,int s,int us,int id,int link_layer_type)168     Packet(unsigned char* data, int len, int s, int us, int id, int link_layer_type)
169     {
170         m_s               = s;
171         m_us              = us;
172         m_data            = data;
173         m_len             = len;
174         m_id              = id;
175         m_link_layer_type = link_layer_type;
176     }
177 
178     ParseResult parse(Packet_handler* handler, const std::vector<int>& columns, Row& destination_row, bool sample);
179     bool parse_ethernet();
180     bool parse_ip(unsigned char* data, int len, int ether_type);
181     bool parse_transport(unsigned char* data, int len);
182 
183     IP_header      m_ip_header;
184     unsigned char* m_data;
185     int            m_len;
186     int            m_s;
187     int            m_us;
188     int            m_id;
189     int            m_link_layer_type;
190 };
191 
192 struct Packet_column {
193     const char*   name;
194     const char*   description;
195     int           id;
196     Coltype::Type type;
197 };
198 
199 class Packet_handler {
200 public:
Packet_handler()201     Packet_handler()
202         : table_name(0)
203     {
204     }
~Packet_handler()205     virtual ~Packet_handler()
206     {
207     }
208 
209     Table* create_table(const std::vector<int>& columns);
210 
211     // for actual packet handlers to fill in
212     virtual void on_table_created(Table* table, const std::vector<int>& columns) = 0;
213     virtual Packet::ParseResult parse(Packet& packet, const std::vector<int>& columns, Row& destination_row, bool sample) = 0;
214 
215     const char*                table_name;
216     std::vector<Packet_column> packet_columns;
217 
218     void add_packet_column(const char* name, const char* description, Coltype::Type type, int id);
219 };
220 
221 void            init_packet_handlers();
222 void            destroy_packet_handlers();
223 Packet_handler* get_packet_handler(std::string table_name);
224 
225 } // namespace packetq
226 
227 #endif // __packetq_packet_handler_h
228