static int analyzer_jpeg_init(struct analyzer *analyzer) { struct analyzer_pload_type *pload_type = analyzer_pload_type_get_by_name(ANALYZER_JPEG_PLOAD_TYPE); if (!pload_type) { pomlog(POMLOG_ERR "Payload type " ANALYZER_JPEG_PLOAD_TYPE " not found"); return POM_ERR; } static struct data_item_reg pload_jpeg_data_items[ANALYZER_JPEG_PLOAD_DATA_COUNT] = { { 0 } }; pload_jpeg_data_items[analyzer_jpeg_pload_width].name = "width"; pload_jpeg_data_items[analyzer_jpeg_pload_width].value_type = ptype_get_type("uint16"); pload_jpeg_data_items[analyzer_jpeg_pload_height].name = "height"; pload_jpeg_data_items[analyzer_jpeg_pload_height].value_type = ptype_get_type("uint16"); pload_jpeg_data_items[analyzer_jpeg_pload_exif].name = "exif"; pload_jpeg_data_items[analyzer_jpeg_pload_exif].flags = ANALYZER_DATA_FLAG_LIST; static struct data_reg pload_jpeg_data = { .items = pload_jpeg_data_items, .data_count = ANALYZER_JPEG_PLOAD_DATA_COUNT }; static struct analyzer_pload_reg pload_reg; memset(&pload_reg, 0, sizeof(struct analyzer_pload_reg)); pload_reg.analyzer = analyzer; pload_reg.analyze = analyzer_jpeg_pload_analyze; pload_reg.cleanup = analyzer_jpeg_pload_cleanup; pload_reg.data_reg = &pload_jpeg_data; pload_reg.flags = ANALYZER_PLOAD_PROCESS_PARTIAL; return analyzer_pload_register(pload_type, &pload_reg); }
int proto_expectation_add(struct proto_expectation *e) { if (!e || !e->tail || !e->tail->proto) { pomlog(POMLOG_ERR "Cannot add expectation as it's incomplete"); return POM_ERR; } if (e->flags & PROTO_EXPECTATION_FLAG_QUEUED) return POM_ERR; struct proto *proto = e->tail->proto; pom_rwlock_wlock(&proto->expectation_lock); __sync_fetch_and_or(&e->flags, PROTO_EXPECTATION_FLAG_QUEUED); e->next = proto->expectations; if (e->next) e->next->prev = e; proto->expectations = e; pom_rwlock_unlock(&proto->expectation_lock); registry_perf_inc(e->proto->perf_expt_pending, 1); return POM_OK; }
int proto_expectation_set_field(struct proto_expectation *e, int stack_index, struct ptype *value, int direction) { struct proto_expectation_stack *es = NULL; int i; if (stack_index > 0) { es = e->head; for (i = 1; es && i < stack_index; i++) es = es->next; } else { stack_index = -stack_index; es = e->tail; for (i = 1; es && i < stack_index; i++) es = es->prev; } if (!es) { pomlog(POMLOG_ERR "Invalid stack index in the expectation"); return POM_ERR; } if (es->fields[direction]) { ptype_cleanup(es->fields[direction]); es->fields[direction] = NULL; } if (value) { es->fields[direction] = ptype_alloc_from(value); if (!es->fields[direction]) return POM_ERR; } return POM_OK; }
static struct proto_expectation_stack *proto_expectation_stack_alloc(struct proto *p, struct ptype *fwd_value, struct ptype *rev_value) { if (!p || !fwd_value) { pomlog(POMLOG_ERR "Cannot allocate expectation with a forward nor reverse conntrack entry field value"); return NULL; } struct proto_expectation_stack *es = malloc(sizeof(struct proto_expectation_stack)); if (!es) { pom_oom(sizeof(struct proto_expectation_stack)); return NULL; } memset(es, 0, sizeof(struct proto_expectation_stack)); es->proto = p; es->fields[POM_DIR_FWD] = ptype_alloc_from(fwd_value); if (!es->fields[POM_DIR_FWD]) { free(es); return NULL; } if (rev_value) { es->fields[POM_DIR_REV] = ptype_alloc_from(rev_value); if (!es->fields[POM_DIR_REV]) { ptype_cleanup(es->fields[POM_DIR_FWD]); free(es); return NULL; } } return es; }
int proto_unregister(char *name) { struct proto *proto; for (proto = proto_head; proto && strcmp(proto->info->name, name); proto = proto->next); if (!proto) return POM_OK; proto_number_unregister(proto); if (proto->info->cleanup && proto->info->cleanup(proto->priv)) { pomlog(POMLOG_ERR "Error while cleaning up the protocol %s", name); return POM_ERR; } if (proto->reg_instance) registry_remove_instance(proto->reg_instance); conntrack_table_cleanup(proto->ct); if (proto->next) proto->next->prev = proto->prev; if (proto->prev) proto->prev->next = proto->next; else proto_head = proto->next; mod_refcount_dec(proto->info->mod); free(proto); return POM_OK; }
int proto_post_process(struct packet *p, struct proto_process_stack *s, unsigned int stack_index) { if (!s) return PROTO_ERR; struct proto *proto = s[stack_index].proto; if (!proto) return PROTO_ERR; // Process the listeners after the whole stack has been processed struct proto_packet_listener *l; for (l = proto->packet_listeners; l; l = l->next) { if (l->filter && packet_filter_match(l->filter, s) != FILTER_MATCH_YES) continue; if (l->process(l->object, p, s, stack_index) != POM_OK) { pomlog(POMLOG_WARN "Warning packet listener failed"); // FIXME remove listener from the list ? } } if (proto->info->post_process) return proto->info->post_process(proto->priv, p, s, stack_index); return POM_OK; }
struct ptype* ptype_alloc_unit(const char* type, char* unit) { struct ptype_reg *reg; for (reg = ptype_reg_head; reg && strcmp(reg->info->name, type); reg = reg->next); if (!reg) { // This should only be needed at startup pomlog(POMLOG_DEBUG "Ptype of type %s not found, trying to load module", type); char ptype_mod_name[64] = { 0 }; strcat(ptype_mod_name, "ptype_"); strncat(ptype_mod_name, type, sizeof(ptype_mod_name) - 1 - strlen(ptype_mod_name)); if (!mod_load(ptype_mod_name)) { pomlog(POMLOG_ERR "Ptype of type %s not found", type); return NULL; } for (reg = ptype_reg_head; reg && strcmp(reg->info->name, type); reg = reg->next); if (!reg) { pomlog(POMLOG_ERR "Ptype of type %s not found even after loading module", type); return NULL; } } struct ptype *ret = malloc(sizeof(struct ptype)); if (!ret) { pom_oom(sizeof(struct ptype)); return NULL; } memset(ret, 0, sizeof(struct ptype)); ret->type = reg; if (reg->info->alloc) { if (reg->info->alloc(ret) != POM_OK) { pomlog(POMLOG_ERR "Error while allocating ptype %s", type); free(ret); return NULL; } } if (unit) { ret->unit = strdup(unit); if (!ret->unit) pom_oom(strlen(unit)); } return ret; }
int core_cleanup(int emergency_cleanup) { core_run = 0; int i; for (i = 0; i < CORE_PROCESS_THREAD_MAX && core_processing_threads[i]; i++) { struct core_processing_thread *t = core_processing_threads[i]; int res = pthread_cond_signal(&t->pkt_queue_cond); if (res) { pomlog(POMLOG_ERR "Error while signaling the restart condition : %s", pom_strerror(res)); abort(); } pthread_join(t->thread, NULL); res = pthread_mutex_destroy(&t->pkt_queue_lock); if (res) pomlog(POMLOG_WARN "Error while destroying a processing thread lock : %s", pom_strerror(res)); res = pthread_cond_destroy(&t->pkt_queue_cond); if (res) pomlog(POMLOG_WARN "Error while destroying a processing thread condition : %s", pom_strerror(res)); struct core_packet_queue *tmp = NULL; while (t->pkt_queue_head) { tmp = t->pkt_queue_head; t->pkt_queue_head = tmp->next; // packet_pool_cleanup() was already called when the thread stopped // packet_pool_release(tmp->pkt); free(tmp); pomlog(POMLOG_WARN "A packet was still in a thread's queue"); } while (t->pkt_queue_unused) { tmp = t->pkt_queue_unused; t->pkt_queue_unused = tmp->next; // packet_pool_cleanup() was already called when the thread stopped // packet_pool_release(tmp->pkt); free(tmp); } free(t); } return POM_OK; }
void core_pause_processing() { int res = pthread_rwlock_wrlock(&core_processing_lock); if (res) { pomlog(POMLOG_ERR "Error while locking core processing lock : %s", pom_strerror(res)); abort(); } }
struct event_reg *event_register(struct event_reg_info *reg_info) { struct event_reg *evt; // Check if an event with the same name has already been registered for (evt = event_reg_head; evt && strcmp(evt->info->name, reg_info->name); evt = evt->next); if (evt) { pomlog(POMLOG_ERR "An event named %s has already been registered", reg_info->name); return NULL; } // Allocate the event_reg evt = malloc(sizeof(struct event_reg)); if (!evt) { pom_oom(sizeof(struct event_reg)); return NULL; } memset(evt, 0, sizeof(struct event_reg)); evt->reg_instance = registry_add_instance(event_registry_class, reg_info->name); if (!evt->reg_instance) { free(evt); return NULL; } evt->perf_listeners = registry_instance_add_perf(evt->reg_instance, "listeners", registry_perf_type_gauge, "Number of event listeners", "listeners"); evt->perf_ongoing = registry_instance_add_perf(evt->reg_instance, "ongoing", registry_perf_type_gauge, "Number of ongoing events", "events"); evt->perf_processed = registry_instance_add_perf(evt->reg_instance, "processed", registry_perf_type_counter, "Number of events fully processed", "events"); if (!evt->perf_listeners || !evt->perf_ongoing || !evt->perf_processed) { registry_remove_instance(evt->reg_instance); free(evt); return NULL; } evt->info = reg_info; evt->next = event_reg_head; if (evt->next) evt->next->prev = evt; event_reg_head = evt; pomlog(POMLOG_DEBUG "Event %s registered", reg_info->name); return evt; }
int proto_cleanup() { struct proto *proto; for (proto = proto_head; proto; proto = proto->next) { if (proto->info->cleanup && proto->info->cleanup(proto->priv) == POM_ERR) pomlog(POMLOG_WARN "Error while cleaning up protocol %s", proto->info->name); conntrack_table_cleanup(proto->ct); mod_refcount_dec(proto->info->mod); } while (proto_head) { proto = proto_head; proto_head = proto->next; int res = pthread_rwlock_destroy(&proto->listeners_lock); if (res) pomlog(POMLOG_ERR "Error while destroying the listners lock : %s", pom_strerror(res)); res = pthread_rwlock_destroy(&proto->expectation_lock); if (res) pomlog(POMLOG_ERR "Error while destroying the listners lock : %s", pom_strerror(res)); free(proto); } if (proto_registry_class) registry_remove_class(proto_registry_class); proto_registry_class = NULL; while (proto_number_class_head) { struct proto_number_class *cls = proto_number_class_head; proto_number_class_head = cls->next; while (cls->nums) { struct proto_number *num = cls->nums; cls->nums = num->next; free(num); } free(cls->name); free(cls); } return POM_OK; }
int core_cleanup(int emergency_cleanup) { core_run = 0; if (!emergency_cleanup) { while (core_pkt_queue_head) { pomlog("Waiting for all the packets to be processed"); if (pthread_cond_broadcast(&core_pkt_queue_restart_cond)) { pomlog(POMLOG_ERR "Error while signaling the restart condition : %s", pom_strerror(errno)); return POM_ERR; } sleep(1); } } if (pthread_cond_broadcast(&core_pkt_queue_restart_cond)) { pomlog(POMLOG_ERR "Error while signaling the restart condition : %s", pom_strerror(errno)); return POM_ERR; } int i; for (i = 0; i < CORE_PROCESS_THREAD_MAX && core_processing_threads[i]; i++) { pthread_join(core_processing_threads[i]->thread, NULL); free(core_processing_threads[i]); } pthread_cond_destroy(&core_pkt_queue_restart_cond); while (core_pkt_queue_head) { struct core_packet_queue *tmp = core_pkt_queue_head; core_pkt_queue_head = tmp->next; packet_pool_release(tmp->pkt); free(tmp); pomlog(POMLOG_WARN "A packet was still in the buffer"); } while (core_pkt_queue_unused) { struct core_packet_queue *tmp = core_pkt_queue_unused; core_pkt_queue_unused = tmp->next; free(tmp); } return POM_OK; }
int addon_log_xml_close(void *output_priv) { struct output_log_xml_priv *priv = output_priv; if (priv->fd == -1) { pomlog(POMLOG_ERR "Output already stopped"); return POM_ERR; } if (close(priv->fd)) { pomlog(POMLOG_ERR "Error while closing log file : %s", pom_strerror(errno)); return POM_ERR; } priv->fd = -1; return POM_OK; }
int ptype_copy(struct ptype *dst, struct ptype *src) { if (dst->type != src->type) { pomlog(POMLOG_ERR "Error, trying to copy ptypes of different type"); return POM_ERR; } return src->type->info->copy(dst, src); }
void conntrack_refcount_dec(struct conntrack_entry *ce) { pom_mutex_lock(&ce->lock); if (!ce->refcount) { pomlog(POMLOG_ERR "Reference count already 0 !"); abort(); } ce->refcount--; pom_mutex_unlock(&ce->lock); }
void registry_perf_timeticks_restart(struct registry_perf *p) { if (p->type != registry_perf_type_timeticks) { pomlog(POMLOG_ERR "Trying to restart a non timetick performance"); return; } if (p->value & REGISTRY_PERF_TIMETICKS_STARTED) { pomlog(POMLOG_ERR "Timeticks performance already started"); return; } ptime now = pom_gettimeofday(); // value currently holds the runtime in usec volatile uint64_t new_val = (now + REGISTRY_PERF_TIMETICKS_STARTED) - p->value; p->value = new_val; }
int packet_info_pool_init(struct packet_info_pool *pool) { if (pthread_mutex_init(&pool->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing the pkt_info_pool lock : ", pom_strerror(errno)); return POM_ERR; } return POM_OK; }
int event_listener_register(struct event_reg *evt_reg, void *obj, int (*process_begin) (struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index), int (*process_end) (struct event *evt, void *obj)) { struct event_listener *lst; for (lst = evt_reg->listeners; lst && lst->obj != obj; lst = lst->next); if (lst) { pomlog(POMLOG_ERR "Event %s is already being listened to by obj %p", evt_reg->info->name, obj); return POM_ERR; } lst = malloc(sizeof(struct event_listener)); if (!lst) { pom_oom(sizeof(struct event_listener)); return POM_ERR; } memset(lst, 0, sizeof(struct event_listener)); lst->obj = obj; lst->process_begin = process_begin; lst->process_end = process_end; lst->next = evt_reg->listeners; if (lst->next) lst->next->prev = lst; evt_reg->listeners = lst; if (!lst->next) { // Got a listener now, notify if (evt_reg->info->listeners_notify && evt_reg->info->listeners_notify(evt_reg->info->source_obj, evt_reg, 1) != POM_OK) { pomlog(POMLOG_ERR "Error while notifying event object about new listener"); evt_reg->listeners = NULL; free(lst); return POM_ERR; } } registry_perf_inc(evt_reg->perf_listeners, 1); return POM_OK; }
void registry_perf_timeticks_stop(struct registry_perf *p) { if (p->type != registry_perf_type_timeticks) { pomlog(POMLOG_ERR "Trying to stop a non timetick performance"); return; } if (!(p->value & REGISTRY_PERF_TIMETICKS_STARTED)) { pomlog(POMLOG_ERR "Timeticks performance already stopped"); return; } ptime now = pom_gettimeofday(); // value currently holds the absolute start time expressed in usec // Not sure if the below is correct ... volatile uint64_t new_val = (now + REGISTRY_PERF_TIMETICKS_STARTED) - p->value; p->value = new_val; }
static int input_pcap_dir_open(struct input *i) { struct input_pcap_priv *p = i->priv; struct input_pcap_dir_priv *dp = &p->tpriv.dir; // Reset the interrupt flag dp->interrupt_scan = 0; pomlog(POMLOG_INFO "Scanning directory %s for pcap files ...", PTYPE_STRING_GETVAL(dp->p_dir)); int found = input_pcap_dir_browse(p); if (dp->interrupt_scan) return POM_ERR; if (found == POM_ERR) return POM_ERR; pomlog(POMLOG_INFO "Found %u files", found); dp->cur_file = dp->files; // Skip files which were not read while (dp->cur_file && !dp->cur_file->first_pkt) dp->cur_file = dp->cur_file->next; if (!dp->cur_file) { pomlog(POMLOG_ERR "No useable file found"); return POM_ERR; } char errbuf[PCAP_ERRBUF_SIZE + 1] = { 0 }; p->p = pcap_open_offline(dp->cur_file->full_path, errbuf); if (!p->p) { pomlog(POMLOG_ERR "Error opening %s for reading", dp->cur_file->full_path); return POM_ERR; } pomlog("Reading file %s", dp->cur_file->filename); return input_pcap_common_open(i); }
void xmlrcpcmd_serial_inc() { pom_mutex_lock(&xmlrpccmd_serial_lock); xmlrpccmd_serial++; if (pthread_cond_broadcast(&xmlrpccmd_serial_cond)) { pomlog(POMLOG_ERR "Error while signaling the serial condition. Aborting"); abort(); } pom_mutex_unlock(&xmlrpccmd_serial_lock); }
int conntrack_timer_cleanup(struct conntrack_timer *t) { #ifdef DEBUG_CONNTRACK int res = pthread_mutex_lock(&t->ce->lock); if (!res) { pomlog(POMLOG_ERR "Internal error, conntrack not locked when timer cleaned up"); pom_mutex_unlock(&t->ce->lock); } else if (res != EDEADLK) { pomlog(POMLOG_ERR "Error while locking timer lock : %s", pom_strerror(errno)); abort(); } #endif timer_cleanup(t->timer); free(t); return POM_OK; }
int output_file_pload_close(void *pload_instance_priv) { struct output_file_pload_priv *ppriv = pload_instance_priv; int fd = ppriv->fd; pomlog(POMLOG_DEBUG "File %s closed", ppriv->filename); free(ppriv->filename); free(ppriv); return close(fd); }
struct ptype_reg *ptype_get_type(char *name) { struct ptype_reg *tmp; for (tmp = ptype_reg_head; tmp && strcmp(tmp->info->name, name); tmp = tmp->next); if (!tmp) pomlog(POMLOG_WARN "Warning, requested ptype %s not found", name); return tmp; }
int output_file_pload_write(void *pload_instance_priv, void *data, size_t len) { struct output_file_pload_priv *ppriv = pload_instance_priv; int res = pom_write(ppriv->fd, data, len); if (res == POM_ERR) pomlog(POMLOG_ERR "Error while writing to file %s : %s", ppriv->filename, pom_strerror(errno)); return res; }
void core_wait_state(enum core_state state) { pom_mutex_lock(&core_state_lock); while (core_cur_state != state) { if (pthread_cond_wait(&core_state_cond, &core_state_lock)) { pomlog(POMLOG_ERR "Error while waiting for core cond : %s", pom_strerror(errno)); abort(); break; } } pom_mutex_unlock(&core_state_lock); }
int stream_cleanup(struct stream *stream) { if (stream->wait_list_head) { pomlog(POMLOG_ERR "Internal error, cleaning up stream while packets still present!"); return POM_ERR; } while (stream->head[0] || stream->head[1]) { if (stream_force_dequeue(stream) == POM_ERR) { pomlog(POMLOG_ERR "Error while processing remaining packets in the stream"); break; } } conntrack_delayed_cleanup(stream->ce, 0, stream->last_ts); int res = pthread_mutex_destroy(&stream->lock); if (res){ pomlog(POMLOG_ERR "Error while destroying stream lock : %s", pom_strerror(res)); } res = pthread_mutex_destroy(&stream->wait_lock); if (res){ pomlog(POMLOG_ERR "Error while destroying stream wait lock : %s", pom_strerror(res)); } while (stream->wait_list_unused) { struct stream_thread_wait *tmp = stream->wait_list_unused; stream->wait_list_unused = tmp->next; if (pthread_cond_destroy(&tmp->cond)) pomlog(POMLOG_WARN "Error while destroying list condition"); free(tmp); } free(stream); debug_stream("thread %p, entry %p, released", pthread_self(), stream); return POM_OK; }
// Called from lua to listen to a new event from an instance static int addon_output_event_listen_start(lua_State *L) { // Args should be : // 1) self // 2) event name // 3) process_begin // 4) process_end // Find the event const char *evt_name = luaL_checkstring(L, 2); struct event_reg *evt = event_find(evt_name); if (!evt) luaL_error(L, "Event %s does not exists", evt_name); // Check which function we should register int (*process_begin) (struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) = NULL; int (*process_end) (struct event *evt, void *obj) = NULL; if (lua_isfunction(L, 3)) process_begin = addon_event_process_begin; if (lua_isfunction(L, 4)) process_end = addon_event_process_end; // Get the output struct addon_instance_priv *p = addon_output_get_priv(L, 1); if (event_listener_register(evt, p, process_begin, process_end) != POM_OK) luaL_error(L, "Error while listening to event %s", evt_name); // Add a table to self for the processing functions of this event lua_newtable(L); lua_pushlightuserdata(L, evt); lua_pushvalue(L, -2); lua_settable(L, 1); // Add the processing function if (process_begin) { lua_pushliteral(L, "begin"); lua_pushvalue(L, 3); lua_settable(L, -3); } if (process_end) { lua_pushliteral(L, "end"); lua_pushvalue(L, 4); lua_settable(L, -3); } pomlog(POMLOG_DEBUG "Output listening to event %s", evt_name); return 0; }
int decoder_decode_simple(char *encoding, char *in, size_t in_len, char **out, size_t *out_len) { struct decoder_reg *tmp; for (tmp = decoder_reg_head; tmp && strcasecmp(tmp->name, encoding); tmp = tmp->next); if (!tmp) { pomlog(POMLOG_ERR "Decoder %s does not exists", encoding); *out = NULL; *out_len = 0; return DEC_ERR; } struct decoder dec = { 0 }; dec.reg = tmp->info; if (dec.reg->alloc && dec.reg->alloc(&dec) != POM_OK) return DEC_ERR; dec.avail_in = in_len; dec.next_in = in; size_t buff_len = dec.reg->estimate_size(in_len); dec.next_out = malloc(buff_len); *out = dec.next_out; dec.avail_out = buff_len; if (!dec.next_out) { pom_oom(dec.avail_out); goto err; } int res = dec.reg->decode(&dec); if (res == DEC_ERR) { free(dec.next_out); goto err; } if (dec.reg->cleanup) dec.reg->cleanup(&dec); *out_len = buff_len - dec.avail_out; return DEC_OK; err: if (dec.reg->cleanup) dec.reg->cleanup(&dec); *out = NULL; *out_len = 0; return DEC_ERR; }
int conntrack_session_bind(struct conntrack_entry *ce, struct conntrack_session *session) { if (ce->session) { pomlog(POMLOG_WARN "Warning, session already exists when trying to bind another session. TODO: implement merging"); conntrack_session_refcount_dec(ce->session); } conntrack_session_refcount_inc(session); ce->session = session; return POM_OK; }