/** * \brief Update stream with SACK records from a TCP packet. * * \param stream The stream to update. * \param p packet to get the SACK records from * * \retval -1 error * \retval 0 ok */ int StreamTcpSackUpdatePacket(TcpStream *stream, Packet *p) { int records = TCP_GET_SACK_CNT(p); int record = 0; TCPOptSackRecord *sack_rec = (TCPOptSackRecord *)(TCP_GET_SACK_PTR(p)); for (record = 0; record < records; record++) { SCLogDebug("%p last_ack %u, left edge %u, right edge %u", sack_rec, stream->last_ack, ntohl(sack_rec->le), ntohl(sack_rec->re)); if (SEQ_LEQ(ntohl(sack_rec->re), stream->last_ack)) { SCLogDebug("record before last_ack"); goto next; } /** \todo need a metric to a check for a right edge limit */ /* if (SEQ_GT(ntohl(sack_rec->re), stream->next_seq)) { SCLogDebug("record beyond next_seq %u", stream->next_seq); goto next; } */ if (SEQ_GEQ(ntohl(sack_rec->le), ntohl(sack_rec->re))) { SCLogDebug("invalid record: le >= re"); goto next; } if (StreamTcpSackInsertRange(stream, ntohl(sack_rec->le), ntohl(sack_rec->re)) == -1) { SCReturnInt(-1); } next: sack_rec++; } #ifdef DEBUG StreamTcpSackPrintList(stream); #endif SCReturnInt(0); }
static int TCPGetSackTest01(void) { int retval = 0; static uint8_t raw_tcp[] = { 0x00, 0x50, 0x06, 0xa6, 0xfa, 0x87, 0x0b, 0xf5, 0xf1, 0x59, 0x02, 0xe0, 0xa0, 0x10, 0x3e, 0xbc, 0x1d, 0xe7, 0x00, 0x00, 0x01, 0x01, 0x05, 0x12, 0xf1, 0x59, 0x13, 0xfc, 0xf1, 0x59, 0x1f, 0x64, 0xf1, 0x59, 0x08, 0x94, 0xf1, 0x59, 0x0e, 0x48 }; static uint8_t raw_tcp_sack[] = { 0xf1, 0x59, 0x13, 0xfc, 0xf1, 0x59, 0x1f, 0x64, 0xf1, 0x59, 0x08, 0x94, 0xf1, 0x59, 0x0e, 0x48 }; Packet *p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return 0; IPV4Hdr ip4h; ThreadVars tv; DecodeThreadVars dtv; memset(&tv, 0, sizeof(ThreadVars)); memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&ip4h, 0, sizeof(IPV4Hdr)); p->src.family = AF_INET; p->dst.family = AF_INET; p->ip4h = &ip4h; FlowInitConfig(FLOW_QUIET); DecodeTCP(&tv, &dtv, p, raw_tcp, sizeof(raw_tcp), NULL); if (p->tcph == NULL) { printf("tcp packet decode failed: "); goto end; } if (!TCP_HAS_SACK(p)) { printf("tcp packet sack not decoded: "); goto end; } int sack = TCP_GET_SACK_CNT(p); if (sack != 2) { printf("expected 2 sack records, got %u: ", TCP_GET_SACK_CNT(p)); goto end; } uint8_t *sackptr = TCP_GET_SACK_PTR(p); if (sackptr == NULL) { printf("no sack data: "); goto end; } if (memcmp(sackptr, raw_tcp_sack, 16) != 0) { printf("malformed sack data: "); goto end; } retval = 1; end: PACKET_RECYCLE(p); FlowShutdown(); SCFree(p); return retval; }
/** * \brief Convert IP packet to an IDMEF alert (RFC 4765). * This function stores the alert SID (description and reference), * the payload of the packet, and pre-processed data. * * \return 0 if ok */ static int PacketToData(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert, AlertPreludeCtx *ctx) { SCEnter(); if (unlikely(p == NULL)) SCReturnInt(0); AddIntData(alert, "snort_rule_sid", pa->s->id); AddIntData(alert, "snort_rule_rev", pa->s->rev); if (ctx->log_packet_header) { if ( PKT_IS_IPV4(p) ) PacketToDataV4(p, pa, alert); else if ( PKT_IS_IPV6(p) ) PacketToDataV6(p, pa, alert); if ( PKT_IS_TCP(p) ) { AddIntData(alert, "tcp_seq", TCP_GET_SEQ(p)); AddIntData(alert, "tcp_ack", TCP_GET_ACK(p)); AddIntData(alert, "tcp_off", TCP_GET_OFFSET(p)); AddIntData(alert, "tcp_res", TCP_GET_X2(p)); AddIntData(alert, "tcp_flags", TCP_GET_FLAGS(p)); AddIntData(alert, "tcp_win", TCP_GET_WINDOW(p)); AddIntData(alert, "tcp_sum", TCP_GET_SUM(p)); AddIntData(alert, "tcp_urp", TCP_GET_URG_POINTER(p)); if (p->tcpvars.ts_val != 0) { AddIntData(alert, "tcp_tsval", TCP_GET_TSVAL(p)); } if (p->tcpvars.ts_ecr != 0) { AddIntData(alert, "tcp_tsecr", TCP_GET_TSECR(p)); } if (p->tcph != NULL) { AddIntData(alert, "tcp_wscale", TCP_GET_WSCALE(p)); } if (TCP_HAS_SACKOK(p)) { AddIntData(alert, "tcp_sackok", TCP_GET_SACKOK(p)); } if (TCP_HAS_SACK(p)) { AddIntData(alert, "tcp_sack_cnt", TCP_GET_SACK_CNT(p)); } AddIntData(alert, "tcp_hlen", TCP_GET_HLEN(p)); } else if ( PKT_IS_UDP(p) ) { AddIntData(alert, "udp_len", UDP_GET_LEN(p)); AddIntData(alert, "udp_sum", UDP_GET_SUM(p)); } else if ( PKT_IS_ICMPV4(p) ) { AddIntData(alert, "icmp_type", ICMPV4_GET_TYPE(p)); AddIntData(alert, "icmp_code", ICMPV4_GET_CODE(p)); AddIntData(alert, "icmp_sum", ICMPV4_GET_RAW_CSUM(p)); } else if ( PKT_IS_ICMPV6(p) ) { AddIntData(alert, "icmp_type", ICMPV6_GET_TYPE(p)); AddIntData(alert, "icmp_code", ICMPV6_GET_CODE(p)); AddIntData(alert, "icmp_csum", ICMPV6_GET_RAW_CSUM(p)); } } if (ctx->log_packet_content) AddByteData(alert, "payload", p->payload, p->payload_len); SCReturnInt(0); }