2 * Copyright (c) 2011 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * @file Segment processing
44 /** Alocate new segment structure. */
45 tcp_segment_t
*tcp_segment_new(void)
47 return calloc(1, sizeof(tcp_segment_t
));
50 /** Delete segment. */
51 void tcp_segment_delete(tcp_segment_t
*seg
)
56 /** Create duplicate of segment.
59 * @return Duplicate segment
61 tcp_segment_t
*tcp_segment_dup(tcp_segment_t
*seg
)
66 scopy
= tcp_segment_new();
70 scopy
->ctrl
= seg
->ctrl
;
71 scopy
->seq
= seg
->seq
;
72 scopy
->ack
= seg
->ack
;
73 scopy
->len
= seg
->len
;
74 scopy
->wnd
= seg
->wnd
;
77 tsize
= tcp_segment_text_size(seg
);
78 scopy
->data
= calloc(tsize
, 1);
79 if (scopy
->data
== NULL
) {
84 memcpy(scopy
->data
, seg
->data
, tsize
);
85 scopy
->dfptr
= scopy
->data
;
90 /** Create a control-only segment.
94 tcp_segment_t
*tcp_segment_make_ctrl(tcp_control_t ctrl
)
98 seg
= tcp_segment_new();
103 seg
->len
= seq_no_control_len(ctrl
);
108 /** Create an RST segment.
110 * @param seg Segment we are replying to
111 * @return RST segment
113 tcp_segment_t
*tcp_segment_make_rst(tcp_segment_t
*seg
)
117 rseg
= tcp_segment_new();
121 if ((seg
->ctrl
& CTL_ACK
) == 0) {
122 rseg
->ctrl
= CTL_RST
| CTL_ACK
;
124 rseg
->ack
= seg
->seq
+ seg
->len
;
126 rseg
->ctrl
= CTL_RST
;
127 rseg
->seq
= seg
->ack
;
133 /** Create a control segment.
137 tcp_segment_t
*tcp_segment_make_data(tcp_control_t ctrl
, void *data
,
142 seg
= tcp_segment_new();
147 seg
->len
= seq_no_control_len(ctrl
) + size
;
149 seg
->dfptr
= seg
->data
= malloc(size
);
150 if (seg
->dfptr
== NULL
) {
155 memcpy(seg
->data
, data
, size
);
161 /** Trim segment from left and right by the specified amount.
163 * Trim any text or control to remove the specified amount of sequence
164 * numbers from the left (lower sequence numbers) and right side
165 * (higher sequence numbers) of the segment.
167 * @param seg Segment, will be modified in place
168 * @param left Amount of sequence numbers to trim from the left
169 * @param right Amount of sequence numbers to trim from the right
171 void tcp_segment_trim(tcp_segment_t
*seg
, uint32_t left
, uint32_t right
)
175 assert(left
+ right
<= seg
->len
);
177 /* Special case, entire segment trimmed from left */
178 if (left
== seg
->len
) {
179 seg
->seq
= seg
->seq
+ seg
->len
;
184 /* Special case, entire segment trimmed from right */
185 if (right
== seg
->len
) {
192 t_size
= tcp_segment_text_size(seg
);
194 if (left
> 0 && (seg
->ctrl
& CTL_SYN
) != 0) {
196 seg
->ctrl
&= ~CTL_SYN
;
202 if (right
> 0 && (seg
->ctrl
& CTL_FIN
) != 0) {
204 seg
->ctrl
&= ~CTL_FIN
;
209 if (left
> 0 || right
> 0) {
210 /* Trim segment text */
211 assert(left
+ right
<= t_size
);
214 seg
->len
-= left
+ right
;
218 /** Copy out text data from segment.
220 * Data is copied from the beginning of the segment text up to @a size bytes.
221 * @a size must not be greater than the size of the segment text, but
225 * @param buf Destination buffer
226 * @param size Size of destination buffer
228 void tcp_segment_text_copy(tcp_segment_t
*seg
, void *buf
, size_t size
)
230 assert(size
<= tcp_segment_text_size(seg
));
231 memcpy(buf
, seg
->data
, size
);
234 /** Return number of bytes in segment text.
237 * @return Number of bytes in segment text
239 size_t tcp_segment_text_size(tcp_segment_t
*seg
)
241 return seg
->len
- seq_no_control_len(seg
->ctrl
);
244 /** Dump segment contents to log.
248 void tcp_segment_dump(tcp_segment_t
*seg
)
250 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, "Segment dump:");
251 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - ctrl = %u", (unsigned)seg
->ctrl
);
252 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - seq = % " PRIu32
, seg
->seq
);
253 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - ack = % " PRIu32
, seg
->ack
);
254 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - len = % " PRIu32
, seg
->len
);
255 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - wnd = % " PRIu32
, seg
->wnd
);
256 log_msg(LOG_DEFAULT
, LVL_DEBUG2
, " - up = % " PRIu32
, seg
->up
);