// Placeholder for all the stuff to do when processing starts static int core_processing_start() { if (*PTYPE_BOOL_GETVAL(core_param_offline_dns) && dns_init() != POM_OK) return POM_ERR; if (*PTYPE_BOOL_GETVAL(core_param_reset_perf_on_restart)) registry_perf_reset_all(); return POM_OK; }
int output_instance_start_stop_handler(void *priv, struct ptype *run) { struct output *o = priv; char *new_state = PTYPE_BOOL_GETVAL(run); if (o->running == *new_state) { pomlog(POMLOG_ERR "Error, output is already %s", (*new_state ? "running" : "stopped")); return POM_ERR; } if (*new_state) { if (o->info->reg_info->open) { if (o->info->reg_info->open(o->priv) != POM_OK) { pomlog(POMLOG_ERR "Error while starting the output"); return POM_ERR; } } registry_perf_timeticks_restart(o->perf_runtime); pomlog("Output %s started", o->info->reg_info->name); } else { if (o->info->reg_info->close) { if (o->info->reg_info->close(o->priv) != POM_OK) { pomlog(POMLOG_ERR "Error while stopping the output"); return POM_ERR; } } registry_perf_timeticks_stop(o->perf_runtime); pomlog("Output %s stopped", o->info->reg_info->name); } o->running = *new_state; return POM_OK; }
// Placeholder for all the stuff to do when processing starts static int core_processing_start() { if (*PTYPE_BOOL_GETVAL(core_param_offline_dns) && dns_init() != POM_OK) return POM_ERR; 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; }
// Placeholder for all the stuff to do when processing stops static int core_processing_stop() { if (*PTYPE_BOOL_GETVAL(core_param_offline_dns)) dns_cleanup(); // Free all the conntracks proto_finish(); return POM_OK; }
int output_file_open(void *output_priv) { struct output_file_priv *priv = output_priv; char *listen_pload_evt = PTYPE_BOOL_GETVAL(priv->p_listen_pload_evt); if (*listen_pload_evt && event_payload_listen_start() != POM_OK) return POM_ERR; return analyzer_pload_output_register(priv, &priv->output_reg); }
int output_file_close(void *output_priv) { if (analyzer_pload_output_unregister(output_priv) != POM_OK) return POM_ERR; struct output_file_priv *priv = output_priv; char *listen_pload_evt = PTYPE_BOOL_GETVAL(priv->p_listen_pload_evt); if (*listen_pload_evt) event_payload_listen_stop(); return POM_OK; }
int core_process_multi_packet(struct proto_process_stack *s, unsigned int stack_index, struct packet *p) { int res = core_process_packet_stack(s, stack_index, p); char *dump_pkt = PTYPE_BOOL_GETVAL(core_param_dump_pkt); if (*dump_pkt) core_process_dump_info(s, p, res); // Clean the stack memset(&s[stack_index], 0, sizeof(struct proto_process_stack) * (CORE_PROTO_STACK_MAX - stack_index)); return res; }
// Placeholder for all the stuff to do when processing stops static int core_processing_stop() { core_pause_processing(); if (*PTYPE_BOOL_GETVAL(core_param_offline_dns)) dns_core_cleanup(); // Free all the conntracks proto_finish(); // Give the analyzers the chance to clear their state analyzer_finish(); core_resume_processing(); return POM_OK; }
int core_process_packet(struct packet *p) { struct proto_process_stack s[CORE_PROTO_STACK_MAX + 2]; // Add one entry at the begining and the end memset(s, 0, sizeof(struct proto_process_stack) * (CORE_PROTO_STACK_MAX + 2)); s[CORE_PROTO_STACK_START].pload = p->buff; s[CORE_PROTO_STACK_START].plen = p->len; s[CORE_PROTO_STACK_START].proto = p->datalink; int res = core_process_packet_stack(s, CORE_PROTO_STACK_START, p); char *dump_pkt = PTYPE_BOOL_GETVAL(core_param_dump_pkt); if (*dump_pkt) core_process_dump_info(s, p, res); if (res == PROTO_ERR) return PROTO_ERR; return PROTO_OK; }
static int input_pcap_interface_open(struct input *i) { struct input_pcap_priv *p = i->priv; char errbuf[PCAP_ERRBUF_SIZE + 1] = { 0 }; char *interface = PTYPE_STRING_GETVAL(p->tpriv.iface.p_interface); p->p = pcap_create(interface, errbuf); if (!p->p) { pomlog(POMLOG_ERR "Error opening interface %s : %s", interface, errbuf); return POM_ERR; } char *promisc = PTYPE_BOOL_GETVAL(p->tpriv.iface.p_promisc); int err = pcap_set_promisc(p->p, *promisc); if (err) pomlog(POMLOG_WARN "Error while setting promisc mode : %s", pcap_statustostr(err)); uint32_t buff_size = *PTYPE_UINT32_GETVAL(p->tpriv.iface.p_buff_size); err = pcap_set_buffer_size(p->p, buff_size); if (err) pomlog(POMLOG_WARN "Error while setting the pcap buffer size : %s", pcap_statustostr(err)); err = pcap_activate(p->p); if (err < 0) { pomlog(POMLOG_ERR "Error while activating pcap : %s", pcap_statustostr(err)); return POM_ERR; } else if (err > 0) { pomlog(POMLOG_WARN "Warning while activating pcap : %s", pcap_statustostr(err)); } return input_pcap_common_open(i); }
int output_file_open(void *output_priv) { struct output_file_priv *priv = output_priv; char *filter_str = PTYPE_STRING_GETVAL(priv->p_filter); struct filter *filter = NULL; if (strlen(filter_str)) { filter = pload_filter_compile(filter_str); if (!filter) { pomlog(POMLOG_ERR "Error while parsing filter '%s'", filter_str); return POM_ERR; } } char *listen_pload_evt = PTYPE_BOOL_GETVAL(priv->p_listen_pload_evt); if (*listen_pload_evt && event_payload_listen_start() != POM_OK) { if (filter) filter_cleanup(filter); return POM_ERR; } return pload_listen_start(output_priv, NULL, filter, output_file_pload_open, output_file_pload_write, output_file_pload_close); }
static int analyzer_tftp_pkt_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) { struct analyzer_tftp_priv *priv = obj; struct proto_process_stack *s = &stack[stack_index]; struct proto_process_stack *s_prev = &stack[stack_index - 1]; uint16_t opcode = *PTYPE_UINT16_GETVAL(s_prev->pkt_info->fields_value[proto_tftp_field_opcode]); // Get the session struct conntrack_session *session = conntrack_session_get(s_prev->ce); if (!session) return POM_ERR; struct analyzer_tftp_session_priv *spriv = conntrack_session_get_priv(session, obj); if (!spriv) { // Add session priv if it is not done yet spriv = malloc(sizeof(struct analyzer_tftp_session_priv)); if (!spriv) { pom_oom(sizeof(struct analyzer_tftp_session_priv)); goto err; } memset(spriv, 0, sizeof(struct analyzer_tftp_session_priv)); if (conntrack_session_add_priv(session, obj, spriv, analyzer_tftp_session_priv_cleanup) != POM_OK) { free(spriv); goto err; } } void *pload = s->pload; uint32_t plen = s->plen; switch (opcode) { case tftp_rrq: case tftp_wrq: { if (plen < 3) return POM_OK; // Invalid packet // Find the filename // The below should always be valid as proto_tftp already checked this char *filename = pload; char *mode = memchr(filename, 0, plen - 1) + 1; struct analyzer_tftp_file *fq = malloc(sizeof(struct analyzer_tftp_file)); if (!fq) { pom_oom(sizeof(struct analyzer_tftp_file)); goto err; } memset(fq, 0, sizeof(struct analyzer_tftp_file)); // Get the port on which we expect this file // No need to check the IP as we got the session biding struct proto_process_stack *s_l4 = &stack[stack_index - 2]; unsigned int i; for (i = 0; !fq->port ; i++) { struct proto_reg_info *pinfo = proto_get_info(s_l4->proto); char *name = pinfo->pkt_fields[i].name; if (!name) { pomlog(POMLOG_ERR "Source port not found in RRQ/WRQ packets"); goto err; } if (!strcmp(name, "sport")) { fq->port = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]); break; } } fq->evt = event_alloc(priv->evt_file); if (!fq->evt) { free(fq); goto err; } struct data *evt_data = event_get_data(fq->evt); PTYPE_STRING_SETVAL(evt_data[analyzer_tftp_file_filename].value, filename); data_set(evt_data[analyzer_tftp_file_filename]); PTYPE_STRING_SETVAL(evt_data[analyzer_tftp_file_mode].value, mode); data_set(evt_data[analyzer_tftp_file_mode]); PTYPE_BOOL_SETVAL(evt_data[analyzer_tftp_file_write].value, opcode == tftp_wrq); data_set(evt_data[analyzer_tftp_file_write]); fq->next = spriv->files; if (fq->next) fq->next->prev = fq; spriv->files = fq; conntrack_session_unlock(session); event_process_begin(fq->evt, stack, stack_index, p->ts); break; } case tftp_data: { if (plen < sizeof(uint16_t)) return POM_OK; // Invalid packet struct analyzer_tftp_file *f = conntrack_get_priv(s_prev->ce, obj); struct data *evt_data = NULL; if (!f) { // The file is not yet associated to this connection // Find it in the queue struct proto_process_stack *s_l4 = &stack[stack_index - 2]; unsigned int i; uint16_t sport = 0, dport = 0; for (i = 0; !sport || !dport ; i++) { struct proto_reg_info *pinfo = proto_get_info(s_l4->proto); char *name = pinfo->pkt_fields[i].name; if (!name) { pomlog(POMLOG_ERR "Source port not found in data packets"); goto err; } if (!strcmp(name, "sport")) sport = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]); if (!strcmp(name, "dport")) dport = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]); } // Find the file in the session list for (f = spriv->files; ; f = f->next) { evt_data = event_get_data(f->evt); if (*PTYPE_BOOL_GETVAL(evt_data[analyzer_tftp_file_write].value)) { if (f->port == sport) break; } else { if (f->port == dport) break; } } if (!f) { pomlog(POMLOG_DEBUG "File not found in queued file request."); conntrack_session_unlock(session); return POM_OK; } // Remove the file from the queue and assign it to the conntrack if (f->prev) f->prev->next = f->next; else spriv->files = f->next; if (f->next) f->next->prev = f->prev; f->prev = NULL; f->next = NULL; // Create the payload buffer f->pload = pload_alloc(f->evt, PLOAD_FLAG_NEED_MAGIC); if (!f->pload) goto err; conntrack_add_priv(s_prev->ce, obj, f, analyzer_tftp_conntrack_priv_cleanup); } else { evt_data = event_get_data(f->evt); } conntrack_session_unlock(session); if (!f->pload) { pomlog(POMLOG_DEBUG "Ignoring extra packet"); return POM_OK; } // Discard the block ID pload += sizeof(uint16_t); plen -= sizeof(uint16_t); if (pload_append(f->pload, pload, plen) != POM_OK) goto err; uint32_t *size = PTYPE_UINT32_GETVAL(evt_data[analyzer_tftp_file_size].value); *size += plen; if (plen < ANALYZER_TFTP_BLK_SIZE) { // Got last packet ! data_set(evt_data[analyzer_tftp_file_size]); int res = pload_end(f->pload); res += event_process_end(f->evt); f->evt = NULL; f->pload = NULL; if (res) goto err; } break; } case tftp_error: { conntrack_session_unlock(session); struct analyzer_tftp_file *f = conntrack_get_priv(s_prev->ce, obj); if (f && f->pload) { int res = pload_end(f->pload); res += event_process_end(f->evt); f->pload = NULL; f->evt = NULL; if (res) goto err; } break; } default: conntrack_session_unlock(session); break; } return POM_OK; err: conntrack_session_unlock(session); return POM_ERR; }
int input_instance_start_stop_handler(void *priv, struct ptype *run) { struct input *i = priv; char *new_state = PTYPE_BOOL_GETVAL(run); pom_mutex_lock(&i->lock); char cur_state = (i->running == INPUT_RUN_STOPPED ? 0 : 1); if (cur_state == *new_state) { pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "Error, input is already %s", (cur_state ? "running" : "stopped")); return POM_ERR; } if (*new_state) { if (!(i->reg->info->flags & INPUT_REG_FLAG_LIVE)) { struct input *tmp; for (tmp = input_head; tmp; tmp = tmp->next) { if (tmp != i) { pom_mutex_lock(&tmp->lock); if (i->running) { pom_mutex_unlock(&tmp->lock); pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "When using non-live input, it can only be started alone"); return POM_ERR; } pom_mutex_unlock(&tmp->lock); } } } if (i->reg->info->open && i->reg->info->open(i) != POM_OK) { pomlog(POMLOG_ERR "Error while starting input %s", i->name); pom_mutex_unlock(&i->lock); return POM_ERR; } i->running = INPUT_RUN_RUNNING; pom_mutex_unlock(&i->lock); if (pthread_create(&i->thread, NULL, input_process_thread, (void*) i)) { pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "Unable to start a new thread for input %s : %s", i->name, pom_strerror(errno)); return POM_ERR; } input_cur_running++; if (input_cur_running == 1) core_set_state(core_state_running); } else { i->running = INPUT_RUN_STOPPING; pom_mutex_unlock(&i->lock); if (i->reg->info->interrupt && i->reg->info->interrupt(i) == POM_ERR) { pomlog(POMLOG_WARN "Warning : error while interrupting the read process of the input"); } if (i->thread != pthread_self()) { if (pthread_join(i->thread, NULL)) pomlog(POMLOG_WARN "Error while joining the input thread : %s", pom_strerror(errno)); } else { if (pthread_detach(i->thread)) pomlog(POMLOG_WARN "Error while detaching the input thread : %s", pom_strerror(errno)); } input_cur_running--; if (!input_cur_running) core_set_state(core_state_finishing); } return POM_OK; }