summaryrefslogtreecommitdiff
path: root/scanner/packet_based_scanner.c
diff options
context:
space:
mode:
Diffstat (limited to 'scanner/packet_based_scanner.c')
-rw-r--r--scanner/packet_based_scanner.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/scanner/packet_based_scanner.c b/scanner/packet_based_scanner.c
new file mode 100644
index 0000000..a2ad540
--- /dev/null
+++ b/scanner/packet_based_scanner.c
@@ -0,0 +1,357 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stellar/utils.h"
+#include "stellar/packet.h"
+
+#include "scanner_maat.h"
+#include "attribute_kv.h"
+#include "attribute_schema.h"
+#include "scanner_module.h"
+#include "packet_based_scanner.h"
+
+struct packet_scanner
+{
+ int exdata_idx;
+};
+
+int32_t is_duplicate_tag_uuid(uuid_t *tag_uuids, size_t tag_uuids_num, uuid_t tag_uuid)
+{
+ if(tag_uuids==NULL || tag_uuids_num==0)
+ {
+ return FALSE;
+ }
+
+ for(size_t i=0; i<tag_uuids_num; i++)
+ {
+ if(uuid_compare(tag_uuids[i], tag_uuid)==0)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void ip4_format_to_maat(const struct ip *ip4, struct ip_addr *c_net_addr, struct ip_addr *s_net_addr)
+{
+ if(ip4==NULL || c_net_addr==NULL || s_net_addr==NULL)
+ {
+ return ;
+ }
+
+ c_net_addr->ip_type=4;
+ s_net_addr->ip_type=4;
+ c_net_addr->ipv4=ip4->ip_src.s_addr;
+ s_net_addr->ipv4=ip4->ip_dst.s_addr;
+}
+
+static void ip6_format_to_maat(const struct ip6_hdr *ip6, struct ip_addr *c_net_addr, struct ip_addr *s_net_addr)
+{
+ if(ip6==NULL || c_net_addr==NULL || s_net_addr==NULL)
+ {
+ return ;
+ }
+
+ c_net_addr->ip_type=6;
+ s_net_addr->ip_type=6;
+ memcpy(c_net_addr->ipv6, ip6->ip6_src.s6_addr, sizeof(c_net_addr->ipv6));
+ memcpy(s_net_addr->ipv6, ip6->ip6_dst.s6_addr, sizeof(s_net_addr->ipv6));
+}
+
+// static void packet_scanner_exdata_free(int idx __unused, void *ex_ptr, void *arg __unused)
+// {
+// if(ex_ptr==NULL)return;
+// FREE(ex_ptr);
+// }
+
+const struct utable_kv *packet_scanner_get_attribute(struct packet_scanner *pkt_scanner, struct packet *pkt, enum ATTRIBUTE_KV_INDEX index)
+{
+ if(pkt_scanner==NULL || pkt==NULL || index>=ATTRIBUTE_KV_MAX || index<=ATTRIBUTE_KV_UNKNOWN)
+ {
+ return NULL;
+ }
+
+ return attribute_kv_get((struct attribute_kv *)packet_get_exdata(pkt, pkt_scanner->exdata_idx), index);
+}
+
+void attribute_scratch_scan(struct scanner_maat *cm_maat, struct maat_state *scan_state, const char *readable_addr, struct maat_stream **stream_handle, struct attribute_scratch *attribute, size_t n_attribute)
+{
+ if(cm_maat==NULL || scan_state==NULL || attribute==NULL || n_attribute==0)
+ {
+ return ;
+ }
+
+ for(size_t i=0; i<n_attribute; i++)
+ {
+ if(attribute[i].schema==NULL)
+ {
+ continue;
+ }
+
+ switch(attribute[i].value_type)
+ {
+ case ATTRIBUTE_VALUE_TYPE_STRING:
+ scanner_scan_string_attribute(cm_maat, scan_state, attribute[i].string.value, readable_addr, attribute[i].schema->scan_attribute_name, attribute[i].string.value_sz);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_INTEGER:
+ scanner_scan_integer_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, attribute[i].integer);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_FLAG:
+ scanner_scan_flag_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, attribute[i].flag);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_MAAT_OBJECT:
+ scanner_scan_object_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, attribute[i].maat_object.object_uuid, attribute[i].maat_object.item_uuid, attribute[i].maat_object.n_uuid);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_IPV4:
+ scanner_scan_ipv4_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, attribute[i].ipv4_port.ipv4, attribute[i].ipv4_port.port);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_IPV6:
+ scanner_scan_ipv6_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, (uint8_t *)(attribute[i].ipv6_port.ipv6), attribute[i].ipv6_port.port);
+ break;
+ case ATTRIBUTE_VALUE_TYPE_NOT_LOGIC:
+ scanner_scan_stream_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name, stream_handle, attribute[i].chunk.value, attribute[i].chunk.value_sz);
+ break;
+ default:
+ break;
+ }
+
+ if(attribute[i].schema->scan_not_logic_flag==TRUE)
+ {
+ scanner_scan_not_logic_attribute(cm_maat, scan_state, readable_addr, attribute[i].schema->scan_attribute_name);
+ }
+ }
+}
+
+size_t ipaddr_entry_tag_uuid_get(struct scanner_maat *cm_maat, struct ip_addr *net_ipaddr, uuid_t *tag_uuids, size_t n_tag_uuids)
+{
+ size_t n_ipaddr_exdata=n_tag_uuids;
+ struct plugin_entry *ipaddr_exdata[n_ipaddr_exdata];
+ int n_exdata=scanner_maat_get0_data_ipaddr_entry(cm_maat, net_ipaddr, ipaddr_exdata, n_ipaddr_exdata);
+ if(n_exdata==0)
+ {
+ return 0;
+ }
+
+ size_t tag_ids_offset=0;
+
+ for(int i=0; i<n_exdata; i++)
+ {
+ if(ipaddr_exdata[i]==NULL || ipaddr_exdata[i]->n_tag_uuids==0)
+ {
+ continue;
+ }
+
+ for(size_t j=0; j<ipaddr_exdata[i]->n_tag_uuids; j++)
+ {
+ if(is_duplicate_tag_uuid(tag_uuids, tag_ids_offset, ipaddr_exdata[i]->tag_uuids[j])==TRUE)
+ {
+ continue;
+ }
+
+ if(tag_ids_offset>=n_tag_uuids)
+ {
+ break;
+ }
+
+ uuid_copy(tag_uuids[tag_ids_offset++], ipaddr_exdata[i]->tag_uuids[j]);
+ }
+ }
+
+ return tag_ids_offset;
+}
+
+void cs_ipport_attribute_get_from_packet_layer(struct attribute_scratch *attr, size_t attr_max, size_t *attr_offset, struct scanner_maat *cm_maat, struct attribute_schema *attr_schema, const struct layer *layers, int layer_count)
+{
+ if(attr==NULL || (*attr_offset)>=attr_max || layers==NULL || layer_count<=0)
+ {
+ return ;
+ }
+
+ int32_t c_port=-1, s_port=-1;
+ struct ip *ip4=NULL;
+ struct ip6_hdr *ip6=NULL;
+ struct tcphdr *tcp=NULL;
+ struct udphdr *udp=NULL;
+ // uuid_t *ip_protocol_object_uuid=NULL;
+ struct ip_addr c_net_addr={0}, s_net_addr={0};
+
+ for(int j=0; j<layer_count; j++)
+ {
+ switch(layers[j].proto)
+ {
+ case LAYER_PROTO_IPV4:
+ ip4=(struct ip *)layers[j].hdr.ip4;
+ ip4_format_to_maat(ip4, &c_net_addr, &s_net_addr);
+ break;
+ case LAYER_PROTO_IPV6:
+ ip6=(struct ip6_hdr *)layers[j].hdr.ip6;
+ ip6_format_to_maat(ip6, &c_net_addr, &s_net_addr);
+ break;
+ case LAYER_PROTO_TCP:
+ // TODO: implement
+ // ip_protocol_object_uuid=plugin_shared_ip_protocol_object_uuid_get(ip_proto);
+ tcp=(struct tcphdr *)layers[j].hdr.tcp;
+ if(tcp!=NULL)
+ {
+ c_port=ntohs(tcp->th_sport);
+ s_port=ntohs(tcp->th_dport);
+ }
+ break;
+ case LAYER_PROTO_UDP:
+ // TODO: implement
+ // ip_protocol_object_uuid=plugin_shared_ip_protocol_object_uuid_get(ip_proto);
+ udp=(struct udphdr *)layers[j].hdr.udp;
+ if(udp!=NULL)
+ {
+ c_port=ntohs(udp->uh_sport);
+ s_port=ntohs(udp->uh_dport);
+ }
+ break;
+ case LAYER_PROTO_ICMP:
+ case LAYER_PROTO_ICMP6:
+ // TODO: implement
+ // ip_protocol_object_uuid=plugin_shared_ip_protocol_object_uuid_get(ip_proto);
+ break;
+ default:
+ continue;
+ }
+ }
+
+ size_t max_tag_ids=MAX_TAG_IDS_NUM;
+ uuid_t tag_uuids[max_tag_ids];
+ size_t n_tag_uuids=ipaddr_entry_tag_uuid_get(cm_maat, &c_net_addr, tag_uuids, max_tag_ids);
+ attribute_scratch_maat_object_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_CLIENT_IP_TAG_UUIDS]), FREE_FALSE, NULL, tag_uuids, n_tag_uuids);
+
+ n_tag_uuids=ipaddr_entry_tag_uuid_get(cm_maat, &s_net_addr, tag_uuids, max_tag_ids);
+ attribute_scratch_maat_object_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_SERVER_IP_TAG_UUIDS]), FREE_FALSE, NULL, tag_uuids, n_tag_uuids);
+
+ if(ip4!=NULL)
+ {
+ attribute_scratch_ipv4_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_CLIENT_IP]), FREE_FALSE, ip4->ip_src.s_addr, c_port);
+ attribute_scratch_ipv4_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_SERVER_IP]), FREE_FALSE, ip4->ip_dst.s_addr, s_port);
+ }
+
+ if(ip6!=NULL)
+ {
+ attribute_scratch_ipv6_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_CLIENT_IP]), FREE_FALSE, ip6->ip6_src.s6_addr, c_port);
+ attribute_scratch_ipv6_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_SERVER_IP]), FREE_FALSE, ip6->ip6_dst.s6_addr, s_port);
+ }
+
+ if(c_port!=-1 && s_port!=-1)
+ {
+ attribute_scratch_integer_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_CLIENT_PORT]), FREE_FALSE, (long long)c_port);
+ attribute_scratch_integer_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_SERVER_PORT]), FREE_FALSE, (long long)s_port);
+ }
+
+ // TODO: IP protocol
+ // if(ip_protocol_object_uuid!=NULL)
+ // {
+ // attribute_scratch_maat_object_fill(attr, attr_max, attr_offset, FREE_FALSE, &(attr_schema[ATTRIBUTE_SCHEMA_IP_PROTOCOL]), FREE_FALSE, NULL, &ip_protocol_object_uuid, 1);
+ // }
+}
+
+void packet_based_scanner_node_entry(struct packet *rawpkt, struct module *mod_scanner)
+{
+ if(rawpkt==NULL || mod_scanner==NULL)
+ {
+ return ;
+ }
+
+ struct scanner *scanner=(struct scanner *)module_get_ctx(mod_scanner);
+ if(scanner==NULL)
+ {
+ return ;
+ }
+
+ int pkt_layer_count=packet_get_layer_count(rawpkt);
+ const struct layer *innermost_layer=packet_get_layer_by_idx(rawpkt, pkt_layer_count-1);
+ if(innermost_layer==NULL || pkt_layer_count<2)
+ {
+ return ;
+ }
+
+ switch(innermost_layer->proto)
+ {
+ case LAYER_PROTO_UDP:
+ case LAYER_PROTO_TCP:
+ //TODO: lookup session
+ break;
+ case LAYER_PROTO_ICMP:
+ case LAYER_PROTO_ICMP6:
+ break;
+ default:
+ return ;
+ }
+
+ struct attribute_kv *attr_kv=attribute_kv_new();
+ packet_set_exdata(rawpkt, scanner->pkt_scanner->exdata_idx, (void *)attr_kv);
+
+ struct maat_state *scan_state=maat_state_new(scanner_cm_maat_get_feather(scanner->cm_maat), 1);
+
+ size_t attr_max=128;
+ size_t attr_offset=0;
+ struct attribute_scratch attr[attr_max];
+ int layers_count=2;
+ const struct layer *layers=packet_get_layer_by_idx(rawpkt, pkt_layer_count-layers_count);
+ cs_ipport_attribute_get_from_packet_layer(attr, attr_max, &(attr_offset), scanner->cm_maat, scanner->attr_schema, layers, layers_count);
+ attribute_scratch_scan(scanner->cm_maat, scan_state, NULL, NULL, attr, attr_offset);
+ attribute_scratch_reset(attr, attr_offset);
+ attr_offset=0;
+
+ // TODO: internal external
+ //int is_client_internal=(packet_get_direction(rawpkt)==PACKET_DIRECTION_OUTGOING) ? TRUE : FALSE;
+
+ attribute_scratch_not_logic_fill(attr, attr_max, &attr_offset, FREE_FALSE, &(scanner->attr_schema[ATTRIBUTE_SCHEMA_CLIENT_IP_COMMIT]), FREE_FALSE);
+ attribute_scratch_not_logic_fill(attr, attr_max, &attr_offset, FREE_FALSE, &(scanner->attr_schema[ATTRIBUTE_SCHEMA_SERVER_IP_COMMIT]), FREE_FALSE);
+ attribute_scratch_not_logic_fill(attr, attr_max, &attr_offset, FREE_FALSE, &(scanner->attr_schema[ATTRIBUTE_SCHEMA_CLIENT_PORT_COMMIT]), FREE_FALSE);
+ attribute_scratch_not_logic_fill(attr, attr_max, &attr_offset, FREE_FALSE, &(scanner->attr_schema[ATTRIBUTE_SCHEMA_SERVER_PORT_COMMIT]), FREE_FALSE);
+
+ attribute_scratch_scan(scanner->cm_maat, scan_state, NULL, NULL, attr, attr_offset);
+ attribute_scratch_reset(attr, attr_offset);
+
+ return ;
+}
+
+struct maat_state *scanner_get_maat_state_from_packet(struct scanner *scanner, const struct packet *pkt)
+{
+ if(scanner==NULL || scanner->pkt_scanner==NULL || pkt==NULL)
+ {
+ return NULL;
+ }
+
+ return (struct maat_state *)packet_get_exdata(pkt, scanner->pkt_scanner->exdata_idx);
+}
+
+struct packet_scanner *packet_scanner_new(struct scanner *scanner)
+{
+ if(scanner==NULL)
+ {
+ return NULL;
+ }
+
+ struct packet_scanner *pkt_scanner=CALLOC(struct packet_scanner, 1);
+// // pkt_scanner->exdata_idx=packet_manager_new_packet_exdata_index(pkt_mgr, "SCANNER_EXDATA_SESSION", packet_scanner_exdata_free, (void *)scanner);
+// // if(pkt_scanner->exdata_idx<0)
+// // {
+// // STELLAR_LOG_FATAL(scanner->logger, SCANNER_MODULE_NAME, "packet_scanner_new failed to create exdata index");
+// // goto INIT_ERROR;
+// // }
+
+ return pkt_scanner;
+
+// // INIT_ERROR:
+// // packet_scanner_free(pkt_scanner);
+// return NULL;
+}
+
+void packet_scanner_free(struct packet_scanner *pkt_scanner)
+{
+ if(pkt_scanner==NULL)
+ {
+ return ;
+ }
+
+ FREE(pkt_scanner);
+} \ No newline at end of file