#include #include #include #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; iip_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; iscan_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; in_tag_uuids==0) { continue; } for(size_t j=0; jn_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; jth_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); }