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-unittest.h"
35 #include "util-unittest-helper.h"
36 
37 /**
38  * \brief Compare the shared data portion of two segments
39  *
40  * If no data is shared, 0 will be returned.
41  *
42  * \param seg1 first segment
43  * \param seg2 second segment
44  *
45  * \retval 0 shared data is the same (or no data is shared)
46  * \retval 1 shared data is different
47  */
49  const Packet *p, const TcpSegment *seg)
50 {
51  SCEnter();
52 
53  if (p == NULL || seg == NULL) {
54  SCReturnInt(0);
55  }
56 
57  const uint8_t *seg_data;
58  uint32_t seg_datalen;
59  StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
60  if (seg_data == NULL || seg_datalen == 0)
61  SCReturnInt(0);
62 
63  const uint32_t pkt_seq = TCP_GET_SEQ(p);
64 
65  if (SEQ_EQ(pkt_seq, seg->seq) && p->payload_len == seg_datalen) {
66  int r = SCMemcmp(p->payload, seg_data, seg_datalen);
67  SCReturnInt(r);
68  } else if (SEQ_GT(pkt_seq, (seg->seq + seg_datalen))) {
69  SCReturnInt(0);
70  } else if (SEQ_GT(seg->seq, (pkt_seq + p->payload_len))) {
71  SCReturnInt(0);
72  } else {
73  SCLogDebug("p %u (%u), seg2 %u (%u)", pkt_seq,
74  p->payload_len, seg->seq, seg_datalen);
75 
76  uint32_t pkt_end = pkt_seq + p->payload_len;
77  uint32_t seg_end = seg->seq + seg_datalen;
78  SCLogDebug("pkt_end %u, seg_end %u", pkt_end, seg_end);
79 
80  /* get the minimal seg*_end */
81  uint32_t end = (SEQ_GT(pkt_end, seg_end)) ? seg_end : pkt_end;
82  /* and the max seq */
83  uint32_t seq = (SEQ_LT(pkt_seq, seg->seq)) ? seg->seq : pkt_seq;
84 
85  SCLogDebug("seq %u, end %u", seq, end);
86 
87  uint32_t pkt_off = seq - pkt_seq;
88  uint32_t seg_off = seq - seg->seq;
89  SCLogDebug("pkt_off %u, seg_off %u", pkt_off, seg_off);
90 
91  uint32_t range = end - seq;
92  SCLogDebug("range %u", range);
93  BUG_ON(range > 65536);
94 
95  if (range) {
96  int r = SCMemcmp(p->payload + pkt_off, seg_data + seg_off, range);
97  SCReturnInt(r);
98  }
99  SCReturnInt(0);
100  }
101 }
102 
103 /**
104  * \brief Replace (part of) the payload portion of a packet by the data
105  * in a TCP segment
106  *
107  * \param p Packet
108  * \param seg TCP segment
109  *
110  * \todo What about reassembled fragments?
111  * \todo What about unwrapped tunnel packets?
112  */
114  Packet *p, const TcpSegment *seg)
115 {
116  SCEnter();
117 
118  uint32_t pseq = TCP_GET_SEQ(p);
119  uint32_t tseq = seg->seq;
120 
121  /* check if segment is within the packet */
122  if (tseq + TCP_SEG_LEN(seg) < pseq) {
123  SCReturn;
124  } else if (pseq + p->payload_len < tseq) {
125  SCReturn;
126  }
127 
128  const uint8_t *seg_data;
129  uint32_t seg_datalen;
130  StreamingBufferSegmentGetData(&stream->sb, &seg->sbseg, &seg_data, &seg_datalen);
131 
132  uint32_t pend = pseq + p->payload_len;
133  uint32_t tend = tseq + seg_datalen;
134  SCLogDebug("pend %u, tend %u", pend, tend);
135 
136  /* get the minimal seg*_end */
137  uint32_t end = (SEQ_GT(pend, tend)) ? tend : pend;
138  /* and the max seq */
139  uint32_t seq = (SEQ_LT(pseq, tseq)) ? tseq : pseq;
140  SCLogDebug("seq %u, end %u", seq, end);
141 
142  uint32_t poff = seq - pseq;
143  uint32_t toff = seq - tseq;
144  SCLogDebug("poff %u, toff %u", poff, toff);
145 
146  uint32_t range = end - seq;
147  SCLogDebug("range %u", range);
148  BUG_ON(range > 65536);
149 
150  if (range) {
151  /* update the packets payload. As payload is a ptr to either
152  * p->pkt or p->ext_pkt that is updated as well */
153  memcpy(p->payload+poff, seg_data+toff, range);
154 
155  /* flag as modified so we can reinject / replace after
156  * recalculating the checksum */
158  }
159 }
160 
161 #ifdef UNITTESTS
162 #include "tests/stream-tcp-inline.c"
163 #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:1008
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:573
Packet_::flags
uint32_t flags
Definition: decode.h:463
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:113
TcpSegment::seq
uint32_t seq
Definition: stream-tcp-private.h:75
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:574
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:289
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:428
stream-tcp-private.h
suricata-common.h
SEQ_GT
#define SEQ_GT(a, b)
Definition: stream-tcp-private.h:252
TcpStream_::sb
StreamingBuffer sb
Definition: stream-tcp-private.h:134
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:48
SEQ_LT
#define SEQ_LT(a, b)
Definition: stream-tcp-private.h:250
SEQ_EQ
#define SEQ_EQ(a, b)
Definition: stream-tcp-private.h:249
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:1520
stream-tcp-inline.c
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290