struct stream* stream_alloc(uint32_t max_buff_size, struct conntrack_entry *ce, unsigned int flags, int (*handler) (struct conntrack_entry *ce, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index)) { struct stream *res = malloc(sizeof(struct stream)); if (!res) { pom_oom(sizeof(struct stream)); return NULL; } memset(res, 0, sizeof(struct stream)); res->max_buff_size = max_buff_size; res->ce = ce; if (pthread_mutex_init(&res->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing stream lock : %s", pom_strerror(errno)); free(res); return NULL; } if (pthread_mutex_init(&res->wait_lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing stream wait lock : %s", pom_strerror(errno)); free(res); return NULL; } res->flags = flags; res->handler = handler; debug_stream("thread %p, entry %p, allocated", pthread_self(), res); return res; }
void registry_perf_set_update_hook(struct registry_perf *p, int (*update_hook) (uint64_t *cur_val, void *priv), void *hook_priv) { if (p->type == registry_perf_type_timeticks) { pomlog(POMLOG_ERR "Trying to set an update hook on a timeticks perf"); return; } if (!update_hook) { if (p->update_hook) { int res = pthread_mutex_destroy(&p->hook_lock); if (res) { pomlog(POMLOG_ERR "Error while destroying the perf hook lock : %s", pom_strerror(res)); abort(); } } p->update_hook = NULL; p->hook_priv = NULL; return; } if (!p->update_hook) { int res = pthread_mutex_init(&p->hook_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing the perf hook lock : %s", pom_strerror(res)); abort(); } } p->update_hook = update_hook; p->hook_priv = hook_priv; }
struct packet_stream* packet_stream_alloc(uint32_t start_seq, uint32_t start_ack, int direction, uint32_t max_buff_size, struct conntrack_entry *ce, unsigned int flags) { struct packet_stream *res = malloc(sizeof(struct packet_stream)); if (!res) { pom_oom(sizeof(struct packet_stream)); return NULL; } memset(res, 0, sizeof(struct packet_stream)); int rev_direction = POM_DIR_REVERSE(direction); res->cur_seq[direction] = start_seq; res->cur_ack[direction] = start_ack; res->cur_seq[rev_direction] = start_ack; res->cur_ack[rev_direction] = start_seq; res->max_buff_size = max_buff_size; res->ce = ce; if (pthread_mutex_init(&res->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing stream lock : %s", pom_strerror(errno)); free(res); return NULL; } if (pthread_mutex_init(&res->wait_lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing stream wait lock : %s", pom_strerror(errno)); free(res); return NULL; } res->flags = flags; debug_stream("thread %p, entry %p, allocated, start_seq %u, start_ack %u, direction %u", pthread_self(), res, start_seq, start_ack, direction); return res; }
int mod_load_all() { char *path = getenv(MOD_LIBDIR_ENV_VAR); if (!path) path = POM_LIBDIR; DIR *d; d = opendir(path); if (!d) { pomlog(POMLOG_ERR "Could not open directory %s for browsing : %s", path, pom_strerror(errno)); return POM_ERR; } struct dirent tmp, *dp; while (1) { if (readdir_r(d, &tmp, &dp) < 0) { pomlog(POMLOG_ERR "Error while reading directory entry : %s", pom_strerror(errno)); closedir(d); return POM_ERR; } if (!dp) // EOF break; size_t len = strlen(dp->d_name); if (len < strlen(POM_LIB_EXT) + 1) continue; if (!strcmp(dp->d_name + strlen(dp->d_name) - strlen(POM_LIB_EXT), POM_LIB_EXT)) { char *name = strdup(dp->d_name); if (!name) { pom_oom(strlen(dp->d_name)); closedir(d); return POM_ERR; } *(name + strlen(dp->d_name) - strlen(POM_LIB_EXT)) = 0; // Check if a dependency already loaded this module pom_mutex_lock(&mod_reg_lock); struct mod_reg *tmp; for (tmp = mod_reg_head; tmp && strcmp(name, tmp->name); tmp = tmp->next); if (tmp) { pom_mutex_unlock(&mod_reg_lock); free(name); continue; } pom_mutex_unlock(&mod_reg_lock); mod_load(name); free(name); } } closedir(d); return POM_OK; }
static int input_kismet_drone_open(struct input *i) { struct input_kismet_drone_priv *priv = i->priv; char *host = PTYPE_STRING_GETVAL(priv->p_host); char *port = ptype_print_val_alloc(priv->p_port, NULL); if (!port) return POM_ERR; struct addrinfo hints = { 0 }; //hints.ai_family = AF_UNSPEC; hints.ai_family = AF_INET; // kismet_drone seem to only listen on ipv4 address hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_flags = AI_ADDRCONFIG; struct addrinfo *res = NULL; int err = getaddrinfo(host, port, &hints, &res); free(port); if (err) { pomlog(POMLOG_ERR "Error while resolving hostname %s : %s", host, gai_strerror(err)); return POM_ERR; } priv->fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (priv->fd == -1) { freeaddrinfo(res); pomlog(POMLOG_ERR "Error while creating socket : %s", pom_strerror(errno)); return POM_ERR; } if (connect(priv->fd, res->ai_addr, res->ai_addrlen)) { freeaddrinfo(res); close(priv->fd); priv->fd = -1; pomlog(POMLOG_ERR "Error while connecting to Kismet drone : %s", pom_strerror(errno)); return POM_ERR; } freeaddrinfo(res); pomlog("Connection established to Kismet drone %s:%u", host, *PTYPE_UINT16_GETVAL(priv->p_port)); return POM_OK; }
int output_tap_open(void *output_priv) { struct output_tap_priv *priv = output_priv; priv->fd = open("/dev/net/tun", O_RDWR | O_SYNC); if (priv->fd < 0) { pomlog(POMLOG_ERR "Error while opening the tap device : %s", pom_strerror(errno)); return POM_ERR; } struct ifreq ifr; memset(&ifr, 0, sizeof(struct ifreq)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr.ifr_name, PTYPE_STRING_GETVAL(priv->p_ifname), IFNAMSIZ); if (ioctl(priv->fd, TUNSETIFF, (void *) &ifr) < 0) { pomlog(POMLOG_ERR "Unable to setup tap device %s : %s", PTYPE_STRING_GETVAL(priv->p_ifname), pom_strerror(errno)); return POM_ERR; } if (ioctl(priv->fd, TUNSETPERSIST, *PTYPE_BOOL_GETVAL(priv->p_persistent)) < 0) { pomlog(POMLOG_WARN "Unable to set persistent mode to tap device %s : %s", PTYPE_STRING_GETVAL(priv->p_ifname), pom_strerror(errno)); } priv->listener = proto_packet_listener_register(proto_get("ethernet"), 0, priv, output_tap_pkt_process, priv->filter); if (!priv->listener) goto err; return POM_OK; err: close(priv->fd); priv->fd = -1; return POM_ERR; }
int conntrack_table_cleanup(struct conntrack_tables *ct) { if (!ct) return POM_OK; if (ct->table) { conntrack_table_empty(ct); free(ct->table); } if (ct->locks) { unsigned int i; for (i = 0; i < ct->table_size; i++) { int res = pthread_mutex_destroy(&ct->locks[i]); if (res) { pomlog(POMLOG_WARN "Error while destroying a hash lock : %s", pom_strerror(errno)); } } free(ct->locks); } free(ct); return POM_OK; }
void core_resume_processing() { if (pthread_rwlock_unlock(&core_processing_lock)) { pomlog(POMLOG_ERR "Error while locking core processing lock : %s", pom_strerror(errno)); abort(); } }
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(); } }
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; }
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 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 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 core_set_state(enum core_state state) { int res = POM_OK; pom_mutex_lock(&core_state_lock); if (core_cur_state == state) { pomlog(POMLOG_DEBUG "Core state unchanged : %u", state); pom_mutex_unlock(&core_state_lock); return POM_OK; } core_cur_state = state; pomlog(POMLOG_DEBUG "Core state changed to %u", state); if (pthread_cond_broadcast(&core_state_cond)) { pomlog(POMLOG_ERR "Unable to signal core state condition : %s", pom_strerror(errno)); pom_mutex_unlock(&core_state_lock); return POM_ERR; } pom_mutex_unlock(&core_state_lock); if (state == core_state_idle) { res = core_processing_stop(); ptime now = pom_gettimeofday(); int i; for (i = 0; i < CORE_PROCESS_THREAD_MAX; i++) core_clock[i] = 0; ptime runtime = now - core_start_time; pomlog(POMLOG_INFO "Core was running for %u.%06u secs", pom_ptime_sec(runtime), pom_ptime_usec(runtime)); } else if (state == core_state_running) { core_start_time = pom_gettimeofday(); res = core_processing_start(); } else if (state == core_state_finishing) { // Signal all the threads unsigned int i; for (i = 0; i < core_num_threads; i++) { struct core_processing_thread *t = core_processing_threads[i]; pom_mutex_lock(&t->pkt_queue_lock); int res = pthread_cond_broadcast(&t->pkt_queue_cond); pom_mutex_unlock(&t->pkt_queue_lock); if (res) { pomlog(POMLOG_ERR "Error while broadcasting restart condition after set state"); abort(); } } } 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 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; }
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; }
int output_file_pload_write(void *output_priv, void *pload_instance_priv, void *data, size_t len) { struct output_file_priv *priv = output_priv; 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)); else if (priv && priv->perf_bytes_written) registry_perf_inc(priv->perf_bytes_written, len); return res; }
int core_set_state(enum core_state state) { int res = POM_OK; pom_mutex_lock(&core_state_lock); core_cur_state = state; pomlog(POMLOG_DEBUG "Core state changed to %u", state); if (pthread_cond_broadcast(&core_state_cond)) { pomlog(POMLOG_ERR "Unable to signal core state condition : %s", pom_strerror(errno)); pom_mutex_unlock(&core_state_lock); return POM_ERR; } if (state == core_state_idle) { res = core_processing_stop(); struct timeval now; gettimeofday(&now, NULL); if (now.tv_usec < core_start_time.tv_usec) { now.tv_sec--; now.tv_usec += 1000000; } pom_mutex_lock(&core_clock_lock); memset(&core_clock, 0, sizeof(struct timeval)); pom_mutex_unlock(&core_clock_lock); now.tv_usec -= core_start_time.tv_usec; now.tv_sec -= core_start_time.tv_sec; pomlog(POMLOG_INFO "Core was running for %u.%06u secs", now.tv_sec, now.tv_usec); } else if (state == core_state_running) { gettimeofday(&core_start_time, NULL); res = core_processing_start(); } else if (state == core_state_finishing) { //pom_mutex_lock(&core_pkt_queue_mutex); if (pthread_cond_broadcast(&core_pkt_queue_restart_cond)) { pom_mutex_unlock(&core_pkt_queue_mutex); pom_mutex_unlock(&core_state_lock); pomlog(POMLOG_ERR "Error while broadcasting restart condition after set state"); return POM_ERR; } //pom_mutex_unlock(&core_pkt_queue_mutex); } pom_mutex_unlock(&core_state_lock); return res; }
static int input_kismet_drone_discard_bytes(struct input_kismet_drone_priv *priv, size_t len) { // Discard whatever command we dont need/support char buffer[256]; size_t r = len; while (r > 0) { size_t rlen = sizeof(buffer); if (rlen > r) rlen = r; size_t res = read(priv->fd, buffer, rlen); if (res < 0) { pomlog(POMLOG_ERR "Read error : %s", pom_strerror(errno)); return POM_ERR; } r -= res; } 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; }
struct conntrack_tables* conntrack_table_alloc(size_t table_size, int has_rev) { struct conntrack_tables *ct = malloc(sizeof(struct conntrack_tables)); if (!ct) { pom_oom(sizeof(struct conntrack_tables)); return NULL; } memset(ct, 0, sizeof(struct conntrack_tables)); size_t size = sizeof(struct conntrack_list) * table_size; ct->table = malloc(size); if (!ct->table) { pom_oom(size); goto err; } memset(ct->table, 0, size); size = sizeof(pthread_mutex_t) *table_size; ct->locks = malloc(size); if (!ct->locks) { pom_oom(size); goto err; } unsigned int i; for (i = 0; i < table_size; i++) { int res = pthread_mutex_init(&ct->locks[i], NULL); if (res) { pomlog(POMLOG_ERR "Could not initialize conntrack hash lock : %s", pom_strerror(res)); goto err; } } ct->table_size = table_size; return ct; err: conntrack_table_cleanup(ct); return NULL; }
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; }
static int input_kismet_drone_close(struct input *i) { struct input_kismet_drone_priv *priv = i->priv; if (priv->fd != -1) { if (close(priv->fd)) pomlog(POMLOG_WARN "Error while closing socket to kismet_drone : %s", pom_strerror(errno)); priv->fd = -1; } while (priv->srcs) { struct kismet_drone_source *src = priv->srcs; priv->srcs = src->next; free(src->name); free(src->interface); free(src->type); free(src); } return POM_OK; }
xmlrpc_value *xmlrpccmd_core_serial_poll(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void * const userData) { uint32_t last_serial = 0; xmlrpc_decompose_value(envP, paramArrayP, "(i)", &last_serial); if (envP->fault_occurred) return NULL; pom_mutex_lock(&xmlrpccmd_serial_lock); if (last_serial == xmlrpccmd_serial) { // Wait for update if (pthread_cond_wait(&xmlrpccmd_serial_cond, &xmlrpccmd_serial_lock)) { xmlrpc_faultf(envP, "Error while waiting for serial condition : %s", pom_strerror(errno)); abort(); return NULL; } } last_serial = xmlrpccmd_serial; pom_mutex_unlock(&xmlrpccmd_serial_lock); registry_lock(); pomlog_rlock(); struct pomlog_entry *last_log = pomlog_get_tail(); xmlrpc_value *res = xmlrpc_build_value(envP, "{s:i,s:i,s:i}", "main", last_serial, "registry", registry_serial_get(), "log", last_log->id); pomlog_unlock(); registry_unlock(); return res; }
struct conntrack_session *conntrack_session_get(struct conntrack_entry *ce) { if (!ce->session) { ce->session = malloc(sizeof(struct conntrack_session)); if (!ce->session) { pom_oom(sizeof(struct conntrack_session)); return NULL; } memset(ce->session, 0, sizeof(struct conntrack_session)); if (pthread_mutex_init(&ce->session->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing session mutex : %s", pom_strerror(errno)); free(ce->session); ce->session = NULL; return NULL; } ce->session->refcount++; } pom_mutex_lock(&ce->session->lock); return ce->session; }
int addon_log_xml_open(void *output_priv) { struct output_log_xml_priv *priv = output_priv; if (priv->fd != -1) { pomlog(POMLOG_ERR "Output log_xml already started"); return POM_ERR; } char *filename = PTYPE_STRING_GETVAL(priv->p_filename); if (!strlen(filename)) { pomlog(POMLOG_ERR "You must specify a filename where to log the output"); return POM_ERR; } priv->fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (priv->fd == -1) { pomlog(POMLOG_ERR "Error while opening log file \"%s\" : %s", filename, pom_strerror(errno)); return POM_ERR; } return POM_OK; }
int timers_process() { static int processing = 0; int res = pthread_mutex_trylock(&timer_main_lock); if (res == EBUSY) { // Already locked, give up return POM_OK; } else if (res) { // Something went wrong pomlog(POMLOG_ERR "Error while trying to lock the main timer lock : %s", pom_strerror(res)); abort(); return POM_ERR; } // Another thread is already processing the timers, drop out if (processing) { pom_mutex_unlock(&timer_main_lock); return POM_OK; } processing = 1; ptime now = core_get_clock(); struct timer_queue *tq; tq = timer_queues; while (tq) { while (tq->head && (tq->head->expires < now)) { // Dequeue the timer struct timer *tmp = tq->head; tq->head = tq->head->next; if (tq->head) tq->head->prev = NULL; else tq->tail = NULL; tmp->next = NULL; tmp->prev = NULL; tmp->queue = NULL; pom_mutex_unlock(&timer_main_lock); registry_perf_dec(perf_timer_queued, 1); // Process it debug_timer( "Timer 0x%lx reached. Starting handler ...", (unsigned long) tmp); if ((*tmp->handler) (tmp->priv, now) != POM_OK) { return POM_ERR; } registry_perf_inc(perf_timer_processed, 1); pom_mutex_lock(&timer_main_lock); } tq = tq->next; } processing = 0; pom_mutex_unlock(&timer_main_lock); return POM_OK; }
int proto_register(struct proto_reg_info *reg_info) { if (reg_info->api_ver != PROTO_API_VER) { pomlog(POMLOG_ERR "Cannot register proto as API version differ : expected %u got %u", PROTO_API_VER, reg_info->api_ver); return POM_ERR; } // Check if the protocol already exists struct proto *proto; for (proto = proto_head; proto && strcmp(proto->info->name, reg_info->name); proto = proto->next); if (proto) return POM_ERR; // Allocate the protocol proto = malloc(sizeof(struct proto)); if (!proto) { pom_oom(sizeof(struct proto)); return POM_ERR; } memset(proto, 0, sizeof(struct proto)); proto->info = reg_info; proto->id = proto_count; proto_count++; if (reg_info->number_class) { proto->number_class = proto_number_class_get(reg_info->number_class); if (!proto->number_class) goto err_proto; } int res = pthread_rwlock_init(&proto->expectation_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing the proto_expectation rwlock : %s", pom_strerror(res)); goto err_proto; } res = pthread_rwlock_init(&proto->listeners_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing the proto_listeners rwlock : %s", pom_strerror(res)); goto err_lock1; } proto->reg_instance = registry_add_instance(proto_registry_class, reg_info->name); if (!proto->reg_instance) { pomlog(POMLOG_ERR "Error while adding the registry instanc for protocol %s", reg_info->name); goto err_lock; } // Allocate the conntrack table if (reg_info->ct_info) { proto->ct = conntrack_table_alloc(reg_info->ct_info->default_table_size, (reg_info->ct_info->rev_pkt_field_id == -1 ? 0 : 1)); if (!proto->ct) { pomlog(POMLOG_ERR "Error while allocating conntrack tables"); goto err_registry; } proto->perf_conn_cur = registry_instance_add_perf(proto->reg_instance, "conn_cur", registry_perf_type_gauge, "Current number of monitored connection", "connections"); proto->perf_conn_tot = registry_instance_add_perf(proto->reg_instance, "conn_tot", registry_perf_type_counter, "Total number of connections", "connections"); proto->perf_conn_hash_col = registry_instance_add_perf(proto->reg_instance, "conn_hash_col", registry_perf_type_counter, "Total number of conntrack hash collisions", "collisions"); if (!proto->perf_conn_cur || !proto->perf_conn_tot || !proto->perf_conn_hash_col) goto err_conntrack; } proto->perf_pkts = registry_instance_add_perf(proto->reg_instance, "pkts", registry_perf_type_counter, "Number of packets processed", "pkts"); proto->perf_bytes = registry_instance_add_perf(proto->reg_instance, "bytes", registry_perf_type_counter, "Number of bytes processed", "bytes"); proto->perf_expt_pending = registry_instance_add_perf(proto->reg_instance, "expectations_pending", registry_perf_type_gauge, "Number of expectations pending", "expectations"); proto->perf_expt_matched = registry_instance_add_perf(proto->reg_instance, "expectations_matched", registry_perf_type_counter, "Number of expectations matched", "expectations"); if (!proto->perf_pkts || !proto->perf_bytes || !proto->perf_expt_pending || !proto->perf_expt_matched) goto err_conntrack; if (reg_info->init) { if (reg_info->init(proto, proto->reg_instance) == POM_ERR) { pomlog(POMLOG_ERR "Error while registering proto %s", reg_info->name); goto err_conntrack; } } mod_refcount_inc(reg_info->mod); proto->next = proto_head; if (proto->next) proto->next->prev = proto; proto_head = proto; pomlog(POMLOG_DEBUG "Proto %s registered", reg_info->name); return POM_OK; err_conntrack: // Remove proto number if any proto_number_unregister(proto); conntrack_table_cleanup(proto->ct); err_registry: registry_remove_instance(proto->reg_instance); err_lock: pthread_rwlock_destroy(&proto->listeners_lock); err_lock1: pthread_rwlock_destroy(&proto->expectation_lock); err_proto: free(proto); return POM_ERR; }
int core_init(unsigned int num_threads) { core_registry_class = registry_add_class(CORE_REGISTRY); if (!core_registry_class) return POM_ERR; perf_pkt_queue = registry_class_add_perf(core_registry_class, "pkt_queue", registry_perf_type_gauge, "Number of packets in the queue waiting to be processed", "pkts"); perf_thread_active = registry_class_add_perf(core_registry_class, "active_thread", registry_perf_type_gauge, "Number of active threads", "threads"); if (!perf_pkt_queue || !perf_thread_active) return POM_OK; core_param_dump_pkt = ptype_alloc("bool"); if (!core_param_dump_pkt) return POM_ERR; core_param_offline_dns = ptype_alloc("bool"); if (!core_param_offline_dns) { ptype_cleanup(core_param_dump_pkt); core_param_dump_pkt = NULL; return POM_ERR; } core_param_reset_perf_on_restart = ptype_alloc("bool"); if (!core_param_reset_perf_on_restart) { ptype_cleanup(core_param_dump_pkt); core_param_dump_pkt = NULL; ptype_cleanup(core_param_offline_dns); core_param_offline_dns = NULL; return POM_ERR; } struct registry_param *param = registry_new_param("dump_pkt", "no", core_param_dump_pkt, "Dump packets to logs", REGISTRY_PARAM_FLAG_CLEANUP_VAL); if (registry_class_add_param(core_registry_class, param) != POM_OK) goto err; param = registry_new_param("offline_dns", "yes", core_param_offline_dns, "Enable offline DNS resolver", REGISTRY_PARAM_FLAG_CLEANUP_VAL); if (registry_class_add_param(core_registry_class, param) != POM_OK) goto err; param = registry_new_param("reset_perf_on_restart", "no", core_param_reset_perf_on_restart, "Reset performances when core restarts", REGISTRY_PARAM_FLAG_CLEANUP_VAL); if (registry_class_add_param(core_registry_class, param) != POM_OK) goto err; param = NULL; // Start the processing threads unsigned int num_cpu = sysconf(_SC_NPROCESSORS_ONLN) - 1; if (num_cpu < 1) { pomlog(POMLOG_WARN "Could not find the number of CPU, assuming %u", CORE_PROCESS_THREAD_DEFAULT); num_cpu = CORE_PROCESS_THREAD_DEFAULT; } if (num_threads < 1) num_threads = num_cpu; if (num_threads > num_cpu) pomlog(POMLOG_WARN "WARNING : Running more processing threads than available CPU is discouraged as it will cause issues by creating higher latencies and eventually dropping packets !!! You have been warned !"); if (num_threads > CORE_PROCESS_THREAD_MAX) num_threads = CORE_PROCESS_THREAD_MAX; core_num_threads = num_threads; pomlog(POMLOG_INFO "Starting %u processing thread(s)", core_num_threads); core_run = 1; memset(core_processing_threads, 0, sizeof(struct core_processing_thread*) * CORE_PROCESS_THREAD_MAX); unsigned int i; for (i = 0; i < core_num_threads; i++) { struct core_processing_thread *tmp = malloc(sizeof(struct core_processing_thread)); if (!tmp) { pom_oom(sizeof(struct core_processing_thread)); goto err; } memset(tmp, 0, sizeof(struct core_processing_thread)); tmp->thread_id = i; int res = pthread_mutex_init(&tmp->pkt_queue_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing a thread pkt_queue lock : %s", pom_strerror(res)); free(tmp); goto err; } res = pthread_cond_init(&tmp->pkt_queue_cond, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing a thread pkt_queue condition : %s", pom_strerror(res)); pthread_mutex_destroy(&tmp->pkt_queue_lock); free(tmp); goto err; } if (pthread_create(&tmp->thread, NULL, core_processing_thread_func, tmp)) { pomlog(POMLOG_ERR "Error while creating a new processing thread : %s", pom_strerror(errno)); pthread_mutex_destroy(&tmp->pkt_queue_lock); pthread_cond_destroy(&tmp->pkt_queue_cond); free(tmp); goto err; } core_processing_threads[i] = tmp; } return POM_OK; err: if (param) registry_cleanup_param(param); core_cleanup(0); return POM_ERR; }