/** * \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 (PKT_IS_PSEUDOPKT(p)) return TM_ECODE_OK; DecodeUpdatePacketCounters(tv, dtv, p); 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; }
/** * \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; 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)); } return 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(); /* 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); } 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 */ DecodeUpdatePacketCounters(tv, dtv, 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); }
/** * \brief Add IPv4 header data, to be stored in the Additional Data * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765). * * \return 0 if ok */ static int PacketToDataV4(Packet *p, PacketAlert *pa, idmef_alert_t *alert) { SCEnter(); AddIntData(alert, "ip_ver", IPV4_GET_RAW_VER(p->ip4h)); AddIntData(alert, "ip_hlen", IPV4_GET_RAW_HLEN(p->ip4h)); AddIntData(alert, "ip_tos", IPV4_GET_RAW_IPTOS(p->ip4h)); AddIntData(alert, "ip_len", ntohs(IPV4_GET_RAW_IPLEN(p->ip4h))); AddIntData(alert, "ip_id", ntohs(IPV4_GET_RAW_IPID(p->ip4h))); AddIntData(alert, "ip_off", ntohs(IPV4_GET_RAW_IPOFFSET(p->ip4h))); AddIntData(alert, "ip_ttl", IPV4_GET_RAW_IPTTL(p->ip4h)); AddIntData(alert, "ip_proto", IPV4_GET_RAW_IPPROTO(p->ip4h)); AddIntData(alert, "ip_sum", ntohs(p->ip4h->ip_csum)); SCReturnInt(0); }
/** * \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; }
/** * Note, this is the IP header, plus a bit of the original packet, not the whole thing! */ int DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len ) { /** Check the sizes, the header must fit at least */ if (len < IPV4_HEADER_LEN) { SCLogDebug("DecodePartialIPV4: ICMPV4_IPV4_TRUNC_PKT"); ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_TRUNC_PKT); return -1; } IPV4Hdr *icmp4_ip4h = (IPV4Hdr*)partial_packet; /** Check the embedded version */ if (IPV4_GET_RAW_VER(icmp4_ip4h) != 4) { /** Check the embedded version */ SCLogDebug("DecodePartialIPV4: ICMPv4 contains Unknown IPV4 version " "ICMPV4_IPV4_UNKNOWN_VER"); ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_UNKNOWN_VER); return -1; } /** We need to fill icmpv4vars */ p->icmpv4vars.emb_ipv4h = icmp4_ip4h; /** Get the IP address from the contained packet */ p->icmpv4vars.emb_ip4_src = IPV4_GET_RAW_IPSRC(icmp4_ip4h); p->icmpv4vars.emb_ip4_dst = IPV4_GET_RAW_IPDST(icmp4_ip4h); p->icmpv4vars.emb_ip4_hlen=IPV4_GET_RAW_HLEN(icmp4_ip4h) << 2; switch (IPV4_GET_RAW_IPPROTO(icmp4_ip4h)) { case IPPROTO_TCP: if (len >= IPV4_HEADER_LEN + TCP_HEADER_LEN ) { p->icmpv4vars.emb_tcph = (TCPHdr*)(partial_packet + IPV4_HEADER_LEN); p->icmpv4vars.emb_sport = ntohs(p->icmpv4vars.emb_tcph->th_sport); p->icmpv4vars.emb_dport = ntohs(p->icmpv4vars.emb_tcph->th_dport); p->icmpv4vars.emb_ip4_proto = IPPROTO_TCP; SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP header sport: " "%"PRIu8" dport %"PRIu8"", p->icmpv4vars.emb_sport, p->icmpv4vars.emb_dport); } else if (len >= IPV4_HEADER_LEN + 4) { /* only access th_sport and th_dport */ TCPHdr *emb_tcph = (TCPHdr*)(partial_packet + IPV4_HEADER_LEN); p->icmpv4vars.emb_tcph = NULL; p->icmpv4vars.emb_sport = ntohs(emb_tcph->th_sport); p->icmpv4vars.emb_dport = ntohs(emb_tcph->th_dport); p->icmpv4vars.emb_ip4_proto = IPPROTO_TCP; SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP partial header sport: " "%"PRIu8" dport %"PRIu8"", p->icmpv4vars.emb_sport, p->icmpv4vars.emb_dport); } else { SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->TCP " "header Didn't fit in the packet!"); p->icmpv4vars.emb_sport = 0; p->icmpv4vars.emb_dport = 0; } break; case IPPROTO_UDP: if (len >= IPV4_HEADER_LEN + UDP_HEADER_LEN ) { p->icmpv4vars.emb_udph = (UDPHdr*)(partial_packet + IPV4_HEADER_LEN); p->icmpv4vars.emb_sport = ntohs(p->icmpv4vars.emb_udph->uh_sport); p->icmpv4vars.emb_dport = ntohs(p->icmpv4vars.emb_udph->uh_dport); p->icmpv4vars.emb_ip4_proto = IPPROTO_UDP; SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->UDP header sport: " "%"PRIu8" dport %"PRIu8"", p->icmpv4vars.emb_sport, p->icmpv4vars.emb_dport); } else { SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->UDP " "header Didn't fit in the packet!"); p->icmpv4vars.emb_sport = 0; p->icmpv4vars.emb_dport = 0; } break; case IPPROTO_ICMP: if (len >= IPV4_HEADER_LEN + ICMPV4_HEADER_LEN ) { p->icmpv4vars.emb_icmpv4h = (ICMPV4Hdr*)(partial_packet + IPV4_HEADER_LEN); p->icmpv4vars.emb_sport = 0; p->icmpv4vars.emb_dport = 0; p->icmpv4vars.emb_ip4_proto = IPPROTO_ICMP; SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header"); } break; } /* debug print */ #ifdef DEBUG char s[16], d[16]; PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s)); PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d)); SCLogDebug("ICMPv4 embedding IPV4 %s->%s - PROTO: %" PRIu32 " ID: %" PRIu32 "", s,d, IPV4_GET_RAW_IPPROTO(icmp4_ip4h), IPV4_GET_RAW_IPID(icmp4_ip4h)); #endif return 0; }
/** * \brief Main decoding function for PPPOE Session packets */ int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { SCPerfCounterIncr(dtv->counter_pppoe, tv->sc_perf_pca); if (len < PPPOE_SESSION_HEADER_LEN) { ENGINE_SET_INVALID_EVENT(p, PPPOE_PKT_TOO_SMALL); return TM_ECODE_FAILED; } p->pppoesh = (PPPOESessionHdr *)pkt; if (p->pppoesh == NULL) return TM_ECODE_FAILED; SCLogDebug("PPPOE VERSION %" PRIu32 " TYPE %" PRIu32 " CODE %" PRIu32 " SESSIONID %" PRIu32 " LENGTH %" PRIu32 "", PPPOE_SESSION_GET_VERSION(p->pppoesh), PPPOE_SESSION_GET_TYPE(p->pppoesh), p->pppoesh->pppoe_code, ntohs(p->pppoesh->session_id), ntohs(p->pppoesh->pppoe_length)); /* can't use DecodePPP() here because we only get a single 2-byte word to indicate protocol instead of the full PPP header */ if (ntohs(p->pppoesh->pppoe_length) > 0) { /* decode contained PPP packet */ switch (ntohs(p->pppoesh->protocol)) { case PPP_VJ_COMP: case PPP_IPX: case PPP_OSI: case PPP_NS: case PPP_DECNET: case PPP_APPLE: case PPP_BRPDU: case PPP_STII: case PPP_VINES: case PPP_HELLO: case PPP_LUXCOM: case PPP_SNS: case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: case PPP_IPCP: case PPP_OSICP: case PPP_NSCP: case PPP_DECNETCP: case PPP_APPLECP: case PPP_IPXCP: case PPP_STIICP: case PPP_VINESCP: case PPP_IPV6CP: case PPP_MPLSCP: case PPP_LCP: case PPP_PAP: case PPP_LQM: case PPP_CHAP: ENGINE_SET_EVENT(p,PPP_UNSUP_PROTO); break; case PPP_VJ_UCOMP: if(len < (PPPOE_SESSION_HEADER_LEN + IPV4_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, PPPVJU_PKT_TOO_SMALL); return TM_ECODE_OK; } if(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPPOE_SESSION_HEADER_LEN)) == 4) { DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); } break; case PPP_IP: if(len < (PPPOE_SESSION_HEADER_LEN + IPV4_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, PPPIPV4_PKT_TOO_SMALL); return TM_ECODE_OK; } DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); break; /* PPP IPv6 was not tested */ case PPP_IPV6: if(len < (PPPOE_SESSION_HEADER_LEN + IPV6_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, PPPIPV6_PKT_TOO_SMALL); return TM_ECODE_OK; } DecodeIPV6(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); break; default: SCLogDebug("unknown PPP protocol: %" PRIx32 "",ntohs(p->ppph->protocol)); ENGINE_SET_INVALID_EVENT(p, PPP_WRONG_TYPE); return TM_ECODE_OK; } } return TM_ECODE_OK; }
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_ppp); if (unlikely(len < PPP_HEADER_LEN)) { ENGINE_SET_INVALID_EVENT(p, PPP_PKT_TOO_SMALL); return TM_ECODE_FAILED; } p->ppph = (PPPHdr *)pkt; if (unlikely(p->ppph == NULL)) return TM_ECODE_FAILED; SCLogDebug("p %p pkt %p PPP protocol %04x Len: %" PRId32 "", p, pkt, ntohs(p->ppph->protocol), len); switch (ntohs(p->ppph->protocol)) { case PPP_VJ_UCOMP: if (unlikely(len < (PPP_HEADER_LEN + IPV4_HEADER_LEN))) { ENGINE_SET_INVALID_EVENT(p,PPPVJU_PKT_TOO_SMALL); p->ppph = NULL; return TM_ECODE_FAILED; } if (likely(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPP_HEADER_LEN)) == 4)) { return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); } else return TM_ECODE_FAILED; break; case PPP_IP: if (unlikely(len < (PPP_HEADER_LEN + IPV4_HEADER_LEN))) { ENGINE_SET_INVALID_EVENT(p,PPPIPV4_PKT_TOO_SMALL); p->ppph = NULL; return TM_ECODE_FAILED; } return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); /* PPP IPv6 was not tested */ case PPP_IPV6: if (unlikely(len < (PPP_HEADER_LEN + IPV6_HEADER_LEN))) { ENGINE_SET_INVALID_EVENT(p,PPPIPV6_PKT_TOO_SMALL); p->ppph = NULL; return TM_ECODE_FAILED; } return DecodeIPV6(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); case PPP_VJ_COMP: case PPP_IPX: case PPP_OSI: case PPP_NS: case PPP_DECNET: case PPP_APPLE: case PPP_BRPDU: case PPP_STII: case PPP_VINES: case PPP_HELLO: case PPP_LUXCOM: case PPP_SNS: case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: case PPP_IPCP: case PPP_OSICP: case PPP_NSCP: case PPP_DECNETCP: case PPP_APPLECP: case PPP_IPXCP: case PPP_STIICP: case PPP_VINESCP: case PPP_IPV6CP: case PPP_MPLSCP: case PPP_LCP: case PPP_PAP: case PPP_LQM: case PPP_CHAP: ENGINE_SET_EVENT(p,PPP_UNSUP_PROTO); return TM_ECODE_OK; default: SCLogDebug("unknown PPP protocol: %" PRIx32 "",ntohs(p->ppph->protocol)); ENGINE_SET_INVALID_EVENT(p, PPP_WRONG_TYPE); return TM_ECODE_OK; } }