]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Add comments for functions and fix some coding style issue.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Option.c
1 /** @file
2
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Tcp4Option.c
15
16 Abstract:
17
18 Routines to process TCP option.
19
20
21 **/
22
23 #include "Tcp4Main.h"
24
25 /**
26 Get a UINT16 value from buffer.
27
28 @param Buf Pointer to input buffer.
29
30 @return The UINT16 value get from buffer.
31
32 **/
33 UINT16
34 TcpGetUint16 (
35 IN UINT8 *Buf
36 )
37 {
38 UINT16 Value;
39 CopyMem (&Value, Buf, sizeof (UINT16));
40 return NTOHS (Value);
41 }
42
43 /**
44 Get a UINT32 value from buffer.
45
46 @param Buf Pointer to input buffer.
47
48 @return The UINT32 value get from buffer.
49
50 **/
51 UINT32
52 TcpGetUint32 (
53 IN UINT8 *Buf
54 )
55 {
56 UINT32 Value;
57 CopyMem (&Value, Buf, sizeof (UINT32));
58 return NTOHL (Value);
59 }
60
61 /**
62 Put a UINT32 value in buffer.
63
64 @param Buf Pointer to the buffer.
65 @param Data The UINT32 Date to put in buffer
66
67 **/
68 VOID
69 TcpPutUint32 (
70 IN UINT8 *Buf,
71 IN UINT32 Data
72 )
73 {
74 Data = HTONL (Data);
75 CopyMem (Buf, &Data, sizeof (UINT32));
76 }
77
78
79 /**
80 Compute the window scale value according to the given buffer size.
81
82 @param Tcb Pointer to the TCP_CB of this TCP instance.
83
84 @return The scale value.
85
86 **/
87 UINT8
88 TcpComputeScale (
89 IN TCP_CB *Tcb
90 )
91 {
92 UINT8 Scale;
93 UINT32 BufSize;
94
95 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
96
97 BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
98
99 Scale = 0;
100 while ((Scale < TCP_OPTION_MAX_WS) &&
101 ((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
102
103 Scale++;
104 }
105
106 return Scale;
107 }
108
109
110 /**
111 Build the TCP option in three-way handshake.
112
113 @param Tcb Pointer to the TCP_CB of this TCP instance.
114 @param Nbuf Pointer to the buffer to store the options.
115
116 @return The total length of the TCP option field.
117
118 **/
119 UINT16
120 TcpSynBuildOption (
121 IN TCP_CB *Tcb,
122 IN NET_BUF *Nbuf
123 )
124 {
125 UINT8 *Data;
126 UINT16 Len;
127
128 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
129
130 Len = 0;
131
132 //
133 // Add timestamp option if not disabled by application
134 // and it is the first SYN segment or the peer has sent
135 // us its timestamp.
136 //
137 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
138 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
139 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
140
141 Data = NetbufAllocSpace (
142 Nbuf,
143 TCP_OPTION_TS_ALIGNED_LEN,
144 NET_BUF_HEAD
145 );
146
147 ASSERT (Data != NULL);
148 Len += TCP_OPTION_TS_ALIGNED_LEN;
149
150 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
151 TcpPutUint32 (Data + 4, mTcpTick);
152 TcpPutUint32 (Data + 8, 0);
153 }
154
155 //
156 // Build window scale option, only when are configured
157 // to send WS option, and either we are doing active
158 // open or we have received WS option from peer.
159 //
160 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
161 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
162 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
163
164 Data = NetbufAllocSpace (
165 Nbuf,
166 TCP_OPTION_WS_ALIGNED_LEN,
167 NET_BUF_HEAD
168 );
169
170 ASSERT (Data != NULL);
171
172 Len += TCP_OPTION_WS_ALIGNED_LEN;
173 TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
174 }
175
176 //
177 // Build MSS option
178 //
179 Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
180 ASSERT (Data != NULL);
181
182 Len += TCP_OPTION_MSS_LEN;
183 TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
184
185 return Len;
186 }
187
188
189 /**
190 Build the TCP option in synchronized states.
191
192 @param Tcb Pointer to the TCP_CB of this TCP instance.
193 @param Nbuf Pointer to the buffer to store the options.
194
195 @return The total length of the TCP option field.
196
197 **/
198 UINT16
199 TcpBuildOption (
200 IN TCP_CB *Tcb,
201 IN NET_BUF *Nbuf
202 )
203 {
204 UINT8 *Data;
205 UINT16 Len;
206
207 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
208 Len = 0;
209
210 //
211 // Build Timestamp option
212 //
213 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
214 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
215
216 Data = NetbufAllocSpace (
217 Nbuf,
218 TCP_OPTION_TS_ALIGNED_LEN,
219 NET_BUF_HEAD
220 );
221
222 ASSERT (Data != NULL);
223 Len += TCP_OPTION_TS_ALIGNED_LEN;
224
225 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
226 TcpPutUint32 (Data + 4, mTcpTick);
227 TcpPutUint32 (Data + 8, Tcb->TsRecent);
228 }
229
230 return Len;
231 }
232
233
234 /**
235 Parse the supported options.
236
237 @param Tcp Pointer to the TCP_CB of this TCP instance.
238 @param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
239 options.
240
241 @retval 0 The options are successfully pasrsed.
242 @retval -1 Ilegal option was found.
243
244 **/
245 INTN
246 TcpParseOption (
247 IN TCP_HEAD *Tcp,
248 IN TCP_OPTION *Option
249 )
250 {
251 UINT8 *Head;
252 UINT8 TotalLen;
253 UINT8 Cur;
254 UINT8 Type;
255 UINT8 Len;
256
257 ASSERT ((Tcp != NULL) && (Option != NULL));
258
259 Option->Flag = 0;
260
261 TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
262 if (TotalLen <= 0) {
263 return 0;
264 }
265
266 Head = (UINT8 *) (Tcp + 1);
267
268 //
269 // Fast process of timestamp option
270 //
271 if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
272 (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
273
274 Option->TSVal = TcpGetUint32 (Head + 4);
275 Option->TSEcr = TcpGetUint32 (Head + 8);
276 Option->Flag = TCP_OPTION_RCVD_TS;
277
278 return 0;
279 }
280
281 //
282 // Slow path to process the options.
283 //
284 Cur = 0;
285
286 while (Cur < TotalLen) {
287 Type = Head[Cur];
288
289 switch (Type) {
290 case TCP_OPTION_MSS:
291 Len = Head[Cur + 1];
292
293 if ((Len != TCP_OPTION_MSS_LEN) ||
294 (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
295
296 return -1;
297 }
298
299 Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
300 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
301
302 Cur += TCP_OPTION_MSS_LEN;
303 break;
304
305 case TCP_OPTION_WS:
306 Len = Head[Cur + 1];
307
308 if ((Len != TCP_OPTION_WS_LEN) ||
309 (TotalLen - Cur < TCP_OPTION_WS_LEN)) {
310
311 return -1;
312 }
313
314 Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);
315 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
316
317 Cur += TCP_OPTION_WS_LEN;
318 break;
319
320 case TCP_OPTION_TS:
321 Len = Head[Cur + 1];
322
323 if ((Len != TCP_OPTION_TS_LEN) ||
324 (TotalLen - Cur < TCP_OPTION_TS_LEN)) {
325
326 return -1;
327 }
328
329 Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
330 Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
331 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
332
333 Cur += TCP_OPTION_TS_LEN;
334 break;
335
336 case TCP_OPTION_NOP:
337 Cur++;
338 break;
339
340 case TCP_OPTION_EOP:
341 Cur = TotalLen;
342 break;
343
344 default:
345 Len = Head[Cur + 1];
346
347 if ((TotalLen - Cur) < Len || Len < 2) {
348 return -1;
349 }
350
351 Cur = (UINT8) (Cur + Len);
352 break;
353 }
354
355 }
356
357 return 0;
358 }
359
360
361 /**
362 Check the segment against PAWS.
363
364 @param Tcb Pointer to the TCP_CB of this TCP instance.
365 @param TSVal The timestamp value.
366
367 @retval 1 The segment passed the PAWS check.
368 @retval 0 The segment failed to pass the PAWS check.
369
370 **/
371 UINT32
372 TcpPawsOK (
373 IN TCP_CB *Tcb,
374 IN UINT32 TSVal
375 )
376 {
377 //
378 // PAWS as defined in RFC1323, buggy...
379 //
380 if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&
381 TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)) {
382
383 return 0;
384
385 }
386
387 return 1;
388 }