]> git.saurik.com Git - apple/network_cmds.git/blob - ecnprobe/session.c
network_cmds-481.20.1.tar.gz
[apple/network_cmds.git] / ecnprobe / session.c
1 /*
2 Copyright (c) 2000
3 International Computer Science Institute
4 All rights reserved.
5
6 This file may contain software code originally developed for the
7 Sting project. The Sting software carries the following copyright:
8
9 Copyright (c) 1998, 1999
10 Stefan Savage and the University of Washington.
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21 3. All advertising materials mentioning features or use of this software
22 must display the following acknowledgment:
23 This product includes software developed by ACIRI, the AT&T
24 Center for Internet Research at ICSI (the International Computer
25 Science Institute). This product may also include software developed
26 by Stefan Savage at the University of Washington.
27 4. The names of ACIRI, ICSI, Stefan Savage and University of Washington
28 may not be used to endorse or promote products derived from this software
29 without specific prior written permission.
30
31 THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
32 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
35 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 SUCH DAMAGE.
42 */
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <string.h>
47 #include <stdio.h>
48 #include <unistd.h>
49 #include <stdlib.h>
50 #include "base.h"
51 #include "inet.h"
52 #include "session.h"
53 #include "capture.h"
54 #include "support.h"
55 #include "ecn.h"
56 #include <errno.h>
57
58 struct TcpSession session;
59
60 int EstablishSession(uint32 sourceAddress,
61 uint16 sourcePort,
62 uint32 targetAddress,
63 uint16 targetPort,
64 int ip_optlen, // AM: add support for IP options
65 char *ip_opt, // AM: add support for IP options
66 int mss,
67 int optlen,
68 char *opt,
69 int maxwin,
70 int maxpkts,
71 uint8 iptos,
72 uint8 tcp_flags) // AM: Add a tcp_flags parameter
73 {
74
75 int rawSocket;
76
77 struct IPPacket *p = NULL;
78 struct IPPacket *synPacket;
79 char *read_packet;
80 struct pcap_pkthdr pi;
81 int synAckReceived = 0;
82 int numRetransmits = 0;
83 double timeoutTime;
84 double ts1 = 0, ts2;
85 int flag = 1;
86
87 if (session.debug == SESSION_DEBUG_HIGH) {
88 printf("In EstablishSession...\n");
89 }
90
91 arc4random_stir();
92
93 session.src = sourceAddress;
94 session.sport = sourcePort;
95 session.dst = targetAddress;
96 session.dport = targetPort;
97 session.rcv_wnd = maxwin * mss;
98 session.snd_nxt = arc4random(); /* random initial sequence number */
99 session.iss = session.snd_nxt;
100 session.rcv_nxt = 0;
101 session.irs = 0;
102 session.mss = mss ;
103 session.maxseqseen = 0 ;
104 session.epochTime = GetTime();
105 session.maxpkts = maxpkts;
106 session.num_unwanted_drops = 0;
107 session.num_reordered = 0;
108 session.num_rtos = 0;
109 session.num_dup_acks = 0;
110 session.num_pkts_0_dup_acks = 0;
111 session.num_pkts_1_dup_acks = 0;
112 session.num_pkts_2_dup_acks = 0;
113 session.num_pkts_3_dup_acks = 0;
114 session.num_pkts_4_or_more_dup_acks = 0;
115 session.num_dupack_ret = 0;
116 session.num_reord_ret = 0;
117 session.num_reordered = 0;
118 session.num_dup_transmissions = 0;
119 session.ignore_result = 0;
120 session.curr_ttl = 0;
121
122 if ((session.mtu < 1) || (session.mtu > 1460)) {
123 session.mtu = 1500;
124 }
125
126 if (session.verbose) {
127 printf("session.MTU = %d\n", session.mtu);
128 }
129
130 if ((session.dataRcvd = (uint8 *)calloc(sizeof(uint8), mss * session.maxpkts)) == NULL) {
131 perror("ERROR: no memmory to store data:\n");
132 printf("RETURN CODE: %d\n", ERR_MEM_ALLOC);
133 Quit(ERR_MEM_ALLOC);
134 }
135
136 /* Now open a raw socket for sending our "fake" TCP segments */
137 if ((rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
138 perror("ERROR: couldn't open socket:");
139 printf("RETURN CODE: %d\n", ERR_SOCKET_OPEN);
140 Quit(ERR_SOCKET_OPEN);
141 }
142
143 if (setsockopt(rawSocket, IPPROTO_IP, IP_HDRINCL, (char *)&flag,sizeof(flag)) < 0) {
144 perror("ERROR: couldn't set raw socket options:");
145 printf("RETURN CODE: %d\n", ERR_SOCKOPT);
146 Quit(ERR_SOCKOPT);
147 }
148
149 session.socket = rawSocket;
150
151 /* Allocate SYN packet */
152 synPacket = AllocateIPPacket(ip_optlen, optlen, 0, "EstablishSession (SYN)");
153
154 /* Copy IP options at the end of IpHeader structure - New */
155 if (ip_optlen > 0) {
156 memcpy((char *)synPacket->ip + sizeof(struct IpHeader), ip_opt, ip_optlen);
157 }
158
159 /* Copy TCP options at the end of TcpHeader structure - New */
160 if (optlen > 0) {
161 memcpy((char *)synPacket->tcp + sizeof(struct TcpHeader), opt, optlen);
162 }
163
164 /* Send SYN Pkt */
165 SendSessionPacket(synPacket,
166 sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + optlen,
167 TCPFLAGS_SYN | tcp_flags,
168 ip_optlen, /* IP opt len */
169 optlen, /* TCP opt len */
170 iptos);
171
172 timeoutTime = GetTime() + SYNTIMEOUT;
173
174 /*
175 * Wait for SYN/ACK and retransmit SYN if appropriate
176 * not great, but it gets the job done
177 */
178
179 while(!synAckReceived && numRetransmits < MAXSYNRETRANSMITS) {
180
181 while(GetTime() < timeoutTime) {
182
183 /* Have we captured any packets? */
184
185 if ((read_packet = (char *)CaptureGetPacket(&pi)) != NULL) {
186
187 p = (struct IPPacket *)FindHeaderBoundaries(read_packet);
188
189 /* Received a packet from us to them */
190 if (INSESSION(p, session.src, session.sport, session.dst, session.dport)) {
191
192 /* Is it a SYN? */
193 if (p->tcp->tcp_flags & TCPFLAGS_SYN) {
194
195 if (session.debug >= SESSION_DEBUG_LOW) {
196 printf("xmit\n");
197 PrintTcpPacket(p);
198 }
199
200 StorePacket(p);
201
202 ts1 = pi.ts.tv_sec + (double)pi.ts.tv_usec/1000000.0;
203 session.totSeenSent ++ ;
204
205 }
206
207 free(p);
208 continue;
209
210
211 }
212
213 if (INSESSION(p, session.dst, session.dport, session.src, session.sport)) {
214
215 /* Is it a SYN/ACK? */
216 if (p->tcp->tcp_flags & (TCPFLAGS_SYN | TCPFLAGS_ACK)) {
217
218 timeoutTime = GetTime(); /* force exit */
219 synAckReceived++;
220 ts2 = pi.ts.tv_sec + (double)pi.ts.tv_usec/1000000.0;
221 session.rtt = ts2 - ts1 ;
222
223 if (numRetransmits > 0) {
224 session.rtt_unreliable = 1;
225 printf("##### Unreliable\n"); /* ACK for which SYN? */
226 }
227
228 if (session.debug >= SESSION_DEBUG_LOW) {
229 printf("rcvd:\n");
230 PrintTcpPacket(p);
231 printf("Connection setup took %d ms\n",(int)((ts2 - ts1) * 1000.0));
232 }
233
234 StorePacket(p);
235
236 /* Save ttl for,admittedly poor,indications of reverse route change */
237 session.ttl = p->ip->ip_ttl;
238 session.snd_wnd = ntohl(p->tcp->tcp_win);
239 session.totRcvd++;
240
241 free(p);
242 break ;
243
244 }
245
246 }
247
248 free(p->ip);
249 free(p->tcp);
250 free(p);
251
252 }
253
254 }
255
256 if (!synAckReceived) {
257
258 if (session.debug >= SESSION_DEBUG_LOW) {
259 printf("SYN timeout. Retransmitting\n");
260 }
261
262 SendSessionPacket(synPacket,
263 sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + optlen,
264 TCPFLAGS_SYN | tcp_flags,
265 ip_optlen, /* IP opt len */
266 optlen, /* TCP opt len */
267 iptos);
268
269 timeoutTime = GetTime() + SYNTIMEOUT;
270 numRetransmits++;
271 }
272 }
273
274 if (numRetransmits >= MAXSYNRETRANSMITS) {
275 printf("ERROR: Could not establish contact after %d retries\nRETURN CODE: %d\n",
276 numRetransmits, NO_CONNECTION);
277 Quit(NO_CONNECTION);
278 }
279
280 /* Update session variables */
281 session.irs = ntohl(p->tcp->tcp_seq);
282 session.dataRcvd[0] = 1 ;
283 session.rcv_nxt = session.irs + 1; /* SYN/ACK takes up a byte of seq space */
284 session.snd_nxt = session.iss + 1; /* SYN takes up a byte of seq space */
285 session.snd_una = session.iss + 1;
286 session.maxseqseen = ntohl(p->tcp->tcp_seq);
287
288 session.initSession = 1;
289 if (session.debug >= SESSION_DEBUG_LOW) {
290 printf("src = %s:%d (%u)\n", InetAddress(session.src), session.sport, session.iss);
291 printf("dst = %s:%d (%u)\n", InetAddress(session.dst), session.dport, session.irs);
292 }
293
294 free(synPacket->ip);
295 free(synPacket->tcp);
296 free(synPacket);
297
298 if (session.debug == SESSION_DEBUG_HIGH) {
299 printf("Out of EstablishSession...\n");
300 }
301
302 session.start_time = GetTime();
303
304 return 1;
305
306 }
307
308 int PrepareRequest(char *data, char *filename)
309 {
310
311 char h1[] = "GET ";
312 char h2[] = " HTTP/1.1";
313 char h3[] = "Host: ";
314 char h4[] = "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11; DigExt; TBIT)";
315 char h5[] = "Accept: */*";
316
317 /* New */
318 char h7[] = "Pragma: no-cache";
319 char h8[] = "Cache-control: no-chache";
320 char deffile[] = DEFAULT_FILENAME;
321
322
323 if (session.debug == SESSION_DEBUG_HIGH) {
324 printf("In PrepareRequest...\n");
325 }
326
327 if (filename == NULL) {
328 filename = deffile;
329 }
330
331
332 if (strlen(session.targetName) > 0) {
333
334 sprintf(data,
335
336 "%s/%s %s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s%s\r\n\r\n",
337 h1,
338 filename,
339 h2,
340 h4,
341 h7,
342 h8,
343 h5,
344 h3,
345 session.targetName);
346 }else {
347
348 sprintf(data,
349 "%s%s%s\r\n%s\r\n\r\n",
350 h1,
351 filename,
352 h2,
353 h4);
354 }
355
356 if (session.debug == SESSION_DEBUG_HIGH) {
357 printf("Out PrepareRequest...\n");
358 }
359
360 return ((int)strlen(data));
361
362 }
363
364
365 void SendRequest(char *filename, void (*ackData)(struct IPPacket *p))
366 {
367
368 struct IPPacket *p, *datapkt;
369 struct pcap_pkthdr pi;
370 char *read_packet;
371 int i;
372 int sendflag = 1;
373 double startTime = 0;
374 char *dataptr;
375 char data[MAXREQUESTLEN];
376 int datalen;
377 int ipsz;
378
379 if (session.debug == SESSION_DEBUG_HIGH) {
380 printf("In SendRequest...\n");
381 }
382
383 datalen = PrepareRequest(data, filename);
384
385 ipsz = sizeof(struct IpHeader) + sizeof(struct TcpHeader) + datalen + 1;
386
387 /* Allocate space for IP data packet */
388 datapkt = AllocateIPPacket(0, 0, datalen + 1, "SendRequest (Data)");
389
390 dataptr = (char *)datapkt->tcp + sizeof(struct TcpHeader);
391 memcpy((void *)dataptr, (void *)data, datalen);
392
393 /* Send the data packet. Try to "achieve" reliability by sending the
394 * packet upto 5 times, wating for 2 seconds between packets (BAD
395 * busy-wait loop)
396 */
397
398 i = 0 ;
399 while(1) {
400
401 if (sendflag == 1) {
402
403 SendSessionPacket(datapkt,
404 ipsz,
405 TCPFLAGS_PSH | TCPFLAGS_ACK,
406 0, /* ip opt len */
407 0, /* tcp opt len */
408 0); /* tos */
409
410 startTime = GetTime();
411 sendflag = 0 ;
412 i++;
413
414 }
415
416 /* Check if we have received any packets */
417 if ((read_packet = (char *)CaptureGetPacket(&pi)) != NULL) {
418
419 p = (struct IPPacket *)FindHeaderBoundaries(read_packet);
420
421 /*
422 * packet that we sent?
423 */
424
425 if (INSESSION(p,session.src,session.sport,session.dst,session.dport) &&
426 (p->tcp->tcp_flags == (TCPFLAGS_PSH | TCPFLAGS_ACK)) &&
427 (ntohl(p->tcp->tcp_seq) == session.snd_nxt) &&
428 (ntohl(p->tcp->tcp_ack) <= session.rcv_nxt)) {
429
430 if (session.debug >= SESSION_DEBUG_LOW) {
431 printf("xmit %d\n", i);
432 PrintTcpPacket(p);
433 }
434
435 StorePacket(p);
436
437 free(p);
438
439 //session.snd_nxt += datalen + 1;
440 session.totSeenSent++;
441 continue;
442
443 }
444 /*
445 * packet from them?
446 */
447
448 if (INSESSION(p,session.dst,session.dport,session.src,session.sport) &&
449 (p->tcp->tcp_flags & TCPFLAGS_ACK) &&
450 (ntohl(p->tcp->tcp_seq) == session.rcv_nxt) &&
451 (ntohl(p->tcp->tcp_ack) >= session.snd_una)) {
452
453
454 session.snd_una = ntohl(p->tcp->tcp_ack);
455
456 if (p->ip->ip_ttl != session.ttl) {
457 printf("#### WARNING: route may have changed (ttl was %d, is %d).\n",
458 session.ttl, p->ip->ip_ttl);
459 session.ttl = p->ip->ip_ttl;
460 }
461
462 if (session.debug >= SESSION_DEBUG_LOW) {
463 printf("rcvd %d\n", i);
464 PrintTcpPacket(p);
465 }
466
467 StorePacket(p);
468 session.totRcvd ++;
469 session.snd_nxt += datalen + 1;
470
471 /* if the packet also contains data, receive it and send an ack if needed */
472 (*ackData)(p);
473
474 free(p);
475 break;
476
477 }
478
479 free(p);
480
481 }
482
483 if ((GetTime() - startTime >= REXMITDELAY) &&
484 (sendflag == 0) && (i < MAXDATARETRANSMITS)) {
485 sendflag = 1 ;
486 }
487
488 if (i >= MAXDATARETRANSMITS) {
489 printf ("ERROR: sent request 5 times without response\nRETURN CODE: %d\n",
490 SEND_REQUEST_FAILED);
491 Quit(SEND_REQUEST_FAILED);
492 }
493
494 }
495
496 free(datapkt->ip);
497 free(datapkt->tcp);
498 free(datapkt);
499
500 if (session.debug == SESSION_DEBUG_HIGH) {
501 printf("Out of SendRequest...\n");
502 }
503 }
504
505 void SendSessionPacket(struct IPPacket *p,
506 uint16 ip_len, uint8 tcp_flags, uint16 ip_optlen, uint16 optlen,
507 uint8 iptos)
508 {
509 if (session.debug == SESSION_DEBUG_HIGH) {
510 printf("In SendSessionPacket...\n");
511 }
512 WriteIPPacket(p,
513 session.src, session.dst, session.sport, session.dport,
514 session.snd_nxt, session.rcv_nxt, tcp_flags,
515 session.rcv_wnd, 0,
516 (ip_len - sizeof(struct IpHeader) - ip_optlen - sizeof(struct TcpHeader) - optlen),
517 ip_optlen, optlen, iptos, 0);
518
519
520 /* Store packet here rather than in rcvData() because otherwise some
521 * ACKs may not be accounted for upon receiving reordered packets */
522
523 StorePacket(p);
524
525 SendPkt(p,
526 ip_len, /* Total IP datagram size */
527 ip_optlen, /* ip options len */
528 optlen); /* tcp options len */
529
530 if (session.debug == SESSION_DEBUG_HIGH) {
531 printf("Out of SendSessionPacket...\n");
532 }
533
534 }
535
536
537 void SendICMPReply(struct IPPacket *p)
538 {
539
540 struct ICMPUnreachableErrorPacket *icmp_pkt;
541 int icmpsz;
542
543 struct IpHeader *ip = p->ip;
544 struct TcpHeader *tcp = p->tcp;
545
546 if (session.debug == SESSION_DEBUG_HIGH) {
547 printf("In SendICMPReply...\n");
548 }
549
550 icmpsz = sizeof(struct ICMPUnreachableErrorPacket);
551 if ((icmp_pkt = (struct ICMPUnreachableErrorPacket *)calloc(icmpsz + 1, 1)) == NULL) {
552 perror("ERROR: no space for ICMP packet:");
553 Quit(ERR_MEM_ALLOC) ;
554 }
555
556 /* Fill IP Header of ICMP packet */
557 bzero((char *)icmp_pkt, sizeof(struct ICMPUnreachableErrorPacket));
558 icmp_pkt->ip.ip_src = ip->ip_dst;
559 icmp_pkt->ip.ip_dst = ip->ip_src;
560 icmp_pkt->ip.ip_p = IPPROTOCOL_ICMP;
561 icmp_pkt->ip.ip_xsum =
562 htons((uint16)(sizeof(struct IcmpHeader) + sizeof(struct IpHeader) + sizeof(struct IpHeader) + 8)); /* pseudo hdr */
563 icmp_pkt->ip.ip_ttl = 60;
564 icmp_pkt->ip.ip_tos = 0x00;
565 icmp_pkt->ip.ip_vhl = 0x45;
566 #ifdef __FreeBSD__
567 icmp_pkt->ip.ip_off = IP_DF;
568 icmp_pkt->ip.ip_len = (uint16)(sizeof(struct ICMPUnreachableErrorPacket));
569 #else /* __FreeBSD__ */
570 icmp_pkt->ip.ip_off = htons(IP_DF);
571 icmp_pkt->ip.ip_len = htons((uint16)((sizeof (struct ICMPUnreachableErrorPacket) + 8 + 1)));
572 #endif /* __FreeBSD__ */
573
574 /* Fill ICMP header */
575 icmp_pkt->icmp.icmp_type = 0x3;
576 icmp_pkt->icmp.icmp_code = 0x4;
577 icmp_pkt->icmp.icmp_xsum = 0;
578 icmp_pkt->icmp.icmp_unused = 0;
579 icmp_pkt->icmp.icmp_mtu = htons(session.mtu);
580
581 /* Fill in ip header of offending packet */
582 icmp_pkt->off_ip.ip_src = ip->ip_src;
583 icmp_pkt->off_ip.ip_dst = ip->ip_dst;
584 icmp_pkt->off_ip.ip_p = ip->ip_p;
585 icmp_pkt->off_ip.ip_xsum = ip->ip_xsum;
586 icmp_pkt->off_ip.ip_ttl = ip->ip_ttl;
587 icmp_pkt->off_ip.ip_tos = ip->ip_tos;
588 icmp_pkt->off_ip.ip_vhl = ip->ip_vhl;
589 icmp_pkt->off_ip.ip_p = ip->ip_p;
590 #ifdef __FreeBSD__
591 icmp_pkt->off_ip.ip_off = ntohs(ip->ip_off);
592 icmp_pkt->off_ip.ip_len = ntohs(ip->ip_len);
593 #else /* __FreeBSD__ */
594 icmp_pkt->off_ip.ip_off = ip->ip_off;
595 icmp_pkt->off_ip.ip_len = ip->ip_len;
596 #endif /* __FreeBSD__ */
597
598 icmp_pkt->tcp_sport = tcp->tcp_sport;
599 icmp_pkt->tcp_dport = tcp->tcp_dport;
600 icmp_pkt->tcp_seqno = (uint32)tcp->tcp_seq;
601
602 icmp_pkt->icmp.icmp_xsum = InetChecksum((uint16 *)(&(icmp_pkt->icmp)), NULL,
603 (uint16)(sizeof(struct IcmpHeader) + sizeof(struct IpHeader) + 8), 0);
604
605 if (session.verbose) {
606 printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
607 printf("TCP Packet: %lu\n", sizeof(struct IPPacket));
608 PrintTcpPacket(p);
609 printf("ICMP Packet: %lu\n", sizeof(struct ICMPUnreachableErrorPacket));
610 PrintICMPUnreachableErrorPacket(icmp_pkt);
611 printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
612 }
613
614 SendICMPPkt(icmp_pkt, sizeof(struct ICMPUnreachableErrorPacket));
615
616 if (session.debug == SESSION_DEBUG_HIGH) {
617 printf("Out of SendICMPReply...\n");
618 }
619
620 }
621
622 void SendPkt(struct IPPacket *p, uint16 ip_len, int ip_optlen,
623 int tcp_optlen) {
624 int nbytes, datalen;
625 struct sockaddr_in sockAddr;
626 char *assembled_pkt;
627
628 if (session.debug == SESSION_DEBUG_HIGH) {
629 printf("In SendPkt...\n");
630 }
631 /* Assemble contiguos packet to be sent */
632 if ((assembled_pkt = (char *)calloc(1, ip_len)) == NULL) {
633 printf("SendPkt: Cannot allocate memory for assembled packet\n");
634 Quit(ERR_MEM_ALLOC);
635 }
636 /* Copy IP Header and options, if any */
637 memcpy((char *)assembled_pkt, (char *)(p->ip),
638 sizeof(struct IpHeader) + ip_optlen);
639
640 /* Copy TCP Header and options, if any */
641 memcpy((char *)(assembled_pkt + sizeof(struct IpHeader) + ip_optlen),
642 (char *)(p->tcp),
643 sizeof(struct TcpHeader) + tcp_optlen);
644
645 /* Copy data bytes, if any */
646 datalen = ip_len - ((sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + tcp_optlen));
647
648 if (datalen > 0) {
649 memcpy((char *)assembled_pkt + sizeof(struct IpHeader) + ip_optlen + sizeof(struct TcpHeader) + tcp_optlen,
650 (char *)p->tcp + sizeof(struct TcpHeader) + tcp_optlen, datalen);
651 }
652
653
654 sockAddr.sin_family = AF_INET;
655 sockAddr.sin_addr.s_addr = session.dst;
656
657 if ((nbytes = (int)sendto(session.socket,
658 (char *)assembled_pkt,
659 ip_len,
660 0,
661 (struct sockaddr *)&sockAddr,
662 sizeof(sockAddr))) < ip_len) {
663 printf("#### WARNING: only sent %d of %d bytes\n", nbytes, ip_len);
664 perror("here");
665
666 }
667
668 session.totSent++;
669
670 free(assembled_pkt);
671
672 if (session.debug == SESSION_DEBUG_HIGH) {
673 printf("Out SendPkt...\n");
674 }
675
676 }
677
678
679
680 void SendICMPPkt(struct ICMPUnreachableErrorPacket *p, uint16 len) {
681
682 ssize_t nbytes;
683 struct sockaddr_in sockAddr;
684
685 sockAddr.sin_family = AF_INET;
686 sockAddr.sin_addr.s_addr = session.dst;
687
688 nbytes = sendto(session.socket, (char *)p, len, 0,
689 (struct sockaddr *)&sockAddr,
690 sizeof(sockAddr));
691
692 if (nbytes < len) {
693 printf("#### WARNING: only sent %zd of %d (errno: %d) bytes\n",
694 nbytes, len, errno);
695 perror("here");
696 }
697
698 session.totSent++ ;
699
700 }
701
702 void rcvData (void (*ackData)(struct IPPacket *p))
703 {
704
705 struct pcap_pkthdr pi;
706 struct IPPacket *p;
707 char *read_packet;
708 double startTime = GetTime () ;
709
710 if (session.debug == SESSION_DEBUG_HIGH) {
711 printf("In rcvData...\n");
712 }
713
714 while (1) {
715
716 if ((GetTime() - startTime) > (MAXDATARETRANSMITS * REXMITDELAY)) {
717 printf ("ERROR: no Data received for %f seconds\nRETURN CODE: %d\n",
718 (MAXDATARETRANSMITS*REXMITDELAY), NO_DATA_RCVD);
719 Quit(NO_DATA_RCVD) ;
720 }
721
722 if ((read_packet = (char *)CaptureGetPacket(&pi)) != NULL) {
723
724 p = (struct IPPacket *)FindHeaderBoundaries(read_packet);
725
726 /*
727 * Packet that we sent?
728 */
729
730 if (INSESSION(p,session.src,session.sport,session.dst,session.dport) &&
731 ((p->tcp->tcp_flags & TCPFLAGS_ACK) || (p->tcp->tcp_flags & TCPFLAGS_FIN)) &&
732 (ntohl(p->tcp->tcp_seq) == session.snd_nxt) &&
733 (ntohl(p->tcp->tcp_ack) <= session.rcv_nxt)) {
734
735 if (session.debug >= SESSION_DEBUG_LOW) {
736 printf("xmit:\n");
737 PrintTcpPacket(p);
738 }
739
740 session.totSeenSent++ ;
741
742 free(p);
743 continue;
744
745 }
746
747 /*
748 * Data that we were expecting?
749 */
750
751 if (INSESSION(p,session.dst,session.dport,session.src,session.sport) &&
752 (p->tcp->tcp_flags & TCPFLAGS_ACK) &&
753 (ntohl(p->tcp->tcp_ack) >= session.snd_una)) {
754
755 if (p->ip->ip_ttl != session.ttl) {
756 printf("#### WARNING: route may have changed (ttl was %d, is %d).\n",
757 session.ttl, p->ip->ip_ttl);
758 session.ttl = p->ip->ip_ttl;
759 }
760
761 if (session.debug >= SESSION_DEBUG_LOW) {
762 printf("rcvd: \n");
763 PrintTcpPacket(p);
764 }
765
766 session.totRcvd++ ;
767 startTime = GetTime () ;
768 StorePacket(p);
769
770 /* if the packet also contains data, receive it, and send an ack if needed */
771 ECNAckData(p);
772
773 free(p);
774 continue ;
775
776 } else {
777
778 free(p);
779
780 }
781 }
782 }
783 }
784
785