/** * \brief Setup a pseudo packet (tunnel) * * \param parent parent packet for this pseudo pkt * \param pkt raw packet data * \param len packet data length * \param proto protocol of the tunneled packet * * \retval p the pseudo packet or NULL if out of memory */ Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto, PacketQueue *pq) { int ret; SCEnter(); /* get us a packet */ Packet *p = PacketGetFromQueueOrAlloc(); if (unlikely(p == NULL)) { SCReturnPtr(NULL, "Packet"); } /* copy packet and set lenght, proto */ PacketCopyData(p, pkt, len); p->recursion_level = parent->recursion_level + 1; p->ts.tv_sec = parent->ts.tv_sec; p->ts.tv_usec = parent->ts.tv_usec; p->datalink = DLT_RAW; /* set the root ptr to the lowest layer */ if (parent->root != NULL) p->root = parent->root; else p->root = parent; /* tell new packet it's part of a tunnel */ SET_TUNNEL_PKT(p); ret = DecodeTunnel(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq, proto); if (unlikely(ret != TM_ECODE_OK)) { /* Not a tunnel packet, just a pseudo packet */ p->root = NULL; UNSET_TUNNEL_PKT(p); TmqhOutputPacketpool(tv, p); SCReturnPtr(NULL, "Packet"); } /* tell parent packet it's part of a tunnel */ SET_TUNNEL_PKT(parent); /* increment tunnel packet refcnt in the root packet */ TUNNEL_INCR_PKT_TPR(p); /* disable payload (not packet) inspection on the parent, as the payload * is the packet we will now run through the system separately. We do * check it against the ip/port/other header checks though */ DecodeSetNoPayloadInspectionFlag(parent); SCReturnPtr(p, "Packet"); }
void DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { SCPerfCounterIncr(dtv->counter_raw, tv->sc_perf_pca); /* If it is ipv4 or ipv6 it should at least be the size of ipv4 */ if (len < IPV4_HEADER_LEN) { ENGINE_SET_EVENT(p,IPV4_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 4) { SCLogDebug("IPV4 Packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if (IP_GET_RAW_VER(pkt) == 6) { SCLogDebug("IPV6 Packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { SCLogDebug("Unknown ip version %" PRIu8 "", IP_GET_RAW_VER(pkt)); ENGINE_SET_EVENT(p,IPRAW_INVALID_IPV); } return; }
/** * \brief This function passes off to link type decoders. * * DecodePcap reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodePcap(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ DecodeUpdatePacketCounters(tv, dtv, p); /* call the decoder */ switch(p->datalink) { case LINKTYPE_LINUX_SLL: DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_PPP: DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_RAW: DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; case LINKTYPE_NULL: DecodeNull(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodePcap", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
/** * \brief This function passes off to link type decoders. * \todo Unit tests are needed for this module. * * DecodeIPFW reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param tv pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into IPFWThreadVars for ptv * \param pq pointer to the PacketQueue */ TmEcode DecodeIPFW(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p); IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p); DecodeThreadVars *dtv = (DecodeThreadVars *)data; SCEnter(); /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); /* Process IP packets */ if (IPV4_GET_RAW_VER(ip4h) == 4) { SCLogDebug("DecodeIPFW ip4 processing"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { SCLogDebug("DecodeIPFW ip6 processing"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { /* We don't support anything besides IP packets for now, bridged packets? */ SCLogInfo("IPFW unknown protocol support %02x", *GET_PKT_DATA(p)); SCReturnInt(TM_ECODE_FAILED); } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
/** * \test routing header decode */ static int DecodeIPV6RouteTest01 (void) { uint8_t raw_pkt1[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2b, 0x40, 0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xed, 0x00, 0x50, 0x1b, 0xc7, 0x6a, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0xfa, 0x87, 0x00, 0x00, }; Packet *p1 = PacketGetFromAlloc(); if (unlikely(p1 == NULL)) return 0; ThreadVars tv; DecodeThreadVars dtv; int result = 0; PacketQueue pq; FlowInitConfig(FLOW_QUIET); memset(&pq, 0, sizeof(PacketQueue)); memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); PacketCopyData(p1, raw_pkt1, sizeof(raw_pkt1)); DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); if (!(IPV6_EXTHDR_ISSET_RH(p1))) { printf("ipv6 routing header not detected: "); goto end; } if (p1->ip6eh.ip6_exthdrs[0].len != 8) { printf("ipv6 routing length incorrect: "); goto end; } result = 1; end: PACKET_RECYCLE(p1); SCFree(p1); FlowShutdown(); return result; }
/** * \test HOP header decode */ static int DecodeIPV6HopTest01 (void) { uint8_t raw_pkt1[] = { 0x60,0x00,0x00,0x00,0x00,0x20,0x00,0x01,0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x0f,0xfe,0xff,0xfe,0x98,0x3d,0x01,0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3a,0x00,0x05,0x02,0x00,0x00,0x00,0x00, 0x82,0x00,0x1c,0x6f,0x27,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; Packet *p1 = PacketGetFromAlloc(); if (unlikely(p1 == NULL)) return 0; ThreadVars tv; DecodeThreadVars dtv; int result = 0; PacketQueue pq; FlowInitConfig(FLOW_QUIET); memset(&pq, 0, sizeof(PacketQueue)); memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); PacketCopyData(p1, raw_pkt1, sizeof(raw_pkt1)); DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); if (!(IPV6_EXTHDR_ISSET_HH(p1))) { printf("ipv6 routing header not detected: "); goto end; } if (p1->ip6eh.ip6_exthdrs[0].len != 8) { printf("ipv6 routing length incorrect: "); goto end; } if (ENGINE_ISSET_EVENT(p1, IPV6_HOPOPTS_UNKNOWN_OPT)) { printf("engine event IPV6_HOPOPTS_UNKNOWN_OPT set: "); goto end; } result = 1; end: PACKET_RECYCLE(p1); SCFree(p1); FlowShutdown(); return result; }
/** * \brief Decode a packet coming from NFQ */ TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p); IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0); #endif if (IPV4_GET_RAW_VER(ip4h) == 4) { SCLogDebug("IPv4 packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { SCLogDebug("IPv6 packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { SCLogDebug("packet unsupported by NFQ, first byte: %02x", *GET_PKT_DATA(p)); } PacketDecodeFinalize(tv, dtv, p); return TM_ECODE_OK; }
static void AlertJsonPacket(const Packet *p, json_t *js) { unsigned long len = GET_PKT_LEN(p) * 2; uint8_t encoded_packet[len]; Base64Encode((unsigned char*) GET_PKT_DATA(p), GET_PKT_LEN(p), encoded_packet, &len); json_object_set_new(js, "packet", json_string((char *)encoded_packet)); /* Create packet info. */ json_t *packetinfo_js = json_object(); if (unlikely(packetinfo_js == NULL)) { return; } json_object_set_new(packetinfo_js, "linktype", json_integer(p->datalink)); json_object_set_new(js, "packet_info", packetinfo_js); }
TmEcode AlertFastLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; char timebuf[64]; char *action = ""; extern uint8_t engine_mode; if (p->alerts.cnt == 0) return TM_ECODE_OK; CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } if ((pa->action & ACTION_DROP) && IS_ENGINE_MODE_IPS(engine_mode)) { action = "[Drop] "; } else if (pa->action & ACTION_DROP) { action = "[wDrop] "; } SCMutexLock(&aft->file_ctx->fp_mutex); fprintf(aft->file_ctx->fp, "%s %s[**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: " "%" PRIu32 "] [**] [Raw pkt: ", timebuf, action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio); PrintRawLineHexFp(aft->file_ctx->fp, GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32); if (p->pcap_cnt != 0) { fprintf(aft->file_ctx->fp, "] [pcap file packet: %"PRIu64"]\n", p->pcap_cnt); } else { fprintf(aft->file_ctx->fp, "]\n"); } fflush(aft->file_ctx->fp); aft->file_ctx->alerts++; SCMutexUnlock(&aft->file_ctx->fp_mutex); } return TM_ECODE_OK; }
/** * \brief This function passes off to link type decoders. * * DecodeErfDag reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodeErfDag(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); /* call the decoder */ switch(p->datalink) { case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeErfDag", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
TmEcode DecodePcapFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (p->flags & PKT_PSEUDO_STREAM_END) return TM_ECODE_OK; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0 ); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); double curr_ts = p->ts.tv_sec + p->ts.tv_usec / 1000.0; if (curr_ts < prev_signaled_ts || (curr_ts - prev_signaled_ts) > 60.0) { prev_signaled_ts = curr_ts; FlowWakeupFlowManagerThread(); } /* update the engine time representation based on the timestamp * of the packet. */ TimeSet(&p->ts); /* call the decoder */ pcap_g.Decoder(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); #ifdef DEBUG BUG_ON(p->pkt_src != PKT_SRC_WIRE && p->pkt_src != PKT_SRC_FFR_V2); #endif PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
TmEcode AlertDebugLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { AlertDebugLogThread *aft = (AlertDebugLogThread *)data; int i; char timebuf[64]; if (p->alerts.cnt == 0) return TM_ECODE_OK; CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); SCMutexLock(&aft->file_ctx->fp_mutex); fprintf(aft->file_ctx->fp, "+================\n"); fprintf(aft->file_ctx->fp, "TIME: %s\n", timebuf); if (p->pcap_cnt > 0) { fprintf(aft->file_ctx->fp, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt); } fprintf(aft->file_ctx->fp, "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; fprintf(aft->file_ctx->fp, "ALERT MSG [%02d]: %s\n", i, pa->msg); fprintf(aft->file_ctx->fp, "ALERT GID [%02d]: %" PRIu32 "\n", i, pa->gid); fprintf(aft->file_ctx->fp, "ALERT SID [%02d]: %" PRIu32 "\n", i, pa->sid); fprintf(aft->file_ctx->fp, "ALERT REV [%02d]: %" PRIu32 "\n", i, pa->rev); fprintf(aft->file_ctx->fp, "ALERT CLASS [%02d]: %s\n", i, pa->class_msg); fprintf(aft->file_ctx->fp, "ALERT PRIO [%02d]: %" PRIu32 "\n", i, pa->prio); } aft->file_ctx->alerts += p->alerts.cnt; fprintf(aft->file_ctx->fp, "PACKET LEN: %" PRIu32 "\n", GET_PKT_LEN(p)); fprintf(aft->file_ctx->fp, "PACKET:\n"); PrintRawDataFp(aft->file_ctx->fp, GET_PKT_DATA(p), GET_PKT_LEN(p)); fflush(aft->file_ctx->fp); SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; }
static inline #endif void DecodeIPV6FragHeader(Packet *p, uint8_t *pkt, uint16_t hdrextlen, uint16_t plen, uint16_t prev_hdrextlen) { uint16_t frag_offset = (*(pkt + 2) << 8 | *(pkt + 3)) & 0xFFF8; int frag_morefrags = (*(pkt + 2) << 8 | *(pkt + 3)) & 0x0001; p->ip6eh.fh_offset = frag_offset; p->ip6eh.fh_more_frags_set = frag_morefrags ? TRUE : FALSE; p->ip6eh.fh_nh = *pkt; uint32_t fh_id; memcpy(&fh_id, pkt+4, 4); p->ip6eh.fh_id = SCNtohl(fh_id); SCLogDebug("IPV6 FH: offset %u, mf %s, nh %u, id %u/%x", p->ip6eh.fh_offset, p->ip6eh.fh_more_frags_set ? "true" : "false", p->ip6eh.fh_nh, p->ip6eh.fh_id, p->ip6eh.fh_id); // store header offset, data offset uint16_t frag_hdr_offset = (uint16_t)(pkt - GET_PKT_DATA(p)); uint16_t data_offset = (uint16_t)(frag_hdr_offset + hdrextlen); uint16_t data_len = plen - hdrextlen; p->ip6eh.fh_header_offset = frag_hdr_offset; p->ip6eh.fh_data_offset = data_offset; p->ip6eh.fh_data_len = data_len; /* if we have a prev hdr, store the type and offset of it */ if (prev_hdrextlen) { p->ip6eh.fh_prev_hdr_offset = frag_hdr_offset - prev_hdrextlen; } SCLogDebug("IPV6 FH: frag_hdr_offset %u, data_offset %u, data_len %u", p->ip6eh.fh_header_offset, p->ip6eh.fh_data_offset, p->ip6eh.fh_data_len); }
/** * \brief Function to decode IPv4 in IPv6 packets * */ static void DecodeIP6inIP6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t plen, PacketQueue *pq) { if (unlikely(plen < IPV6_HEADER_LEN)) { ENGINE_SET_EVENT(p, IPV6_IN_IPV6_PKT_TOO_SMALL); return; } if (IP_GET_RAW_VER(pkt) == 6) { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt, plen, IPPROTO_IPV6); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, IPPROTO_IP); PacketEnqueue(pq,tp); SCPerfCounterIncr(dtv->counter_ipv6inipv6, tv->sc_perf_pca); return; } } } else { ENGINE_SET_EVENT(p, IPV6_IN_IPV6_WRONG_IP_VER); } return; }
/** * \test routing header decode */ static int DecodeIPV6RouteTest01 (void) { uint8_t raw_pkt1[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2b, 0x40, 0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xed, 0x00, 0x50, 0x1b, 0xc7, 0x6a, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0xfa, 0x87, 0x00, 0x00, }; Packet *p1 = PacketGetFromAlloc(); FAIL_IF(unlikely(p1 == NULL)); ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; FlowInitConfig(FLOW_QUIET); memset(&pq, 0, sizeof(PacketQueue)); memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); PacketCopyData(p1, raw_pkt1, sizeof(raw_pkt1)); DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); FAIL_IF (!(IPV6_EXTHDR_ISSET_RH(p1))); FAIL_IF (p1->ip6eh.rh_type != 0); PACKET_RECYCLE(p1); SCFree(p1); FlowShutdown(); PASS; }
/** * \brief Decode the ERF file. * * This function ups the decoder counters and then passes the packet * off to the ethernet decoder. */ TmEcode DecodeErfFile(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* Update counters. */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0 ); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); SCReturnInt(TM_ECODE_OK); }
/** * \brief This function passes off to link type decoders. * * DecodeErfDag reads packets from the PacketQueue and passes * them off to the proper link type decoder. * * \param t pointer to ThreadVars * \param p pointer to the current packet * \param data pointer that gets cast into PcapThreadVars for ptv * \param pq pointer to the current PacketQueue */ TmEcode DecodeErfDag(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { SCEnter(); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* update counters */ SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca); // SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca); SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p)); #if 0 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca, (GET_PKT_LEN(p) * 8)/1000000.0); #endif SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p)); /* call the decoder */ switch(p->datalink) { case LINKTYPE_ETHERNET: DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); break; default: SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeErfDag", p->datalink); break; } PacketDecodeFinalize(tv, dtv, p); SCReturnInt(TM_ECODE_OK); }
/** * \brief NFQ verdict function */ TmEcode NFQSetVerdict(Packet *p) { int iter = 0; int ret = 0; uint32_t verdict = NF_ACCEPT; /* we could also have a direct pointer but we need to have a ref counf in this case */ NFQQueueVars *t = nfq_q + p->nfq_v.nfq_index; /** \todo add a test on validity of the entry NFQQueueVars could have been * wipeout */ /* can't verdict a "fake" packet */ if (p->flags & PKT_PSEUDO_STREAM_END) { return TM_ECODE_OK; } //printf("%p verdicting on queue %" PRIu32 "\n", t, t->queue_num); NFQMutexLock(t); if (t->qh == NULL) { /* Somebody has started a clean-up, we leave */ NFQMutexUnlock(t); return TM_ECODE_OK; } if (p->action & ACTION_DROP) { verdict = NF_DROP; #ifdef COUNTERS t->dropped++; #endif /* COUNTERS */ } else { switch (nfq_config.mode) { default: case NFQ_ACCEPT_MODE: verdict = NF_ACCEPT; break; case NFQ_REPEAT_MODE: verdict = NF_REPEAT; break; case NFQ_ROUTE_MODE: verdict = ((uint32_t) NF_QUEUE) | nfq_config.next_queue; break; } if (p->flags & PKT_STREAM_MODIFIED) { #ifdef COUNTERS t->replaced++; #endif /* COUNTERS */ } #ifdef COUNTERS t->accepted++; #endif /* COUNTERS */ } do { switch (nfq_config.mode) { default: case NFQ_ACCEPT_MODE: case NFQ_ROUTE_MODE: if (p->flags & PKT_MARK_MODIFIED) { #ifdef HAVE_NFQ_SET_VERDICT2 if (p->flags & PKT_STREAM_MODIFIED) { ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, p->nfq_v.mark, GET_PKT_LEN(p), GET_PKT_DATA(p)); } else { ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, p->nfq_v.mark, 0, NULL); } #else /* fall back to old function */ if (p->flags & PKT_STREAM_MODIFIED) { ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl(p->nfq_v.mark), GET_PKT_LEN(p), GET_PKT_DATA(p)); } else { ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl(p->nfq_v.mark), 0, NULL); } #endif /* HAVE_NFQ_SET_VERDICT2 */ } else { if (p->flags & PKT_STREAM_MODIFIED) { ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, GET_PKT_LEN(p), GET_PKT_DATA(p)); } else { ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, 0, NULL); } } break; case NFQ_REPEAT_MODE: #ifdef HAVE_NFQ_SET_VERDICT2 if (p->flags & PKT_STREAM_MODIFIED) { ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask), GET_PKT_LEN(p), GET_PKT_DATA(p)); } else { ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask), 0, NULL); } #else /* fall back to old function */ if (p->flags & PKT_STREAM_MODIFIED) { ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)), GET_PKT_LEN(p), GET_PKT_DATA(p)); } else { ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)), 0, NULL); } #endif /* HAVE_NFQ_SET_VERDICT2 */ break; } } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_TIME)); NFQMutexUnlock(t); if (ret < 0) { SCLogWarning(SC_ERR_NFQ_SET_VERDICT, "nfq_set_verdict of %p failed %" PRId32 "", p, ret); return TM_ECODE_FAILED; } return TM_ECODE_OK; }
/** * \brief UTHBuildPacketReal is a function that create tcp/udp packets for unittests * specifying ip and port sources and destinations * * \param payload pointer to the payloadd buffer * \param payload_len pointer to the length of the payload * \param ipproto Protocols allowed atm are IPPROTO_TCP and IPPROTO_UDP * \param src pointer to a string containing the ip source * \param dst pointer to a string containing the ip destination * \param sport pointer to a string containing the port source * \param dport pointer to a string containing the port destination * * \retval Packet pointer to the built in packet */ Packet *UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, char *src, char *dst, uint16_t sport, uint16_t dport) { struct in_addr in; Packet *p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return NULL; struct timeval tv; TimeGet(&tv); COPY_TIMESTAMP(&tv, &p->ts); p->src.family = AF_INET; p->dst.family = AF_INET; p->payload = payload; p->payload_len = payload_len; p->proto = ipproto; if (inet_pton(AF_INET, src, &in) != 1) goto error; p->src.addr_data32[0] = in.s_addr; p->sp = sport; if (inet_pton(AF_INET, dst, &in) != 1) goto error; p->dst.addr_data32[0] = in.s_addr; p->dp = dport; p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p); if (p->ip4h == NULL) goto error; p->ip4h->s_ip_src.s_addr = p->src.addr_data32[0]; p->ip4h->s_ip_dst.s_addr = p->dst.addr_data32[0]; p->ip4h->ip_proto = ipproto; p->ip4h->ip_verhl = sizeof(IPV4Hdr); p->proto = ipproto; int hdr_offset = sizeof(IPV4Hdr); switch (ipproto) { case IPPROTO_UDP: p->udph = (UDPHdr *)(GET_PKT_DATA(p) + sizeof(IPV4Hdr)); if (p->udph == NULL) goto error; p->udph->uh_sport = sport; p->udph->uh_dport = dport; hdr_offset += sizeof(UDPHdr); break; case IPPROTO_TCP: p->tcph = (TCPHdr *)(GET_PKT_DATA(p) + sizeof(IPV4Hdr)); if (p->tcph == NULL) goto error; p->tcph->th_sport = htons(sport); p->tcph->th_dport = htons(dport); hdr_offset += sizeof(TCPHdr); break; case IPPROTO_ICMP: p->icmpv4h = (ICMPV4Hdr *)(GET_PKT_DATA(p) + sizeof(IPV4Hdr)); if (p->icmpv4h == NULL) goto error; hdr_offset += sizeof(ICMPV4Hdr); break; default: break; /* TODO: Add more protocols */ } PacketCopyDataOffset(p, hdr_offset, payload, payload_len); SET_PKT_LEN(p, hdr_offset + payload_len); p->payload = GET_PKT_DATA(p)+hdr_offset; return p; error: SCFree(p); return NULL; }
void DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { uint16_t header_len = GRE_HDR_LEN; GRESreHdr *gsre = NULL; SCPerfCounterIncr(dtv->counter_gre, tv->sc_perf_pca); if(len < GRE_HDR_LEN) { ENGINE_SET_EVENT(p,GRE_PKT_TOO_SMALL); return; } p->greh = (GREHdr *)pkt; if(p->greh == NULL) return; SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh)); switch (GRE_GET_VERSION(p->greh)) { case GRE_VERSION_0: /* GRE version 0 doenst support the fields below RFC 1701 */ /** * \todo We need to make sure this does not allow bypassing * inspection. A server may just ignore these and * continue processing the packet, but we will not look * further into it. */ if (GRE_FLAG_ISSET_RECUR(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION0_RECUR); return; } if (GREV1_FLAG_ISSET_FLAGS(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION0_FLAGS); return; } /* Adjust header length based on content */ if (GRE_FLAG_ISSET_KY(p->greh)) header_len += GRE_KEY_LEN; if (GRE_FLAG_ISSET_SQ(p->greh)) header_len += GRE_SEQ_LEN; if (GRE_FLAG_ISSET_CHKSUM(p->greh) || GRE_FLAG_ISSET_ROUTE(p->greh)) header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN; if (header_len > len) { ENGINE_SET_EVENT(p,GRE_VERSION0_HDR_TOO_BIG); return; } if (GRE_FLAG_ISSET_ROUTE(p->greh)) { while (1) { if ((header_len + GRE_SRE_HDR_LEN) > len) { ENGINE_SET_EVENT(p, GRE_VERSION0_MALFORMED_SRE_HDR); return; } gsre = (GRESreHdr *)(pkt + header_len); header_len += GRE_SRE_HDR_LEN; if ((ntohs(gsre->af) == 0) && (gsre->sre_length == 0)) break; header_len += gsre->sre_length; if (header_len > len) { ENGINE_SET_EVENT(p, GRE_VERSION0_MALFORMED_SRE_HDR); return; } } } break; case GRE_VERSION_1: /* GRE version 1 doenst support the fields below RFC 1701 */ /** * \todo We need to make sure this does not allow bypassing * inspection. A server may just ignore these and * continue processing the packet, but we will not look * further into it. */ if (GRE_FLAG_ISSET_CHKSUM(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION1_CHKSUM); return; } if (GRE_FLAG_ISSET_ROUTE(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION1_ROUTE); return; } if (GRE_FLAG_ISSET_SSR(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION1_SSR); return; } if (GRE_FLAG_ISSET_RECUR(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION1_RECUR); return; } if (GREV1_FLAG_ISSET_FLAGS(p->greh)) { ENGINE_SET_EVENT(p,GRE_VERSION1_FLAGS); return; } if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) { ENGINE_SET_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL); return; } if (!(GRE_FLAG_ISSET_KY(p->greh))) { ENGINE_SET_EVENT(p,GRE_VERSION1_NO_KEY); return; } header_len += GRE_KEY_LEN; /* Adjust header length based on content */ if (GRE_FLAG_ISSET_SQ(p->greh)) header_len += GRE_SEQ_LEN; if (GREV1_FLAG_ISSET_ACK(p->greh)) header_len += GREV1_ACK_LEN; if (header_len > len) { ENGINE_SET_EVENT(p,GRE_VERSION1_HDR_TOO_BIG); return; } break; default: ENGINE_SET_EVENT(p,GRE_WRONG_VERSION); return; } switch (GRE_GET_PROTO(p->greh)) { case ETHERNET_TYPE_IP: { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt + header_len, len - header_len, IPPROTO_IP); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, IPPROTO_IP); PacketEnqueue(pq,tp); } } break; } case GRE_PROTO_PPP: { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt + header_len, len - header_len, PPP_OVER_GRE); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, PPP_OVER_GRE); PacketEnqueue(pq,tp); } } break; } case ETHERNET_TYPE_IPV6: { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt + header_len, len - header_len, IPPROTO_IPV6); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, IPPROTO_IPV6); PacketEnqueue(pq,tp); } } break; } case ETHERNET_TYPE_VLAN: { if (pq != NULL) { Packet *tp = PacketPseudoPktSetup(p, pkt + header_len, len - header_len, VLAN_OVER_GRE); if (tp != NULL) { DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp), pq, VLAN_OVER_GRE); PacketEnqueue(pq,tp); } } break; } default: return; } }
int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p) { AlertFastLogThread *aft = (AlertFastLogThread *)data; int i; char timebuf[64]; int decoder_event = 0; CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); char srcip[46], dstip[46]; if (PKT_IS_IPV4(p)) { PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); } else if (PKT_IS_IPV6(p)) { PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); } else { decoder_event = 1; } /* Buffer to store the generated alert strings. The buffer is * filled with alert strings until it doesn't have room to store * another full alert, only then is the buffer written. This is * more efficient for multiple alerts and only slightly slower for * single alerts. */ char alert_buffer[MAX_FASTLOG_BUFFER_SIZE]; for (i = 0; i < p->alerts.cnt; i++) { const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } char *action = ""; if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) { action = "[Drop] "; } else if (pa->action & ACTION_DROP) { action = "[wDrop] "; } char proto[16] = ""; if (likely(decoder_event == 0)) { if (SCProtoNameValid(IP_GET_IPPROTO(p)) == TRUE) { strlcpy(proto, known_proto[IP_GET_IPPROTO(p)], sizeof(proto)); } else { snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IP_GET_IPPROTO(p)); } } /* Create the alert string without locking. */ int size = 0; if (likely(decoder_event == 0)) { PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, "%s %s[**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %"PRIu32"]" " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio, proto, srcip, p->sp, dstip, p->dp); } else { PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, "%s %s[**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: " "%" PRIu32 "] [**] [Raw pkt: ", timebuf, action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio); PrintBufferRawLineHex(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32); if (p->pcap_cnt != 0) { PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, "] [pcap file packet: %"PRIu64"]\n", p->pcap_cnt); } else { PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, "]\n"); } } /* Write the alert to output file */ AlertFastLogOutputAlert(aft, alert_buffer, size); } return TM_ECODE_OK; }
/** * \test fragment decoding */ static int DecodeIPV6FragTest01 (void) { uint8_t raw_frag1[] = { 0x60, 0x0f, 0x1a, 0xcf, 0x05, 0xa8, 0x2c, 0x36, 0x20, 0x01, 0x04, 0x70, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x09, 0x80, 0x32, 0xb2, 0x00, 0x01, 0x2e, 0x41, 0x38, 0xff, 0xfe, 0xa7, 0xea, 0xeb, 0x06, 0x00, 0x00, 0x01, 0xdf, 0xf8, 0x11, 0xd7, 0x00, 0x50, 0xa6, 0x5c, 0xcc, 0xd7, 0x28, 0x9f, 0xc3, 0x34, 0xc6, 0x58, 0x80, 0x10, 0x20, 0x13, 0x18, 0x1f, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0xcd, 0xf9, 0x3a, 0x41, 0x00, 0x1a, 0x91, 0x8a, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x30, 0x32, 0x20, 0x44, 0x65, 0x63, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, 0x30, 0x38, 0x3a, 0x33, 0x32, 0x3a, 0x35, 0x37, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x0d, 0x0a, 0x43, 0x61, 0x63, 0x68, 0x65, 0x2d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x0d, 0x0a, 0x50, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x0d, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x3a, 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x31, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x31, 0x39, 0x37, 0x31, 0x20, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x35, 0x39, 0x39, 0x0d, 0x0a, 0x4b, 0x65, 0x65, 0x70, 0x2d, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x3a, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x35, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x3d, 0x39, 0x39, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4b, 0x65, 0x65, 0x70, 0x2d, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3b, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x61, 0x73, 0x63, 0x69, 0x69, 0x0d, 0x0a, 0x0d, 0x0a, 0x5f, 0x6a, 0x71, 0x6a, 0x73, 0x70, 0x28, 0x7b, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x22, 0x32, 0x30, 0x30, 0x31, 0x3a, 0x39, 0x38, 0x30, 0x3a, 0x33, 0x32, 0x62, 0x32, 0x3a, 0x31, 0x3a, 0x32, 0x65, 0x34, 0x31, 0x3a, 0x33, 0x38, 0x66, 0x66, 0x3a, 0x66, 0x65, 0x61, 0x37, 0x3a, 0x65, 0x61, 0x65, 0x62, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x69, 0x70, 0x76, 0x36, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x76, 0x69, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; uint8_t raw_frag2[] = { 0x60, 0x0f, 0x1a, 0xcf, 0x00, 0x1c, 0x2c, 0x36, 0x20, 0x01, 0x04, 0x70, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x09, 0x80, 0x32, 0xb2, 0x00, 0x01, 0x2e, 0x41, 0x38, 0xff, 0xfe, 0xa7, 0xea, 0xeb, 0x06, 0x00, 0x05, 0xa0, 0xdf, 0xf8, 0x11, 0xd7, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; Packet *p1 = SCMalloc(SIZE_OF_PACKET); if (p1 == NULL) return 0; Packet *p2 = SCMalloc(SIZE_OF_PACKET); if (p2 == NULL) { SCFree(p1); return 0; } ThreadVars tv; DecodeThreadVars dtv; int result = 0; PacketQueue pq; FlowInitConfig(FLOW_QUIET); memset(&pq, 0, sizeof(PacketQueue)); memset(&tv, 0, sizeof(ThreadVars)); memset(p1, 0, SIZE_OF_PACKET); p1->pkt = (uint8_t *)(p1 + 1); memset(p2, 0, SIZE_OF_PACKET); p2->pkt = (uint8_t *)(p2 + 1); memset(&dtv, 0, sizeof(DecodeThreadVars)); PACKET_INITIALIZE(p1); PACKET_INITIALIZE(p2); PacketCopyData(p1, raw_frag1, sizeof(raw_frag1)); PacketCopyData(p2, raw_frag2, sizeof(raw_frag2)); DecodeIPV6(&tv, &dtv, p1, GET_PKT_DATA(p1), GET_PKT_LEN(p1), &pq); if (!(IPV6_EXTHDR_ISSET_FH(p1))) { printf("ipv6 frag header not detected: "); goto end; } DecodeIPV6(&tv, &dtv, p2, GET_PKT_DATA(p2), GET_PKT_LEN(p2), &pq); if (!(IPV6_EXTHDR_ISSET_FH(p2))) { printf("ipv6 frag header not detected: "); goto end; } if (pq.len != 1) { printf("no reassembled packet: "); goto end; } result = 1; end: PACKET_CLEANUP(p1); PACKET_CLEANUP(p2); SCFree(p1); SCFree(p2); FlowShutdown(); return result; }
static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) { MemBuffer *payload = aft->payload_buffer; AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx; int i; if (p->alerts.cnt == 0) return TM_ECODE_OK; json_t *js = CreateJSONHeader((Packet *)p, 0, "alert"); if (unlikely(js == NULL)) return TM_ECODE_OK; for (i = 0; i < p->alerts.cnt; i++) { const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } MemBufferReset(aft->json_buffer); /* alert */ AlertJsonHeader(pa, js); if (json_output_ctx->flags & LOG_JSON_HTTP) { if (p->flow != NULL) { FLOWLOCK_RDLOCK(p->flow); uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_HTTP) AlertJsonHttp(p->flow, js); FLOWLOCK_UNLOCK(p->flow); } } if (json_output_ctx->flags & LOG_JSON_TLS) { if (p->flow != NULL) { FLOWLOCK_RDLOCK(p->flow); uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_TLS) AlertJsonTls(p->flow, js); FLOWLOCK_UNLOCK(p->flow); } } if (json_output_ctx->flags & LOG_JSON_SSH) { if (p->flow != NULL) { FLOWLOCK_RDLOCK(p->flow); uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_SSH) AlertJsonSsh(p->flow, js); FLOWLOCK_UNLOCK(p->flow); } } /* payload */ if (json_output_ctx->flags & (LOG_JSON_PAYLOAD | LOG_JSON_PAYLOAD_BASE64)) { int stream = (p->proto == IPPROTO_TCP) ? (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0) : 0; /* Is this a stream? If so, pack part of it into the payload field */ if (stream) { uint8_t flag; MemBufferReset(payload); if (!EngineModeIsIPS()) { if (p->flowflags & FLOW_PKT_TOSERVER) { flag = FLOW_PKT_TOCLIENT; } else { flag = FLOW_PKT_TOSERVER; } } else { if (p->flowflags & FLOW_PKT_TOSERVER) { flag = FLOW_PKT_TOSERVER; } else { flag = FLOW_PKT_TOCLIENT; } } StreamSegmentForEach((const Packet *)p, flag, AlertJsonDumpStreamSegmentCallback, (void *)payload); if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { unsigned long len = JSON_STREAM_BUFFER_SIZE * 2; uint8_t encoded[len]; Base64Encode((unsigned char *)payload, payload->offset, encoded, &len); json_object_set_new(js, "payload", json_string((char *)encoded)); } if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { uint8_t printable_buf[payload->offset + 1]; uint32_t offset = 0; PrintStringsToBuffer(printable_buf, &offset, sizeof(printable_buf), (unsigned char *)payload, payload->offset); json_object_set_new(js, "payload_printable", json_string((char *)printable_buf)); } } else { /* This is a single packet and not a stream */ if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { unsigned long len = p->payload_len * 2 + 1; uint8_t encoded[len]; Base64Encode(p->payload, p->payload_len, encoded, &len); json_object_set_new(js, "payload", json_string((char *)encoded)); } if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { uint8_t printable_buf[p->payload_len + 1]; uint32_t offset = 0; PrintStringsToBuffer(printable_buf, &offset, p->payload_len + 1, p->payload, p->payload_len); json_object_set_new(js, "payload_printable", json_string((char *)printable_buf)); } } json_object_set_new(js, "stream", json_integer(stream)); } /* base64-encoded full packet */ if (json_output_ctx->flags & LOG_JSON_PACKET) { unsigned long len = GET_PKT_LEN(p) * 2; uint8_t encoded_packet[len]; Base64Encode((unsigned char*) GET_PKT_DATA(p), GET_PKT_LEN(p), encoded_packet, &len); json_object_set_new(js, "packet", json_string((char *)encoded_packet)); } HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg; /* xff header */ if (!(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) { int have_xff_ip = 0; char buffer[XFF_MAXLEN]; FLOWLOCK_RDLOCK(p->flow); if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) { if (pa->flags & PACKET_ALERT_FLAG_TX) { have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN); } else { have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN); } } FLOWLOCK_UNLOCK(p->flow); if (have_xff_ip) { if (xff_cfg->flags & XFF_EXTRADATA) { json_object_set_new(js, "xff", json_string(buffer)); } else if (xff_cfg->flags & XFF_OVERWRITE) { if (p->flowflags & FLOW_PKT_TOCLIENT) { json_object_set(js, "dest_ip", json_string(buffer)); } else { json_object_set(js, "src_ip", json_string(buffer)); } } } } OutputJSONBuffer(js, aft->file_ctx, aft->json_buffer); json_object_del(js, "alert"); } json_object_clear(js); json_decref(js); return TM_ECODE_OK; }
static int AlertJsonDecoderEvent(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) { int i; char timebuf[64]; json_t *js; if (p->alerts.cnt == 0) return TM_ECODE_OK; CreateIsoTimeString(&p->ts, timebuf, sizeof(timebuf)); for (i = 0; i < p->alerts.cnt; i++) { MemBufferReset(aft->json_buffer); const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } char *action = "allowed"; if (pa->action & (ACTION_REJECT|ACTION_REJECT_DST|ACTION_REJECT_BOTH)) { action = "blocked"; } else if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) { action = "blocked"; } char buf[(32 * 3) + 1]; PrintRawLineHexBuf(buf, sizeof(buf), GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32); js = json_object(); if (js == NULL) return TM_ECODE_OK; json_t *ajs = json_object(); if (ajs == NULL) { json_decref(js); return TM_ECODE_OK; } /* time & tx */ json_object_set_new(js, "timestamp", json_string(timebuf)); /* tuple */ //json_object_set_new(js, "srcip", json_string(srcip)); //json_object_set_new(js, "sp", json_integer(p->sp)); //json_object_set_new(js, "dstip", json_string(dstip)); //json_object_set_new(js, "dp", json_integer(p->dp)); //json_object_set_new(js, "proto", json_integer(proto)); json_object_set_new(ajs, "action", json_string(action)); json_object_set_new(ajs, "gid", json_integer(pa->s->gid)); json_object_set_new(ajs, "signature_id", json_integer(pa->s->id)); json_object_set_new(ajs, "rev", json_integer(pa->s->rev)); json_object_set_new(ajs, "signature", json_string((pa->s->msg) ? pa->s->msg : "")); json_object_set_new(ajs, "category", json_string((pa->s->class_msg) ? pa->s->class_msg : "")); json_object_set_new(ajs, "severity", json_integer(pa->s->prio)); if (p->tenant_id > 0) json_object_set_new(ajs, "tenant_id", json_integer(p->tenant_id)); /* alert */ json_object_set_new(js, "alert", ajs); OutputJSONBuffer(js, aft->file_ctx, &aft->json_buffer); json_object_clear(js); json_decref(js); } return TM_ECODE_OK; }
static TmEcode AlertDebugLogger(ThreadVars *tv, const Packet *p, void *thread_data) { AlertDebugLogThread *aft = (AlertDebugLogThread *)thread_data; int i; char timebuf[64]; const char *pkt_src_str = NULL; if (p->alerts.cnt == 0) return TM_ECODE_OK; MemBufferReset(aft->buffer); CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); MemBufferWriteString(aft->buffer, "+================\n" "TIME: %s\n", timebuf); if (p->pcap_cnt > 0) { MemBufferWriteString(aft->buffer, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt); } pkt_src_str = PktSrcToString(p->pkt_src); MemBufferWriteString(aft->buffer, "PKT SRC: %s\n", pkt_src_str); char srcip[46], dstip[46]; if (PKT_IS_IPV4(p)) { PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); } else if (PKT_IS_IPV6(p)) { PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); } MemBufferWriteString(aft->buffer, "SRC IP: %s\n" "DST IP: %s\n" "PROTO: %" PRIu32 "\n", srcip, dstip, p->proto); if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) { MemBufferWriteString(aft->buffer, "SRC PORT: %" PRIu32 "\n" "DST PORT: %" PRIu32 "\n", p->sp, p->dp); if (PKT_IS_TCP(p)) { MemBufferWriteString(aft->buffer, "TCP SEQ: %"PRIu32"\n" "TCP ACK: %"PRIu32"\n", TCP_GET_SEQ(p), TCP_GET_ACK(p)); } } /* flow stuff */ MemBufferWriteString(aft->buffer, "FLOW: to_server: %s, " "to_client: %s\n", p->flowflags & FLOW_PKT_TOSERVER ? "TRUE" : "FALSE", p->flowflags & FLOW_PKT_TOCLIENT ? "TRUE" : "FALSE"); if (p->flow != NULL) { int applayer = 0; applayer = StreamTcpAppLayerIsDisabled(p->flow); CreateTimeString(&p->flow->startts, timebuf, sizeof(timebuf)); MemBufferWriteString(aft->buffer, "FLOW Start TS: %s\n", timebuf); MemBufferWriteString(aft->buffer, "FLOW PKTS TODST: %"PRIu32"\n" "FLOW PKTS TOSRC: %"PRIu32"\n" "FLOW Total Bytes: %"PRIu64"\n", p->flow->todstpktcnt, p->flow->tosrcpktcnt, p->flow->todstbytecnt + p->flow->tosrcbytecnt); MemBufferWriteString(aft->buffer, "FLOW IPONLY SET: TOSERVER: %s, TOCLIENT: %s\n" "FLOW ACTION: DROP: %s\n" "FLOW NOINSPECTION: PACKET: %s, PAYLOAD: %s, APP_LAYER: %s\n" "FLOW APP_LAYER: DETECTED: %s, PROTO %"PRIu16"\n", p->flow->flags & FLOW_TOSERVER_IPONLY_SET ? "TRUE" : "FALSE", p->flow->flags & FLOW_TOCLIENT_IPONLY_SET ? "TRUE" : "FALSE", p->flow->flags & FLOW_ACTION_DROP ? "TRUE" : "FALSE", p->flow->flags & FLOW_NOPACKET_INSPECTION ? "TRUE" : "FALSE", p->flow->flags & FLOW_NOPAYLOAD_INSPECTION ? "TRUE" : "FALSE", applayer ? "TRUE" : "FALSE", (p->flow->alproto != ALPROTO_UNKNOWN) ? "TRUE" : "FALSE", p->flow->alproto); AlertDebugLogFlowVars(aft, p); } AlertDebugLogPktVars(aft, p); /* any stuff */ /* Sig details? */ MemBufferWriteString(aft->buffer, "PACKET LEN: %" PRIu32 "\n" "PACKET:\n", GET_PKT_LEN(p)); PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, GET_PKT_DATA(p), GET_PKT_LEN(p)); MemBufferWriteString(aft->buffer, "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); for (i = 0; i < p->alerts.cnt; i++) { const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } MemBufferWriteString(aft->buffer, "ALERT MSG [%02d]: %s\n" "ALERT GID [%02d]: %" PRIu32 "\n" "ALERT SID [%02d]: %" PRIu32 "\n" "ALERT REV [%02d]: %" PRIu32 "\n" "ALERT CLASS [%02d]: %s\n" "ALERT PRIO [%02d]: %" PRIu32 "\n" "ALERT FOUND IN [%02d]: %s\n", i, pa->s->msg, i, pa->s->gid, i, pa->s->id, i, pa->s->rev, i, pa->s->class_msg ? pa->s->class_msg : "<none>", i, pa->s->prio, i, pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH ? "STREAM" : (pa->flags & PACKET_ALERT_FLAG_STATE_MATCH ? "STATE" : "PACKET")); if (pa->flags & PACKET_ALERT_FLAG_TX) { MemBufferWriteString(aft->buffer, "ALERT IN TX [%02d]: %"PRIu64"\n", i, pa->tx_id); } else { MemBufferWriteString(aft->buffer, "ALERT IN TX [%02d]: N/A\n", i); } if (p->payload_len > 0) { MemBufferWriteString(aft->buffer, "PAYLOAD LEN: %" PRIu32 "\n" "PAYLOAD:\n", p->payload_len); PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, p->payload, p->payload_len); } if ((pa->flags & PACKET_ALERT_FLAG_STATE_MATCH) || (pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH)) { /* This is an app layer or stream alert */ int ret; uint8_t flag; if (!(PKT_IS_TCP(p)) || p->flow == NULL || p->flow->protoctx == NULL) { return TM_ECODE_OK; } /* IDS mode reverse the data */ /** \todo improve the order selection policy */ if (p->flowflags & FLOW_PKT_TOSERVER) { flag = FLOW_PKT_TOCLIENT; } else { flag = FLOW_PKT_TOSERVER; } ret = StreamSegmentForEach((const Packet *)p, flag, AlertDebugPrintStreamSegmentCallback, (void *)aft); if (ret < 0) { return TM_ECODE_FAILED; } } } aft->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer), MEMBUFFER_OFFSET(aft->buffer), aft->file_ctx); return TM_ECODE_OK; }
TmEcode ReceiveIPFWLoop(ThreadVars *tv, void *data, void *slot) { SCEnter(); IPFWThreadVars *ptv = (IPFWThreadVars *)data; IPFWQueueVars *nq = NULL; uint8_t pkt[IP_MAXPACKET]; int pktlen=0; struct pollfd IPFWpoll; struct timeval IPFWts; Packet *p = NULL; uint16_t packet_q_len = 0; nq = IPFWGetQueue(ptv->ipfw_index); if (nq == NULL) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Can't get thread variable"); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("Thread '%s' will run on port %d (item %d)", tv->name, nq->port_num, ptv->ipfw_index); while (1) { if (suricata_ctl_flags & (SURICATA_STOP || SURICATA_KILL)) { SCReturnInt(TM_ECODE_OK); } IPFWpoll.fd = nq->fd; IPFWpoll.events = POLLRDNORM; /* Poll the socket for status */ if ( (poll(&IPFWpoll, 1, IPFW_SOCKET_POLL_MSEC)) > 0) { if (!(IPFWpoll.revents & (POLLRDNORM | POLLERR))) continue; } if ((pktlen = recvfrom(nq->fd, pkt, sizeof(pkt), 0, (struct sockaddr *)&nq->ipfw_sin, &nq->ipfw_sinlen)) == -1) { /* We received an error on socket read */ if (errno == EINTR || errno == EWOULDBLOCK) { /* Nothing for us to process */ continue; } else { SCLogWarning(SC_WARN_IPFW_RECV, "Read from IPFW divert socket failed: %s", strerror(errno)); SCReturnInt(TM_ECODE_FAILED); } } /* We have a packet to process */ memset (&IPFWts, 0, sizeof(struct timeval)); gettimeofday(&IPFWts, NULL); /* make sure we have at least one packet in the packet pool, to prevent * us from alloc'ing packets at line rate */ do { packet_q_len = PacketPoolSize(); if (unlikely(packet_q_len == 0)) { PacketPoolWait(); } } while (packet_q_len == 0); p = PacketGetFromQueueOrAlloc(); if (p == NULL) { SCReturnInt(TM_ECODE_FAILED); } PKT_SET_SRC(p, PKT_SRC_WIRE); SCLogDebug("Received Packet Len: %d", pktlen); p->ts.tv_sec = IPFWts.tv_sec; p->ts.tv_usec = IPFWts.tv_usec; ptv->pkts++; ptv->bytes += pktlen; p->datalink = ptv->datalink; p->ipfw_v.ipfw_index = ptv->ipfw_index; PacketCopyData(p, pkt, pktlen); SCLogDebug("Packet info: pkt_len: %" PRIu32 " (pkt %02x, pkt_data %02x)", GET_PKT_LEN(p), *pkt, GET_PKT_DATA(p)); if (TmThreadsSlotProcessPkt(tv, ((TmSlot *) slot)->slot_next, p) != TM_ECODE_OK) { TmqhOutputPacketpool(tv, p); SCReturnInt(TM_ECODE_FAILED); } SCPerfSyncCountersIfSignalled(tv, 0); } SCReturnInt(TM_ECODE_OK); }
/** * \brief match the specified luajit * * \param t thread local vars * \param det_ctx pattern matcher thread local data * \param p packet * \param s signature being inspected * \param m sigmatch that we will cast into DetectLuajitData * * \retval 0 no match * \retval 1 match */ static int DetectLuajitMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { SCEnter(); int ret = 0; DetectLuajitData *luajit = (DetectLuajitData *)m->ctx; if (luajit == NULL) SCReturnInt(0); DetectLuajitThreadData *tluajit = (DetectLuajitThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, luajit->thread_ctx_id); if (tluajit == NULL) SCReturnInt(0); if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len == 0) SCReturnInt(0); if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p) == 0) SCReturnInt(0); if (tluajit->alproto != ALPROTO_UNKNOWN) { if (p->flow == NULL) SCReturnInt(0); FLOWLOCK_RDLOCK(p->flow); int alproto = p->flow->alproto; FLOWLOCK_UNLOCK(p->flow); if (tluajit->alproto != alproto) SCReturnInt(0); } lua_getglobal(tluajit->luastate, "match"); lua_newtable(tluajit->luastate); /* stack at -1 */ if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len) { lua_pushliteral(tluajit->luastate, "payload"); /* stack at -2 */ lua_pushlstring (tluajit->luastate, (const char *)p->payload, (size_t)p->payload_len); /* stack at -3 */ lua_settable(tluajit->luastate, -3); } if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) { lua_pushliteral(tluajit->luastate, "packet"); /* stack at -2 */ lua_pushlstring (tluajit->luastate, (const char *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */ lua_settable(tluajit->luastate, -3); } if (tluajit->alproto == ALPROTO_HTTP) { FLOWLOCK_RDLOCK(p->flow); HtpState *htp_state = p->flow->alstate; if (htp_state != NULL && htp_state->connp != NULL && htp_state->connp->conn != NULL) { int idx = AppLayerTransactionGetInspectId(p->flow); if (idx != -1) { htp_tx_t *tx = NULL; int size = (int)list_size(htp_state->connp->conn->transactions); for ( ; idx < size; idx++) { tx = list_get(htp_state->connp->conn->transactions, idx); if (tx == NULL) continue; if ((tluajit->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL && bstr_len(tx->request_line) > 0) { lua_pushliteral(tluajit->luastate, "http.request_line"); /* stack at -2 */ lua_pushlstring (tluajit->luastate, (const char *)bstr_ptr(tx->request_line), bstr_len(tx->request_line)); lua_settable(tluajit->luastate, -3); } } } } FLOWLOCK_UNLOCK(p->flow); } int retval = lua_pcall(tluajit->luastate, 1, 1, 0); if (retval != 0) { SCLogInfo("failed to run script: %s", lua_tostring(tluajit->luastate, -1)); } /* process returns from script */ if (lua_gettop(tluajit->luastate) > 0) { /* script returns a number (return 1 or return 0) */ if (lua_type(tluajit->luastate, 1) == LUA_TNUMBER) { double script_ret = lua_tonumber(tluajit->luastate, 1); SCLogDebug("script_ret %f", script_ret); lua_pop(tluajit->luastate, 1); if (script_ret == 1.0) ret = 1; /* script returns a table */ } else if (lua_type(tluajit->luastate, 1) == LUA_TTABLE) { lua_pushnil(tluajit->luastate); const char *k, *v; while (lua_next(tluajit->luastate, -2)) { v = lua_tostring(tluajit->luastate, -1); lua_pop(tluajit->luastate, 1); k = lua_tostring(tluajit->luastate, -1); if (!k || !v) continue; SCLogDebug("k='%s', v='%s'", k, v); if (strcmp(k, "retval") == 0) { if (atoi(v) == 1) ret = 1; } else { /* set flow var? */ } } /* pop the table */ lua_pop(tluajit->luastate, 1); } } if (luajit->negated) { if (ret == 1) ret = 0; else ret = 1; } SCReturnInt(ret); }
/** * \brief This function sets the Verdict and processes the packet * * * \param tv pointer to ThreadVars * \param p pointer to the Packet */ TmEcode IPFWSetVerdict(ThreadVars *tv, IPFWThreadVars *ptv, Packet *p) { uint32_t verdict; struct pollfd IPFWpoll; IPFWQueueVars *nq = NULL; SCEnter(); if (p == NULL) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Packet is NULL"); SCReturnInt(TM_ECODE_FAILED); } nq = IPFWGetQueue(p->ipfw_v.ipfw_index); if (nq == NULL) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "No thread found"); SCReturnInt(TM_ECODE_FAILED); } IPFWpoll.fd = nq->fd; IPFWpoll.events = POLLWRNORM; if (p->action & ACTION_DROP) { verdict = IPFW_DROP; } else { verdict = IPFW_ACCEPT; } if (verdict == IPFW_ACCEPT) { SCLogDebug("IPFW Verdict is to Accept"); ptv->accepted++; /* For divert sockets, accepting means writing the * packet back to the socket for ipfw to pick up */ SCLogDebug("IPFWSetVerdict writing to socket %d, %p, %u", nq->fd, GET_PKT_DATA(p),GET_PKT_LEN(p)); #if 0 while ((poll(&IPFWpoll,1,IPFW_SOCKET_POLL_MSEC)) < 1) { /* Did we receive a signal to shutdown */ if (TmThreadsCheckFlag(tv, THV_KILL) || TmThreadsCheckFlag(tv, THV_PAUSE)) { SCLogInfo("Received ThreadShutdown: IPFW divert socket writing interrupted"); SCReturnInt(TM_ECODE_OK); } } #endif IPFWMutexLock(nq); if (sendto(nq->fd, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,(struct sockaddr *)&nq->ipfw_sin, nq->ipfw_sinlen) == -1) { int r = errno; switch (r) { default: SCLogWarning(SC_WARN_IPFW_XMIT,"Write to ipfw divert socket failed: %s",strerror(r)); IPFWMutexUnlock(nq); SCReturnInt(TM_ECODE_FAILED); case EHOSTDOWN: case ENETDOWN: break; } } IPFWMutexUnlock(nq); SCLogDebug("Sent Packet back into IPFW Len: %d",GET_PKT_LEN(p)); } /* end IPFW_ACCEPT */ if (verdict == IPFW_DROP) { SCLogDebug("IPFW SetVerdict is to DROP"); ptv->dropped++; /** \todo For divert sockets, dropping means not writing the packet back to the socket. * Need to see if there is some better way to free the packet from the queue */ } /* end IPFW_DROP */ SCReturnInt(TM_ECODE_OK); }
/** * \test Test packet Matches * \param raw_eth_pkt pointer to the ethernet packet * \param pktsize size of the packet * \param sig pointer to the signature to test * \param sid sid number of the signature * \retval return 1 if match * \retval return 0 if not */ int DetectReplaceLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize, char *sig, uint32_t sid, uint8_t *pp, uint16_t *len) { int result = 0; Packet *p = NULL; p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return 0; DecodeThreadVars dtv; ThreadVars th_v; DetectEngineThreadCtx *det_ctx = NULL; if (pp == NULL) { SCLogDebug("replace: looks like a second run"); } PacketCopyData(p, raw_eth_pkt, pktsize); memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&th_v, 0, sizeof(th_v)); FlowInitConfig(FLOW_QUIET); DecodeEthernet(&th_v, &dtv, p, GET_PKT_DATA(p), pktsize, NULL); DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; } de_ctx->flags |= DE_QUIET; de_ctx->sig_list = SigInit(de_ctx, sig); if (de_ctx->sig_list == NULL) { goto end; } de_ctx->sig_list->next = NULL; if (de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->type == DETECT_CONTENT) { DetectContentData *co = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; if (co->flags & DETECT_CONTENT_RELATIVE_NEXT) { printf("relative next flag set on final match which is content: "); goto end; } } SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); SigMatchSignatures(&th_v, de_ctx, det_ctx, p); if (PacketAlertCheck(p, sid) != 1) { SCLogDebug("replace: no alert on sig %d", sid); goto end; } if (pp) { memcpy(pp, GET_PKT_DATA(p), GET_PKT_LEN(p)); *len = pktsize; SCLogDebug("replace: copying %d on %p", *len, pp); } result = 1; end: if (de_ctx != NULL) { SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); if (det_ctx != NULL) DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineCtxFree(de_ctx); } FlowShutdown(); SCFree(p); return result; }
/** * \brief Function to fill unified2 packet format into the file. If the alert * was generated based on a stream chunk we call the stream function * to generate the record. * * Barnyard2 doesn't like DLT_RAW + IPv6, so if we don't have an ethernet * header, we create a fake one. * * No need to lock here, since it's already locked. * * \param aun thread local data * \param p Packet * \param stream pointer to stream chunk * \param event_id unique event id * \param stream state/stream match, try logging stream segments * * \retval 0 on succces * \retval -1 on failure */ int Unified2PacketTypeAlert (Unified2AlertThread *aun, Packet *p, uint32_t event_id, int stream) { int ret = 0; /* try stream logging first */ if (stream) { SCLogDebug("logging the state"); uint8_t flag; if (p->flowflags & FLOW_PKT_TOSERVER) { flag = FLOW_PKT_TOCLIENT; } else { flag = FLOW_PKT_TOSERVER; } /* make event id available to callback */ aun->event_id = event_id; /* run callback for all segments in the stream */ ret = StreamSegmentForEach(p, flag, Unified2PrintStreamSegmentCallback, (void *)aun); } /* or no segment could been logged or no segment have been logged */ if (ret == 0) { SCLogDebug("no stream, no state: falling back to payload logging"); Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data); Unified2Packet *phdr = (Unified2Packet *)(hdr + 1); int len = (sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE); int datalink = p->datalink; #ifdef HAVE_OLD_BARNYARD2 int ethh_offset = 0; EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) }; #endif memset(hdr, 0, sizeof(Unified2AlertFileHeader)); memset(phdr, 0, sizeof(Unified2Packet)); hdr->type = htonl(UNIFIED2_PACKET_TYPE); aun->hdr = hdr; phdr->sensor_id = htonl(sensor_id); phdr->linktype = htonl(datalink); phdr->event_id = event_id; phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec); phdr->packet_microsecond = htonl(p->ts.tv_usec); aun->phdr = phdr; /* we need to reset offset and length which could * have been modified by the segment logging */ aun->offset = len; len += GET_PKT_LEN(p); aun->length = len; /* Unified 2 packet header is the one of the packet. */ phdr->linktype = htonl(p->datalink); #ifdef HAVE_OLD_BARNYARD2 /* Fake datalink to avoid bug with old barnyard2 */ if (PKT_IS_IPV6(p) && (!p->ethh)) { /* Fake this */ ethh_offset = 14; datalink = DLT_EN10MB; phdr->linktype = htonl(datalink); aun->length += ethh_offset; if (aun->length > aun->datalen) { SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d", len, aun->datalen - aun->offset); return -1; } ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6); memcpy(aun->data + aun->offset, ðhdr, 14); aun->offset += ethh_offset; } #endif if (len > aun->datalen) { SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d", len, aun->datalen - aun->offset); return -1; } hdr->length = htonl(UNIFIED2_PACKET_SIZE + GET_PKT_LEN(p)); phdr->packet_length = htonl(GET_PKT_LEN(p)); memcpy(aun->data + aun->offset, GET_PKT_DATA(p), GET_PKT_LEN(p)); ret = Unified2Write(aun); } if (ret < 1) { return -1; } return 1; }