suricata
stream-tcp-inline.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Functions for the "inline mode" of the stream engine.
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 #include "stream-tcp-private.h"
29 #include "stream-tcp-inline.h"
30 
31 #include "util-memcmp.h"
32 #include "util-print.h"
33 
34 #include "util-validate.h"
35 #include "util-unittest.h"
36 #include "util-unittest-helper.h"
37 
38 /**
39  * \brief Compare the shared data portion of two segments
40  *
41  * If no data is shared, 0 will be returned.
42  *
43  * \param seg1 first segment
44  * \param seg2 second segment
45  *
46  * \retval 0 shared data is the same (or no data is shared)
47  * \retval 1 shared data is different
48  */
50  const Packet *p, const TcpSegment *seg)
51 {
52  SCEnter();
53 
54  if (p == NULL || seg == NULL) {
55  SCReturnInt(0);
56  }
57 
58  DEBUG_VALIDATE_BUG_ON(SEQ_LEQ(seg->seq + TCP_SEG_LEN(seg), stream->base_seq));
59 
60  const uint8_t *seg_data;
61  uint32_t seg_datalen;
62  StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
63  if (seg_data == NULL || seg_datalen == 0)
64  SCReturnInt(0);
65 
66  const TCPHdr *tcph = PacketGetTCP(p);
67  const uint32_t pkt_seq = TCP_GET_RAW_SEQ(tcph);
68 
69  if (SEQ_EQ(pkt_seq, seg->seq) && p->payload_len == seg_datalen) {
70  int r = SCMemcmp(p->payload, seg_data, seg_datalen);
71  SCReturnInt(r);
72  } else if (SEQ_GT(pkt_seq, (seg->seq + seg_datalen))) {
73  SCReturnInt(0);
74  } else if (SEQ_GT(seg->seq, (pkt_seq + p->payload_len))) {
75  SCReturnInt(0);
76  } else {
77  SCLogDebug("p %u (%u), seg2 %u (%u)", pkt_seq,
78  p->payload_len, seg->seq, seg_datalen);
79 
80  uint32_t seg_seq = seg->seq;
81  if (SEQ_LT(seg_seq, stream->base_seq)) {
82  seg_seq = stream->base_seq;
83  }
84  uint32_t pkt_end = pkt_seq + p->payload_len;
85  uint32_t seg_end = seg_seq + seg_datalen;
86  SCLogDebug("pkt_end %u, seg_end %u", pkt_end, seg_end);
87 
88  /* get the minimal seg*_end */
89  uint32_t end = SEQ_MIN(seg_end, pkt_end);
90  /* and the max seq */
91  uint32_t seq = SEQ_MAX(pkt_seq, seg_seq);
92  seq = SEQ_MAX(seq, stream->base_seq);
93  SCLogDebug("seq %u, end %u", seq, end);
94 
95  uint32_t pkt_off = seq - pkt_seq;
96  uint32_t seg_off = seq - seg_seq;
97  SCLogDebug("pkt_off %u, seg_off %u", pkt_off, seg_off);
98 
99  uint32_t range = end - seq;
100  SCLogDebug("range %u", range);
101  BUG_ON(range > 65536);
102 
103  if (range) {
104  int r = SCMemcmp(p->payload + pkt_off, seg_data + seg_off, range);
105  SCReturnInt(r);
106  }
107  SCReturnInt(0);
108  }
109 }
110 
111 /**
112  * \brief Replace (part of) the payload portion of a packet by the data
113  * in a TCP segment
114  *
115  * \param p Packet
116  * \param seg TCP segment
117  *
118  * \todo What about reassembled fragments?
119  * \todo What about unwrapped tunnel packets?
120  */
122  Packet *p, const TcpSegment *seg)
123 {
124  SCEnter();
125 
126  const TCPHdr *tcph = PacketGetTCP(p);
127  const uint32_t pseq = TCP_GET_RAW_SEQ(tcph);
128  uint32_t tseq = seg->seq;
129 
130  /* check if segment is within the packet */
131  if (tseq + TCP_SEG_LEN(seg) < pseq) {
132  SCReturn;
133  } else if (pseq + p->payload_len < tseq) {
134  SCReturn;
135  }
136 
137  const uint8_t *seg_data;
138  uint32_t seg_datalen;
139  StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
140 
141  uint32_t pend = pseq + p->payload_len;
142  uint32_t tend = tseq + seg_datalen;
143  SCLogDebug("pend %u, tend %u", pend, tend);
144 
145  /* get the minimal seg*_end */
146  uint32_t end = (SEQ_GT(pend, tend)) ? tend : pend;
147  /* and the max seq */
148  uint32_t seq = (SEQ_LT(pseq, tseq)) ? tseq : pseq;
149  SCLogDebug("seq %u, end %u", seq, end);
150 
151  uint32_t poff = seq - pseq;
152  uint32_t toff = seq - tseq;
153  SCLogDebug("poff %u, toff %u", poff, toff);
154 
155  uint32_t range = end - seq;
156  SCLogDebug("range %u", range);
157  BUG_ON(range > 65536);
158 
159  if (range) {
160  /* update the packets payload. As payload is a ptr to either
161  * p->pkt or p->ext_pkt that is updated as well */
162  memcpy(p->payload+poff, seg_data+toff, range);
163 
164  /* flag as modified so we can reinject / replace after
165  * recalculating the checksum */
167  }
168 }
169 
170 #ifdef UNITTESTS
171 #include "tests/stream-tcp-inline.c"
172 #endif
TCP_GET_RAW_SEQ
#define TCP_GET_RAW_SEQ(tcph)
Definition: decode-tcp.h:80
TcpStream_
Definition: stream-tcp-private.h:106
TCP_SEG_LEN
#define TCP_SEG_LEN(seg)
Definition: stream-tcp-private.h:94
stream-tcp-inline.h
PKT_STREAM_MODIFIED
#define PKT_STREAM_MODIFIED
Definition: decode.h:1278
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
seq
uint32_t seq
Definition: stream-tcp-private.h:2
Packet_::payload
uint8_t * payload
Definition: decode.h:580
Packet_::flags
uint32_t flags
Definition: decode.h:516
TcpSegment::sbseg
StreamingBufferSegment sbseg
Definition: stream-tcp-private.h:77
StreamTcpInlineSegmentReplacePacket
void StreamTcpInlineSegmentReplacePacket(const TcpStream *stream, Packet *p, const TcpSegment *seg)
Replace (part of) the payload portion of a packet by the data in a TCP segment.
Definition: stream-tcp-inline.c:121
TcpSegment::seq
uint32_t seq
Definition: stream-tcp-private.h:75
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:581
util-unittest.h
util-unittest-helper.h
util-memcmp.h
decode.h
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
SCReturn
#define SCReturn
Definition: util-debug.h:273
TcpSegment
Definition: stream-tcp-private.h:72
Packet_
Definition: decode.h:479
stream-tcp-private.h
SEQ_MIN
#define SEQ_MIN(a, b)
Definition: stream-tcp-private.h:261
suricata-common.h
SEQ_GT
#define SEQ_GT(a, b)
Definition: stream-tcp-private.h:259
TcpStream_::base_seq
uint32_t base_seq
Definition: stream-tcp-private.h:124
TcpStream_::sb
StreamingBuffer sb
Definition: stream-tcp-private.h:135
SEQ_MAX
#define SEQ_MAX(a, b)
Definition: stream-tcp-private.h:262
util-validate.h
StreamTcpInlineSegmentCompare
int StreamTcpInlineSegmentCompare(const TcpStream *stream, const Packet *p, const TcpSegment *seg)
Compare the shared data portion of two segments.
Definition: stream-tcp-inline.c:49
SEQ_LT
#define SEQ_LT(a, b)
Definition: stream-tcp-private.h:257
SEQ_EQ
#define SEQ_EQ(a, b)
Definition: stream-tcp-private.h:256
SEQ_LEQ
#define SEQ_LEQ(a, b)
Definition: stream-tcp-private.h:258
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:1737
stream-tcp-inline.c
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
TCPHdr_
Definition: decode-tcp.h:149