static int analyzer_smtp_pkt_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) { struct analyzer *analyzer = obj; struct proto_process_stack *s = &stack[stack_index - 1]; if (!s->ce) return POM_ERR; struct analyzer_smtp_ce_priv *cpriv = conntrack_get_priv(s->ce, analyzer); if (!event_is_started(cpriv->evt_msg)) { pomlog(POMLOG_ERR "Payload received while data event not found"); return POM_OK; } struct pload *pload_buff = event_get_priv(cpriv->evt_msg); if (!pload_buff) { pload_buff = pload_alloc(cpriv->evt_msg, 0); pload_set_type(pload_buff, ANALYZER_SMTP_RFC822_PLOAD_TYPE); if (!pload_buff) return POM_ERR; event_set_priv(cpriv->evt_msg, pload_buff); } struct proto_process_stack *pload_stack = &stack[stack_index]; char *pload = pload_stack->pload; size_t plen = pload_stack->plen; // Look for the end of the "<CR><LF>.." sequence if any if (cpriv->dotdot_pos > 0){ int i, found = 1; for (i = 0; i < ANALYZER_SMTP_DOTDOT_LEN - cpriv->dotdot_pos && i <= plen; i++) { if (*(char*)(pload + i) != ANALYZER_SMTP_DOTDOT[cpriv->dotdot_pos + i]) { found = 0; break; } } if (i >= ANALYZER_SMTP_DOTDOT_LEN - cpriv->dotdot_pos) { if (found && (i >= ANALYZER_SMTP_DOTDOT_LEN - cpriv->dotdot_pos)) { // Process up to the last dot size_t len = ANALYZER_SMTP_DOTDOT_LEN - cpriv->dotdot_pos; if (pload_append(pload_buff, pload, len - 1) != POM_OK) return POM_ERR; pload += len; plen -= len; } cpriv->dotdot_pos = 0; } else { cpriv->dotdot_pos += i; } } while (plen) { char * dotdot = pom_strnstr(pload, ANALYZER_SMTP_DOTDOT, plen); if (!dotdot) break; size_t dotdot_len = dotdot - pload + ANALYZER_SMTP_DOTDOT_LEN; if (pload_append(pload_buff, pload, dotdot_len - 1) != POM_OK) return POM_ERR; pload = dotdot + ANALYZER_SMTP_DOTDOT_LEN; plen -= dotdot_len; } // Check for a possible partial dotdot at the end of the pload int i, found = 0; for (i = 1; (i < ANALYZER_SMTP_DOTDOT_LEN) && (i <= plen); i++) { if (!memcmp(pload + plen - i, ANALYZER_SMTP_DOTDOT, i)) { found = 1; } break; } if (found) cpriv->dotdot_pos = i; // Add whatever remains if (plen && pload_append(pload_buff, pload, plen) != POM_OK) return POM_ERR; return POM_OK; }
static int analyzer_rtp_pload_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) { struct analyzer *analyzer = obj; struct analyzer_rtp_priv *priv = analyzer->priv; struct proto_process_stack *pload_stack = &stack[stack_index]; struct proto_process_stack *s = &stack[stack_index - 1]; if (!s->ce) return POM_ERR; struct analyzer_rtp_ce_priv *cp = conntrack_get_priv(s->ce, obj); if (!cp) { cp = malloc(sizeof(struct analyzer_rtp_ce_priv)); if (!cp) { pom_oom(sizeof(struct analyzer_rtp_ce_priv)); return POM_ERR; } memset(cp, 0, sizeof(struct analyzer_rtp_ce_priv)); if (conntrack_add_priv(s->ce, obj, cp, analyzer_rtp_ce_cleanup) != POM_OK) return POM_ERR; } int dir = s->direction; if (!cp->evt[dir]) { cp->evt[dir] = event_alloc(priv->evt_rtp_stream); if (!cp->evt[dir]) return POM_ERR; struct data *evt_data = event_get_data(cp->evt[dir]); ptype_copy(evt_data[analyzer_rtp_stream_ssrc].value, s->pkt_info->fields_value[proto_rtp_field_ssrc]); data_set(evt_data[analyzer_rtp_stream_ssrc]); // For now we always assume RTP is over UDP or TCP if (stack_index > 2) { struct proto_process_stack *l4_stack = &stack[stack_index - 2]; unsigned int i; for (i = 0; !data_is_set(evt_data[analyzer_rtp_stream_src_port]) || !data_is_set(evt_data[analyzer_rtp_stream_dst_port]); i++) { struct proto_reg_info *l4_info = proto_get_info(l4_stack->proto); char *name = l4_info->pkt_fields[i].name; if (!name) break; if (!data_is_set(evt_data[analyzer_rtp_stream_src_port]) && !strcmp(name, "sport")) { ptype_copy(evt_data[analyzer_rtp_stream_src_port].value, l4_stack->pkt_info->fields_value[i]); data_set(evt_data[analyzer_rtp_stream_src_port]); } else if (!data_is_set(evt_data[analyzer_rtp_stream_dst_port]) && !strcmp(name, "dport")) { ptype_copy(evt_data[analyzer_rtp_stream_dst_port].value, l4_stack->pkt_info->fields_value[i]); data_set(evt_data[analyzer_rtp_stream_dst_port]); } } } if (stack_index > 3) { struct proto_process_stack *l3_stack = &stack[stack_index - 3]; unsigned int i; for (i = 0; !data_is_set(evt_data[analyzer_rtp_stream_src_addr]) || !data_is_set(evt_data[analyzer_rtp_stream_dst_addr]); i++) { struct proto_reg_info *l3_info = proto_get_info(l3_stack->proto); char *name = l3_info->pkt_fields[i].name; if (!name) break; if (!data_is_set(evt_data[analyzer_rtp_stream_src_addr]) && !strcmp(name, "src")) { evt_data[analyzer_rtp_stream_src_addr].value = ptype_alloc_from(l3_stack->pkt_info->fields_value[i]); if (evt_data[analyzer_rtp_stream_src_addr].value) data_set(evt_data[analyzer_rtp_stream_src_addr]); } else if (!data_is_set(evt_data[analyzer_rtp_stream_dst_addr]) && !strcmp(name, "dst")) { evt_data[analyzer_rtp_stream_dst_addr].value = ptype_alloc_from(l3_stack->pkt_info->fields_value[i]); if (evt_data[analyzer_rtp_stream_dst_addr].value) data_set(evt_data[analyzer_rtp_stream_dst_addr]); } } } struct proto *sess_proto = telephony_stream_info_get_sess_proto(s->ce); if (sess_proto) { struct proto_reg_info *proto_reg = proto_get_info(sess_proto); PTYPE_STRING_SETVAL(evt_data[analyzer_rtp_stream_sess_proto].value, proto_reg->name); data_set(evt_data[analyzer_rtp_stream_sess_proto]); } char *call_id = telephony_stream_info_get_call_id(s->ce); if (call_id) { PTYPE_STRING_SETVAL_P(evt_data[analyzer_rtp_stream_call_id].value, call_id); data_set(evt_data[analyzer_rtp_stream_call_id]); } if (event_process_begin(cp->evt[dir], stack, stack_index, p->ts) != POM_OK) return POM_ERR; } if (!cp->pload[dir]) { cp->pload[dir] = pload_alloc(cp->evt[dir], 0); if (!cp->pload[dir]) return POM_ERR; struct telephony_codec_info info = { 0 }; if (telephony_stream_info_get_codec(&info, stack, stack_index - 1) == POM_OK) { char *pload_type = telephony_codec_info_get_pload_type(&info); if (pload_type) pload_set_type(cp->pload[dir], pload_type); } } if (pload_append(cp->pload[dir], pload_stack->pload, pload_stack->plen) != POM_OK) return POM_ERR; return POM_OK; }