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 uint32_t pkt_seq = TCP_GET_SEQ(p);
67 
68  if (SEQ_EQ(pkt_seq, seg->seq) && p->payload_len == seg_datalen) {
69  int r = SCMemcmp(p->payload, seg_data, seg_datalen);
70  SCReturnInt(r);
71  } else if (SEQ_GT(pkt_seq, (seg->seq + seg_datalen))) {
72  SCReturnInt(0);
73  } else if (SEQ_GT(seg->seq, (pkt_seq + p->payload_len))) {
74  SCReturnInt(0);
75  } else {
76  SCLogDebug("p %u (%u), seg2 %u (%u)", pkt_seq,
77  p->payload_len, seg->seq, seg_datalen);
78 
79  uint32_t seg_seq = seg->seq;
80  if (SEQ_LT(seg_seq, stream->base_seq)) {
81  seg_seq = stream->base_seq;
82  }
83  uint32_t pkt_end = pkt_seq + p->payload_len;
84  uint32_t seg_end = seg_seq + seg_datalen;
85  SCLogDebug("pkt_end %u, seg_end %u", pkt_end, seg_end);
86 
87  /* get the minimal seg*_end */
88  uint32_t end = SEQ_MIN(seg_end, pkt_end);
89  /* and the max seq */
90  uint32_t seq = SEQ_MAX(pkt_seq, seg_seq);
91  seq = SEQ_MAX(seq, stream->base_seq);
92  SCLogDebug("seq %u, end %u", seq, end);
93 
94  uint32_t pkt_off = seq - pkt_seq;
95  uint32_t seg_off = seq - seg_seq;
96  SCLogDebug("pkt_off %u, seg_off %u", pkt_off, seg_off);
97 
98  uint32_t range = end - seq;
99  SCLogDebug("range %u", range);
100  BUG_ON(range > 65536);
101 
102  if (range) {
103  int r = SCMemcmp(p->payload + pkt_off, seg_data + seg_off, range);
104  SCReturnInt(r);
105  }
106  SCReturnInt(0);
107  }
108 }
109 
110 /**
111  * \brief Replace (part of) the payload portion of a packet by the data
112  * in a TCP segment
113  *
114  * \param p Packet
115  * \param seg TCP segment
116  *
117  * \todo What about reassembled fragments?
118  * \todo What about unwrapped tunnel packets?
119  */
121  Packet *p, const TcpSegment *seg)
122 {
123  SCEnter();
124 
125  uint32_t pseq = TCP_GET_SEQ(p);
126  uint32_t tseq = seg->seq;
127 
128  /* check if segment is within the packet */
129  if (tseq + TCP_SEG_LEN(seg) < pseq) {
130  SCReturn;
131  } else if (pseq + p->payload_len < tseq) {
132  SCReturn;
133  }
134 
135  const uint8_t *seg_data;
136  uint32_t seg_datalen;
137  StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
138 
139  uint32_t pend = pseq + p->payload_len;
140  uint32_t tend = tseq + seg_datalen;
141  SCLogDebug("pend %u, tend %u", pend, tend);
142 
143  /* get the minimal seg*_end */
144  uint32_t end = (SEQ_GT(pend, tend)) ? tend : pend;
145  /* and the max seq */
146  uint32_t seq = (SEQ_LT(pseq, tseq)) ? tseq : pseq;
147  SCLogDebug("seq %u, end %u", seq, end);
148 
149  uint32_t poff = seq - pseq;
150  uint32_t toff = seq - tseq;
151  SCLogDebug("poff %u, toff %u", poff, toff);
152 
153  uint32_t range = end - seq;
154  SCLogDebug("range %u", range);
155  BUG_ON(range > 65536);
156 
157  if (range) {
158  /* update the packets payload. As payload is a ptr to either
159  * p->pkt or p->ext_pkt that is updated as well */
160  memcpy(p->payload+poff, seg_data+toff, range);
161 
162  /* flag as modified so we can reinject / replace after
163  * recalculating the checksum */
165  }
166 }
167 
168 #ifdef UNITTESTS
169 #include "tests/stream-tcp-inline.c"
170 #endif
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:1027
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:586
Packet_::flags
uint32_t flags
Definition: decode.h:474
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:120
TcpSegment::seq
uint32_t seq
Definition: stream-tcp-private.h:75
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:587
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
TCP_GET_SEQ
#define TCP_GET_SEQ(p)
Definition: decode-tcp.h:114
SCReturn
#define SCReturn
Definition: util-debug.h:273
TcpSegment
Definition: stream-tcp-private.h:72
Packet_
Definition: decode.h:437
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:1734
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:103