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; }
static int proto_eap_init(struct proto *proto, struct registry_instance *i) { if (proto_number_register("8021x", 0x0, proto) != POM_OK || proto_number_register("ppp", 0xc227, proto) != POM_OK) return POM_ERR; struct proto_eap_priv *priv = malloc(sizeof(struct proto_eap_priv)); if (!priv) { pom_oom(sizeof(struct proto_eap_priv)); return POM_ERR; } memset(priv, 0, sizeof(struct proto_eap_priv)); proto_set_priv(proto, priv); priv->p_timeout = ptype_alloc_unit("uint32", "seconds"); if (!priv->p_timeout) goto err; struct registry_param *p = registry_new_param("timeout", "60", priv->p_timeout, "Transaction timeout", 0); if (registry_instance_add_param(i, p) != POM_OK) { registry_cleanup_param(p); goto err; } static struct data_item_reg evt_identity_data_items[PROTO_EAP_EVT_IDENTITY_DATA_COUNT] = { { 0 } }; evt_identity_data_items[evt_eap_common_identifier].name = "identifier"; evt_identity_data_items[evt_eap_common_identifier].value_type = ptype_get_type("uint8"); evt_identity_data_items[evt_eap_common_code].name = "code"; evt_identity_data_items[evt_eap_common_code].value_type = ptype_get_type("uint8"); evt_identity_data_items[evt_eap_identity_identity].name = "identity"; evt_identity_data_items[evt_eap_identity_identity].value_type = ptype_get_type("string"); static struct data_reg evt_eap_identity_data = { .items = evt_identity_data_items, .data_count = PROTO_EAP_EVT_IDENTITY_DATA_COUNT }; static struct event_reg_info proto_eap_identity = { 0 }; proto_eap_identity.source_name = "proto_eap"; proto_eap_identity.source_obj = priv; proto_eap_identity.name = "eap_identity"; proto_eap_identity.description = "EAP Identity"; proto_eap_identity.data_reg = &evt_eap_identity_data; priv->evt_identity = event_register(&proto_eap_identity); if (!priv->evt_identity) goto err; static struct data_item_reg evt_md5_challenge_data_items[PROTO_EAP_EVT_MD5_CHALLENGE_DATA_COUNT] = { { 0 } }; evt_md5_challenge_data_items[evt_eap_common_identifier].name = "identifier"; evt_md5_challenge_data_items[evt_eap_common_identifier].value_type = ptype_get_type("uint8"); evt_md5_challenge_data_items[evt_eap_common_code].name = "code"; evt_md5_challenge_data_items[evt_eap_common_code].value_type = ptype_get_type("uint8"); evt_md5_challenge_data_items[evt_eap_md5_challenge_value].name = "value"; evt_md5_challenge_data_items[evt_eap_md5_challenge_value].value_type = ptype_get_type("bytes"); evt_md5_challenge_data_items[evt_eap_md5_challenge_name].name = "name"; evt_md5_challenge_data_items[evt_eap_md5_challenge_name].value_type = ptype_get_type("string"); static struct data_reg evt_eap_md5_challenge_data = { .items = evt_md5_challenge_data_items, .data_count = PROTO_EAP_EVT_MD5_CHALLENGE_DATA_COUNT }; static struct event_reg_info proto_eap_md5_challenge = { 0 }; proto_eap_md5_challenge.source_name = "proto_eap"; proto_eap_md5_challenge.source_obj = priv; proto_eap_md5_challenge.name = "eap_md5_challenge"; proto_eap_md5_challenge.description = "EAP MD5-Challenge"; proto_eap_md5_challenge.data_reg = &evt_eap_md5_challenge_data; priv->evt_md5_challenge = event_register(&proto_eap_md5_challenge); if (!priv->evt_md5_challenge) goto err; static struct data_item_reg evt_success_failure_data_items[PROTO_EAP_EVT_SUCCESS_FAILURE_DATA_COUNT] = { { 0 } }; evt_success_failure_data_items[evt_eap_common_identifier].name = "identifier"; evt_success_failure_data_items[evt_eap_common_identifier].value_type = ptype_get_type("uint8"); evt_success_failure_data_items[evt_eap_success_failure_success].name = "success"; evt_success_failure_data_items[evt_eap_success_failure_success].value_type = ptype_get_type("bool"); static struct data_reg evt_eap_success_failure_data = { .items = evt_success_failure_data_items, .data_count = PROTO_EAP_EVT_SUCCESS_FAILURE_DATA_COUNT }; static struct event_reg_info proto_eap_success_failure = { 0 }; proto_eap_success_failure.source_name = "proto_eap"; proto_eap_success_failure.source_obj = priv; proto_eap_success_failure.name = "eap_success_failure"; proto_eap_success_failure.description = "EAP Success/Failure"; proto_eap_success_failure.data_reg = &evt_eap_success_failure_data; priv->evt_success_failure = event_register(&proto_eap_success_failure); if (!priv->evt_success_failure) goto err; return POM_OK; err: proto_eap_cleanup(priv); return POM_ERR; }
static int input_pcap_interface_init(struct input *i) { if (input_pcap_common_init(i) != POM_OK) return POM_ERR; struct input_pcap_priv *priv = i->priv; struct registry_param *p = NULL; priv->tpriv.iface.p_interface = ptype_alloc("string"); priv->tpriv.iface.p_promisc = ptype_alloc("bool"); priv->tpriv.iface.p_buff_size = ptype_alloc_unit("uint32", "bytes"); if (!priv->tpriv.iface.p_interface || !priv->tpriv.iface.p_promisc || !priv->tpriv.iface.p_buff_size) goto err; priv->tpriv.iface.perf_dropped = registry_instance_add_perf(i->reg_instance, "dropped_pkt", registry_perf_type_counter, "Dropped packets", "pkts"); if (!priv->tpriv.iface.perf_dropped) goto err; registry_perf_set_update_hook(priv->tpriv.iface.perf_dropped, input_pcap_interface_perf_dropped, priv); char err[PCAP_ERRBUF_SIZE] = { 0 }; char *dev = "<none>"; pcap_if_t *alldevsp = NULL; if (pcap_findalldevs(&alldevsp, err)) { pomlog(POMLOG_WARN "Warning, could not find a suitable interface to sniff packets from : %s", err); alldevsp = NULL; } else { dev = alldevsp->name; } p = registry_new_param("interface", dev, priv->tpriv.iface.p_interface, "Interface to capture packets from", 0); if (alldevsp) { pcap_if_t *tmp; for (tmp = alldevsp; tmp; tmp = tmp->next) { if (registry_param_info_add_value(p, tmp->name) != POM_OK) { pcap_freealldevs(alldevsp); goto err; } } pcap_freealldevs(alldevsp); } if (input_add_param(i, p) != POM_OK) goto err; p = registry_new_param("promisc", "no", priv->tpriv.iface.p_promisc, "Promiscious mode", 0); if (input_add_param(i, p) != POM_OK) goto err; p = registry_new_param("buff_size", "16777216", priv->tpriv.iface.p_buff_size, "PCAP ring buffer size", 0); if (input_add_param(i, p) != POM_OK) goto err; priv->type = input_pcap_type_interface; return POM_OK; err: if (priv->tpriv.iface.p_interface) ptype_cleanup(priv->tpriv.iface.p_interface); if (priv->tpriv.iface.p_promisc) ptype_cleanup(priv->tpriv.iface.p_promisc); if (priv->tpriv.iface.p_buff_size) ptype_cleanup(priv->tpriv.iface.p_buff_size); if (p) registry_cleanup_param(p); free(priv); return POM_ERR; }
static int proto_ppp_pap_init(struct proto *proto, struct registry_instance *i) { if (proto_number_register("ppp", 0xc023, proto) != POM_OK) return POM_ERR; struct proto_ppp_pap_priv *priv = malloc(sizeof(struct proto_ppp_pap_priv)); if (!priv) { pom_oom(sizeof(struct proto_ppp_pap_priv)); return POM_ERR; } memset(priv, 0, sizeof(struct proto_ppp_pap_priv)); proto_set_priv(proto, priv); static struct data_item_reg evt_request_data_items[PROTO_PPP_PAP_EVT_REQUEST_DATA_COUNT] = { { 0 } }; evt_request_data_items[evt_ppp_pap_request_code].name = "code"; evt_request_data_items[evt_ppp_pap_request_code].value_type = ptype_get_type("uint8"); evt_request_data_items[evt_ppp_pap_request_identifier].name = "identifier"; evt_request_data_items[evt_ppp_pap_request_identifier].value_type = ptype_get_type("uint8"); evt_request_data_items[evt_ppp_pap_request_peer_id].name = "peer_id"; evt_request_data_items[evt_ppp_pap_request_peer_id].value_type = ptype_get_type("string"); evt_request_data_items[evt_ppp_pap_request_password].name = "password"; evt_request_data_items[evt_ppp_pap_request_password].value_type = ptype_get_type("string"); static struct data_reg evt_ppp_pap_request_data = { .items = evt_request_data_items, .data_count = PROTO_PPP_PAP_EVT_REQUEST_DATA_COUNT }; static struct event_reg_info proto_ppp_pap_request = { 0 }; proto_ppp_pap_request.source_name = "proto_ppp_pap"; proto_ppp_pap_request.source_obj = priv; proto_ppp_pap_request.name = "ppp_pap_request"; proto_ppp_pap_request.description = "PPP PAP Authentication request"; proto_ppp_pap_request.data_reg = &evt_ppp_pap_request_data; priv->evt_request = event_register(&proto_ppp_pap_request); if (!priv->evt_request) goto err; static struct data_item_reg evt_ack_nack_data_items[PROTO_PPP_PAP_EVT_ACK_NACK_DATA_COUNT] = { { 0 } }; evt_ack_nack_data_items[evt_ppp_pap_ack_nack_code].name = "code"; evt_ack_nack_data_items[evt_ppp_pap_ack_nack_code].value_type = ptype_get_type("uint8"); evt_ack_nack_data_items[evt_ppp_pap_ack_nack_identifier].name = "identifier"; evt_ack_nack_data_items[evt_ppp_pap_ack_nack_identifier].value_type = ptype_get_type("uint8"); evt_ack_nack_data_items[evt_ppp_pap_ack_nack_message].name = "message"; evt_ack_nack_data_items[evt_ppp_pap_ack_nack_message].value_type = ptype_get_type("string"); static struct data_reg evt_ppp_pap_ack_nack_data = { .items = evt_ack_nack_data_items, .data_count = PROTO_PPP_PAP_EVT_ACK_NACK_DATA_COUNT }; static struct event_reg_info proto_ppp_pap_ack_nack = { 0 }; proto_ppp_pap_ack_nack.source_name = "proto_ppp_pap"; proto_ppp_pap_ack_nack.source_obj = priv; proto_ppp_pap_ack_nack.name = "ppp_pap_ack_nack"; proto_ppp_pap_ack_nack.description = "PPP-PAP ACK/NACK"; proto_ppp_pap_ack_nack.data_reg = &evt_ppp_pap_ack_nack_data; priv->evt_ack_nack = event_register(&proto_ppp_pap_ack_nack); if (!priv->evt_ack_nack) goto err; priv->p_auth_timeout = ptype_alloc_unit("uint32", "seconds"); if (!priv->p_auth_timeout) goto err; struct registry_param *p = registry_new_param("auth_timeout", "60", priv->p_auth_timeout, "Authentication timeout", 0); if (proto_add_param(proto, p) != POM_OK) { registry_cleanup_param(p); goto err; } return POM_OK; err: proto_ppp_pap_cleanup(priv); return POM_ERR; }
int addon_output_init(struct output *o) { struct addon *addon = o->info->reg_info->mod->priv; lua_State *L = addon_create_state(addon->filename); // Stack : empty if (!L) { pomlog(POMLOG_ERR "Error while creating new lua state for output %s", o->info->reg_info->name); return POM_ERR; } // Get the output from the outputs table lua_getfield(L, LUA_REGISTRYINDEX, ADDON_OUTPUTS_TABLE); // Stack : outputs lua_getfield(L, -1, o->info->reg_info->name); // Stack : outputs, output // Get rid of the outputs table lua_remove(L, -2); // Stack : output lua_pushnil(L); // Stack : output, nil lua_setfield(L, LUA_REGISTRYINDEX, ADDON_OUTPUTS_TABLE); // Stack : output // Add the output to the registry lua_pushvalue(L, -1); // Stack : output, output lua_setfield(L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : output // Create the private data // TODO make __priv read-only struct addon_instance_priv *p = lua_newuserdata(L, sizeof(struct addon_instance_priv)); // Stack : output, priv if (!p) { pom_oom(sizeof(struct addon_instance_priv)); return POM_ERR; } memset(p, 0, sizeof(struct addon_instance_priv)); o->priv = p; p->instance = o; p->L = L; if (pthread_mutex_init(&p->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing mutex : %s", pom_strerror(errno)); abort(); return POM_ERR; } // Assign the output_priv metatable luaL_getmetatable(L, ADDON_OUTPUT_PRIV_METATABLE); // Stack : output, priv, metatable lua_setmetatable(L, -2); // Stack : output, priv // Add it to __priv lua_setfield(L, -2, "__priv"); // Stack : output // Fetch the parameters table lua_getfield(L, -1, "__params"); // Stack : output, params // Parse each param from the class lua_pushnil(L); // Stack : output, params, nil while (lua_next(L, -2) != 0) { // Stack : output, params, key, param if (!lua_istable(L, -1)) { pomlog(POMLOG_ERR "Parameters should be described in tables"); goto err; } // Fetch the name lua_pushinteger(L, 1); // Stack : output, params, key, param, 1 lua_gettable(L, -2); // Stack : output, params, key, param, name if (!lua_isstring(L, -1)) { pomlog(POMLOG_ERR "Parameter name is not a string"); goto err; } const char *name = luaL_checkstring(L, -1); lua_pop(L, 1); // Stack : output, params, key, param // Fetch the ptype type lua_pushinteger(L, 2); // Stack : output, params, key, param, 2 lua_gettable(L, -2); // Stack : output, params, key, param, type if (!lua_isstring(L, -1)) { pomlog(POMLOG_ERR "Parameter type is not a string"); goto err; } const char *type = lua_tostring(L, -1); lua_pop(L, 1); // Stack : output, params, key, param // Fetch the default value lua_pushinteger(L, 3); // Stack : output, params, key, param, 3 lua_gettable(L, -2); // Stack : output, params, key, param, defval if (!lua_isstring(L, -1)) { pomlog(POMLOG_ERR "Parameter default value is not a string"); goto err; } const char *defval = lua_tostring(L, -1); lua_pop(L, 1); // Stack : output, params, key, param // Fetch the description lua_pushinteger(L, 4); // Stack : output, params, key, param, 4 lua_gettable(L, -2); // Stack : output, params, key, param, descr if (!lua_isstring(L, -1)) { pomlog(POMLOG_ERR "Parameter description is not a string"); goto err; } const char *descr = lua_tostring(L, -1); lua_pop(L, 1); // Stack : output, params, key, param // Allocate it struct addon_param *param = malloc(sizeof(struct addon_param)); if (!param) { pom_oom(sizeof(struct addon_param)); goto err; } param->name = strdup(name); if (!param->name) { free(param); pom_oom(strlen(name) + 1); goto err; } param->value = ptype_alloc(type); if (!param->value) { free(param->name); free(param); goto err; } struct registry_param *reg_param = registry_new_param((char*)name, (char*)defval, param->value, (char*)descr, 0); if (output_add_param(o, reg_param) != POM_OK) { pomlog(POMLOG_ERR "Error while adding parameter to the output instance"); if (reg_param) registry_cleanup_param(reg_param); free(param->name); ptype_cleanup(param->value); free(param); goto err; } param->next = p->params; p->params = param; // Pop the value (the param table) lua_pop(L, 1); // Stack : output, params, key } // At this point the stack is : output, params lua_pop(L, 2); // Stack : empty pomlog(POMLOG_DEBUG "Output %s created", o->name); return POM_OK; err: lua_close(L); p->L = NULL; return POM_ERR; }
int input_instance_add(char *type, char *name) { struct input_reg *reg; for (reg = input_reg_head; reg && strcmp(reg->info->name, type); reg = reg->next); if (!reg) { pomlog(POMLOG_ERR "Input type %s does not exists", type); return POM_ERR; } struct input *res = malloc(sizeof(struct input)); if (!res) { pom_oom(sizeof(struct input)); return POM_ERR; } memset(res, 0, sizeof(struct input)); if (pthread_mutex_init(&res->lock, NULL)) { pomlog(POMLOG_ERR "Error while initializing the input mutex : %s", pom_strerror(errno)); goto err; } res->reg = reg; res->name = strdup(name); if (!res->name) { pom_oom(strlen(name) + 1); goto err; } res->reg_instance = registry_add_instance(input_registry_class, name); if (!res->reg_instance) goto err; struct ptype *param_running_val = ptype_alloc("bool"); if (!param_running_val) goto err; struct registry_param *param_running = registry_new_param("running", "no", param_running_val, "Running state of the input", REGISTRY_PARAM_FLAG_CLEANUP_VAL); if (!param_running) { ptype_cleanup(param_running_val); goto err; } res->reg_param_running = param_running; if (registry_param_set_callbacks(param_running, res, NULL, input_instance_start_stop_handler) != POM_OK) { registry_cleanup_param(param_running); ptype_cleanup(param_running_val); goto err; } if (registry_instance_add_param(res->reg_instance, param_running) != POM_OK) { registry_cleanup_param(param_running); ptype_cleanup(param_running_val); goto err; } struct ptype *input_type = ptype_alloc("string"); if (!input_type) goto err; struct registry_param *type_param = registry_new_param("type", type, input_type, "Type of the input", REGISTRY_PARAM_FLAG_CLEANUP_VAL | REGISTRY_PARAM_FLAG_IMMUTABLE); if (!type_param) { ptype_cleanup(input_type); goto err; } if (registry_instance_add_param(res->reg_instance, type_param) != POM_OK) { registry_cleanup_param(type_param); ptype_cleanup(input_type); goto err; } if (registry_uid_create(res->reg_instance) != POM_OK) goto err; res->reg_instance->priv = res; if (reg->info->init) { if (reg->info->init(res) != POM_OK) { pomlog(POMLOG_ERR "Error while initializing the input %s", name); goto err; } } res->next = input_head; if (res->next) res->next->prev = res; input_head = res; return POM_OK; err: if (res->name) free(res->name); if (res->reg_instance) registry_remove_instance(res->reg_instance); free(res); return POM_ERR; }