NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
TCP_Packet.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#include "main.h"
25#include "TCP.h"
26#include "TCP_Header.h"
27
28bool isSynPacket(NetSim_PACKET* packet)
29{
30 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(packet);
31 if (hdr->Syn &&
32 !hdr->Ack)
33 return true;
34 else
35 return false;
36}
37
38bool isSynbitSet(NetSim_PACKET* packet)
39{
40 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(packet);
41 return hdr->Syn ? true : false;
42}
43
44
45void set_tcp_option(PTCP_SEGMENT_HDR hdr, void* option, TCP_OPTION type, UINT32 size)
46{
47 PTCPOPTION opt = (PTCPOPTION)calloc(1, sizeof* opt);
48 opt->type = type;
49 opt->option = option;
50 opt->size = size;
51
52 hdr->HdrLength += size;
53
54 if (hdr->option)
55 {
56 PTCPOPTION o = hdr->option;
57 while (o->next)
58 o = o->next;
59 o->next = opt;
60 }
61 else
62 hdr->option = opt;
63}
64
65void* get_tcp_option(PTCP_SEGMENT_HDR hdr, TCP_OPTION type)
66{
67 PTCPOPTION o = hdr->option;
68 while (o)
69 {
70 if (o->type == type)
71 return o->option;
72 o = o->next;
73 }
74 return NULL;
75}
76
77static void add_tcp_extra_option(PTCP_SEGMENT_HDR hdr, UINT32 l)
78{
79 UINT32 i;
80 for (i = 0; i < 4-l; i++)
81 {
82 if (i == 4 - l - 1)
83 {
84 PEXTRA_OPTION end = calloc(1, sizeof* end);
85 end->type = TCP_OPTION_END;
86 set_tcp_option(hdr, end, TCP_OPTION_END, EXTRA_OPTION_LEN);
87 }
88 else
89 {
90 PEXTRA_OPTION nop = calloc(1, sizeof* nop);
91 nop->type = TCP_OPTION_NOOPERATION;
92 set_tcp_option(hdr, nop, TCP_OPTION_NOOPERATION, EXTRA_OPTION_LEN);
93 }
94 }
95}
96
97static void set_tcp_packet_size(NetSim_PACKET* p)
98{
99 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
100 if (hdr->HdrLength % 4)
101 {
102 add_tcp_extra_option(hdr, hdr->HdrLength % 4);
103 }
104 p->pstruTransportData->dOverhead = hdr->HdrLength;
105 p->pstruTransportData->dPacketSize = p->pstruTransportData->dPayload +
106 p->pstruTransportData->dOverhead;
107}
108
109static void add_tcp_mss_option(PNETSIM_SOCKET s,
110 PTCP_SEGMENT_HDR hdr)
111{
112 PMSS_OPTION opt = (PMSS_OPTION)calloc(1, sizeof* opt);
113 opt->type = TCP_OPTION_MSS;
114 opt->len = MSS_OPTION_LEN;
115 opt->MSSData = s->tcb->get_MSS(s);
116 set_tcp_option(hdr, opt, TCP_OPTION_MSS, MSS_OPTION_LEN);
117}
118
119static void add_tcp_sack_permitted_option(PNETSIM_SOCKET s,
120 PTCP_SEGMENT_HDR hdr)
121{
122 s;
123 PSACKPERMITTED_OPTION opt = (PSACKPERMITTED_OPTION)calloc(1, sizeof* opt);
124 opt->type = TCP_OPTION_SACK_PERMITTED;
125 opt->len = SACKPERMITTED_OPTION_LEN;
126 set_tcp_option(hdr, opt, TCP_OPTION_SACK_PERMITTED, SACKPERMITTED_OPTION_LEN);
127}
128
129static void add_tcp_window_scale_option(PNETSIM_SOCKET s,
130 PTCP_SEGMENT_HDR hdr)
131{
132 PWsopt opt = (PWsopt)calloc(1, sizeof* opt);
133 opt->type = TCP_OPTION_WINDOW_SCALE;
134 opt->len = WSOPT_LEN;
135 opt->Shift_cnt = s->tcb->Snd.Wind_Shift;
136 set_tcp_option(hdr, opt, TCP_OPTION_WINDOW_SCALE, WSOPT_LEN);
137
138 PEXTRA_OPTION ex = (PEXTRA_OPTION)calloc(1, sizeof* ex);
139 ex->type = TCP_OPTION_NOOPERATION;
140 set_tcp_option(hdr, ex, TCP_OPTION_NOOPERATION, EXTRA_OPTION_LEN);
141}
142
143static void add_tcp_timestamp_option(PNETSIM_SOCKET s,
144 PTCP_SEGMENT_HDR hdr)
145{
146 PTSopt opt = (PTSopt)calloc(1, sizeof* opt);
147 opt->type = TCP_OPTION_TIMESTAMP;
148 opt->len = TSOPT_LEN;
149
150 opt->TSval = (UINT)pstruEventDetails->dEventTime;
151
152 if (!hdr->Ack)
153 opt->TSecr = 0;
154 else
155 opt->TSecr = s->tcb->TSVal;
156
157 set_tcp_option(hdr, opt, TCP_OPTION_TIMESTAMP, TSOPT_LEN);
158
159 PEXTRA_OPTION ex = (PEXTRA_OPTION)calloc(1, sizeof* ex);
160 ex->type = TCP_OPTION_NOOPERATION;
161 set_tcp_option(hdr, ex, TCP_OPTION_NOOPERATION, EXTRA_OPTION_LEN);
162}
163
164NetSim_PACKET* create_tcp_ctrl_packet(PNETSIM_SOCKET s,
165 TCPPACKET type,
166 double time)
167{
168 PTCP_SEGMENT_HDR hdr = (PTCP_SEGMENT_HDR)calloc(1, sizeof* hdr);
169 hdr->HdrLength = TCP_HDR_SIZE;
170 hdr->SrcPort = s->localAddr->port;
171 hdr->DstPort = s->remoteAddr->port;
172
173 NetSim_PACKET* p = fn_NetSim_Packet_CreatePacket(TRANSPORT_LAYER);
174 p->nControlDataType = type;
175 add_dest_to_packet(p, s->remoteDeviceId);
176 p->nPacketType = PacketType_Control;
177 p->nSourceId = s->localDeviceId;
178 p->pstruTransportData->dArrivalTime = time;
179 p->pstruTransportData->dOverhead = TCP_HDR_SIZE;
180 p->pstruTransportData->dPayload = 0;
181 p->pstruTransportData->dPacketSize = TCP_HDR_SIZE;
182 p->pstruTransportData->nDestinationPort = s->remoteAddr->port;
183 p->pstruTransportData->nSourcePort = s->localAddr->port;
184 p->pstruTransportData->nTransportProtocol = TX_PROTOCOL_TCP;
185 p->pstruTransportData->Packet_TransportProtocol = hdr;
186
187 p->pstruNetworkData->szSourceIP = s->localAddr->ip;
188 p->pstruNetworkData->szDestIP = s->remoteAddr->ip;
189 p->pstruNetworkData->nTTL = MAX_TTL;
190 p->pstruNetworkData->IPProtocol = IPPROTOCOL_TCP;
191
192 return p;
193}
194
195NetSim_PACKET* create_syn(PNETSIM_SOCKET s,
196 double time)
197{
198 NetSim_PACKET* p = create_tcp_ctrl_packet(s,
199 TCPPACKET_SYN,
200 time);
201
202 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
203
204 hdr->Syn = 1;
205 hdr->SeqNum = s->tcb->ISS;
206 hdr->Window = s->tcb->get_WND(s);
207
208 add_tcp_mss_option(s, hdr);
209
210 if (s->tcb->isSackPermitted)
211 add_tcp_sack_permitted_option(s, hdr);
212
213 if (s->tcb->isTSopt)
214 add_tcp_timestamp_option(s, hdr);
215
216 if (s->tcb->isWindowScaling)
217 add_tcp_window_scale_option(s, hdr);
218
219 set_tcp_packet_size(p);
220
221 return p;
222}
223
224NetSim_PACKET* create_synAck(PNETSIM_SOCKET s,
225 double time)
226{
227 NetSim_PACKET* p = create_tcp_ctrl_packet(s,
228 TCPPACKET_SYNACK,
229 time);
230
231 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
232
233 hdr->Syn = 1;
234 hdr->Ack = 1;
235 hdr->SeqNum = s->tcb->ISS;
236 hdr->AckNum = s->tcb->RCV.NXT;
237 hdr->Window = s->tcb->get_WND(s);
238
239 add_tcp_mss_option(s, hdr);
240
241 if (s->tcb->isWindowScaling)
242 add_tcp_window_scale_option(s, hdr);
243
244 if (s->tcb->isSackPermitted)
245 add_tcp_sack_permitted_option(s, hdr);
246
247 if (s->tcb->isTSopt)
248 add_tcp_timestamp_option(s, hdr);
249
250 set_tcp_packet_size(p);
251
252 return p;
253}
254
255NetSim_PACKET* create_rst(NetSim_PACKET* p,
256 double time,
257 UINT c)
258{
259 NETSIM_SOCKET temp;
260 SOCKETADDRESS l,r;
261
262 l.ip = p->pstruNetworkData->szDestIP;
263 l.port = p->pstruTransportData->nDestinationPort;
264 temp.localAddr = &l;
265
266 r.ip = p->pstruNetworkData->szSourceIP;
267 r.port = p->pstruTransportData->nSourcePort;
268 temp.remoteAddr = &r;
269
270 temp.localDeviceId = get_first_dest_from_packet(p);
271 temp.remoteDeviceId = p->nSourceId;
272
273 NetSim_PACKET* packet = create_tcp_ctrl_packet(&temp,
274 TCPPACKET_RST,
275 time);
276
277 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(packet);
278 PTCP_SEGMENT_HDR seg = TCP_GET_SEGMENT_HDR(p);
279
280 if (seg->Ack || c == 1)
281 {
282 hdr->SeqNum = seg->AckNum;
283 hdr->Rst = 1;
284 }
285 else
286 {
287 hdr->SeqNum = 0;
288 hdr->AckNum = seg->SeqNum + seg->HdrLength;
289 hdr->Rst = 1;
290 hdr->Ack = 1;
291 }
292
293 set_tcp_packet_size(p);
294
295 return packet;
296}
297
298NetSim_PACKET* create_ack(PNETSIM_SOCKET s,
299 double time,
300 UINT32 seqno,
301 UINT32 ackno)
302{
303 NetSim_PACKET* p = create_tcp_ctrl_packet(s,
304 TCPPACKET_ACK,
305 time);
306
307 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
308
309 hdr->Ack = 1;
310 hdr->SeqNum = seqno;
311 hdr->AckNum = ackno;
312 hdr->Window = s->tcb->get_WND(s);
313
314 if (s->tcb->isTSopt)
315 add_tcp_timestamp_option(s, hdr);
316
317 set_sack_option(s, hdr, time);
318 set_tcp_packet_size(p);
319
320 return p;
321}
322
323NetSim_PACKET* create_fin(PNETSIM_SOCKET s,
324 double time)
325{
326 NetSim_PACKET* p = create_tcp_ctrl_packet(s,
327 TCPPACKET_FIN,
328 time);
329
330 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
331
332 hdr->Fin = 1;
333 hdr->SeqNum = s->tcb->ISS + 1 == s->tcb->SND.NXT ?
334 s->tcb->SND.NXT + 1 : s->tcb->SND.NXT;
335 hdr->Window = window_scale_get_wnd(s);
336
337 set_tcp_packet_size(p);
338
339 return p;
340}
341
342void add_tcp_hdr(NetSim_PACKET* p, PNETSIM_SOCKET s)
343{
344 PTCP_SEGMENT_HDR hdr = (PTCP_SEGMENT_HDR)calloc(1, sizeof* hdr);
345 hdr->DstPort = s->remoteAddr->port;
346 hdr->HdrLength = TCP_HDR_SIZE;
347 hdr->SeqNum = s->tcb->SND.NXT;
348 hdr->SrcPort = s->localAddr->port;
349 hdr->Window = window_scale_get_wnd(s);
350
351 if(s->tcb->isTSopt)
352 add_tcp_timestamp_option(s, hdr);
353
354 p->pstruTransportData->dArrivalTime = pstruEventDetails->dEventTime;
355 p->pstruTransportData->dEndTime = pstruEventDetails->dEventTime;
356 p->pstruTransportData->dOverhead = TCP_HDR_SIZE;
357 p->pstruTransportData->dPayload = p->pstruAppData->dPacketSize;
358 p->pstruTransportData->dStartTime = pstruEventDetails->dEventTime;
359 p->pstruTransportData->Packet_TransportProtocol = hdr;
360 p->pstruTransportData->nTransportProtocol = TX_PROTOCOL_TCP;
361
362 p->pstruNetworkData->IPProtocol = IPPROTOCOL_TCP;
363
364 set_tcp_packet_size(p);
365}
366
367static PTCPOPTION copy_tcp_mss_option(PTCPOPTION opt)
368{
369 PTCPOPTION o = (PTCPOPTION)calloc(1, sizeof* o);
370 memcpy(o, opt, sizeof* o);
371 o->next = NULL;
372 PMSS_OPTION mss = opt->option;
373 PMSS_OPTION m = (PMSS_OPTION)calloc(1, sizeof* m);
374 memcpy(m, mss, sizeof* m);
375 o->option = m;
376 return o;
377}
378
379static PTCPOPTION copy_tcp_sack_permitted_option(PTCPOPTION opt)
380{
381 PTCPOPTION o = (PTCPOPTION)calloc(1, sizeof* o);
382 memcpy(o, opt, sizeof* o);
383 o->next = NULL;
384 PSACKPERMITTED_OPTION sackPermitted = opt->option;
385 PSACKPERMITTED_OPTION sp = (PSACKPERMITTED_OPTION)calloc(1, sizeof* sp);
386 memcpy(sp, sackPermitted, sizeof* sp);
387 o->option = sp;
388 return o;
389}
390
391static PTCPOPTION copy_tcp_extra_option(PTCPOPTION opt)
392{
393 PTCPOPTION o = (PTCPOPTION)calloc(1, sizeof* o);
394 memcpy(o, opt, sizeof* o);
395 o->next = NULL;
396 PEXTRA_OPTION ex = opt->option;
397 PEXTRA_OPTION dex = (PEXTRA_OPTION)calloc(1, sizeof* dex);
398 memcpy(dex, ex, sizeof* dex);
399 o->option = dex;
400 return o;
401}
402
403static PTCPOPTION copy_sack_option(PTCPOPTION t)
404{
405 PSACK_OPTION sack = t->option;
406 PSACK_OPTION s = (PSACK_OPTION)calloc(1, sizeof* s);
407 memcpy(s, sack, sizeof* s);
408 s->sackData = NULL;
409 UINT c = get_sack_data_count(sack);
410 s->sackData = (PSACKDATA*)calloc(c, sizeof* s->sackData);
411 for (UINT i = 0; i < c; i++)
412 {
413 s->sackData[i] = (PSACKDATA)calloc(1, sizeof* s->sackData[i]);
414 memcpy(s->sackData[i], sack->sackData[i], sizeof* s->sackData[i]);
415 }
416 PTCPOPTION r = (PTCPOPTION)calloc(1, sizeof* r);
417 r->option = s;
418 r->size = t->size;
419 r->type = t->type;
420 return r;
421}
422
423static PTCPOPTION copy_window_scale_option(PTCPOPTION opt)
424{
425 PTCPOPTION o = (PTCPOPTION)calloc(1, sizeof* o);
426 memcpy(o, opt, sizeof* o);
427 o->next = NULL;
428 PWsopt ex = opt->option;
429 PWsopt dex = (PWsopt)calloc(1, sizeof* dex);
430 memcpy(dex, ex, sizeof* dex);
431 o->option = dex;
432 return o;
433}
434
435static PTCPOPTION copy_timestamp_option(PTCPOPTION opt)
436{
437 PTCPOPTION o = (PTCPOPTION)calloc(1, sizeof* o);
438 memcpy(o, opt, sizeof* o);
439 o->next = NULL;
440 PTSopt ex = opt->option;
441 PTSopt dex = (PTSopt)calloc(1, sizeof* dex);
442 memcpy(dex, ex, sizeof* dex);
443 o->option = dex;
444 return o;
445}
446
447static void copy_tcp_option(PTCP_SEGMENT_HDR dhdr, PTCP_SEGMENT_HDR hdr)
448{
449 PTCPOPTION opt = hdr->option;
450 dhdr->option = NULL;
451 while (opt)
452 {
453 PTCPOPTION dopt = NULL;
454 switch (opt->type)
455 {
456 case TCP_OPTION_END:
457 case TCP_OPTION_NOOPERATION:
458 dopt = copy_tcp_extra_option(opt);
459 break;
460 case TCP_OPTION_MSS:
461 dopt = copy_tcp_mss_option(opt);
462 break;
463 case TCP_OPTION_SACK_PERMITTED:
464 dopt = copy_tcp_sack_permitted_option(opt);
465 break;
466 case TCP_OPTION_SACK:
467 dopt = copy_sack_option(opt);
468 break;
469 case TCP_OPTION_WINDOW_SCALE:
470 dopt = copy_window_scale_option(opt);
471 break;
472 case TCP_OPTION_TIMESTAMP:
473 dopt = copy_timestamp_option(opt);
474 break;
475 default:
476 fnNetSimError("Unknown TCP option %d\n", opt->type);
477 break;
478 }
479 if (dhdr->option)
480 {
481 PTCPOPTION o = dhdr->option;
482 while (o->next)
483 o = o->next;
484 o->next = dopt;
485 }
486 else
487 {
488 dhdr->option = dopt;
489 }
490 opt = opt->next;
491 }
492}
493
494PTCP_SEGMENT_HDR copy_tcp_hdr(PTCP_SEGMENT_HDR hdr)
495{
496 if (hdr)
497 {
498 PTCP_SEGMENT_HDR dhdr = (PTCP_SEGMENT_HDR)calloc(1, sizeof * dhdr);
499 memcpy(dhdr, hdr, sizeof * dhdr);
500 copy_tcp_option(dhdr, hdr);
501 return dhdr;
502 }
503 return NULL;
504}
505
506static void free_tcp_mss_option(PMSS_OPTION mss)
507{
508 free(mss);
509}
510
511static void free_tcp_sack_permitted_option(PSACKPERMITTED_OPTION sackPermitted)
512{
513 free(sackPermitted);
514}
515
516static void free_tcp_extra_option(PEXTRA_OPTION ex)
517{
518 free(ex);
519}
520
521static void free_tcp_sack_option(PSACK_OPTION sack)
522{
523 UINT c = get_sack_data_count(sack);
524 for (UINT i = 0; i < c; i++)
525 {
526 free(sack->sackData[i]);
527 }
528 free(sack->sackData);
529 free(sack);
530}
531
532static void free_tcp_window_scale_option(PWsopt opt)
533{
534 free(opt);
535}
536
537static void free_tcp_timestamp_option(PTSopt opt)
538{
539 free(opt);
540}
541
542static void free_tcp_option(PTCPOPTION opt)
543{
544 while (opt)
545 {
546 PTCPOPTION o = opt->next;
547 switch (opt->type)
548 {
549 case TCP_OPTION_END:
550 case TCP_OPTION_NOOPERATION:
551 free_tcp_extra_option(opt->option);
552 break;
553 case TCP_OPTION_MSS:
554 free_tcp_mss_option(opt->option);
555 break;
556 case TCP_OPTION_SACK_PERMITTED:
557 free_tcp_sack_permitted_option(opt->option);
558 break;
559 case TCP_OPTION_SACK:
560 free_tcp_sack_option(opt->option);
561 break;
562 case TCP_OPTION_WINDOW_SCALE:
563 free_tcp_window_scale_option(opt->option);
564 break;
565 case TCP_OPTION_TIMESTAMP:
566 free_tcp_timestamp_option(opt->option);
567 break;
568 default:
569 fnNetSimError("Unknown TCP option %d\n", opt->type);
570 break;
571 }
572 free(opt);
573 opt = o;
574 }
575}
576
577void free_tcp_hdr(PTCP_SEGMENT_HDR hdr)
578{
579 free_tcp_option(hdr->option);
580 free(hdr);
581}