*** bonesi.c	Wed Dec  7 22:41:22 2011
--- bonesi.c.f	Thu Dec  8 14:55:06 2011
***************
*** 63,68 ****
--- 63,72 ----
      int referer;
      ///index to useragent in useragents
      int useragent;
+     ///index to url number
+     int url;
+     ///payload offset
+     int pload_offset;
  } Connection;
  
  unsigned long cnt;
***************
*** 91,96 ****
--- 95,102 ----
  int maxPackets = 0;
  int url_flag = 0; //flag to indicate if a url has been specified with parameter -u
  char request[URL_SIZE];
+ unsigned int MTU = 1500;
+ unsigned int fragMode = 0;
  
  pthread_t pcapThread;
  extern char *optarg;
***************
*** 448,453 ****
--- 454,461 ----
      printf("  -d, --device=DEVICE              network listening device (only for tcp/http)\n");
      printf("  -v, --verbose                    print additional debug messages\n");
      printf("  -h, --help                       print this message and exit\n");
+     printf("  -m, --mtu=NUM                    set MTU, default 1500\n");
+     printf("  -f, --frag=NUM                    frag mode 0=IP, 1=TCP, default 0\n");
      printf("\n");
  }
  
***************
*** 473,478 ****
--- 481,488 ----
          {"integer", no_argument, &integer, 1},
          {"verbose", no_argument, 0, 'v'},
          {"help", no_argument, 0, 'h'},
+         {"mtu", no_argument, 0, 'm'},
+         {"frag", no_argument, 0, 'f'},
          {0, 0, 0, 0}
      };
      dstIp = 0;
***************
*** 487,493 ****
      u.host[0] = '\0';
      u.path[0] = '\0';
      u.protocol [0] = '\0';    
!     while ((c = getopt_long(argc, argv, ":b:s:r:p:i:o:c:t:hvu:l:d:",long_options, &option_index)) != -1) {
          switch (c) {
          case 'b':
              useragentfilename = optarg;
--- 497,503 ----
      u.host[0] = '\0';
      u.path[0] = '\0';
      u.protocol [0] = '\0';    
!     while ((c = getopt_long(argc, argv, ":b:s:r:p:i:o:c:t:hvu:l:d:m:f:",long_options, &option_index)) != -1) {
          switch (c) {
          case 'b':
              useragentfilename = optarg;
***************
*** 533,538 ****
--- 543,555 ----
          case 'd':
              device = optarg;
              break;
+         case 'm':
+             MTU = ((abs(atoi(optarg))+7)/8)*8;
+             break;
+         case 'f':
+             fragMode= abs(atoi(optarg));
+             if (fragMode != 1) fragMode = 0;
+             break;
          }
      }
      // -- parse destination address and port --
***************
*** 587,592 ****
--- 604,612 ----
      printf("dstPort:       %d\n", dstPort);
      printf("protocol:      %d\n", proto);
      printf("payloadSize:   %d\n", payloadSize);
+     printf("MTU:   %d\n", MTU);
+     (fragMode > 0) ? printf("fragment mode:          TCP\n")
+             : printf("fragment mode:          IP\n");
      (rate > 0) ? printf("rate:          %d\n", rate)
              : printf("rate:          infinite\n");
      printf("ips:           %s\n", filename);
***************
*** 692,698 ****
      static const u_char *sniffedPacket;
      static const struct iphdr* ip;
      static const struct tcphdr* tcp;
!     
      //printf("achnowledge\n");
      //static size_t x = 0;
      sniffedPacket = pcap_next(pcapHandle, &header);
--- 714,724 ----
      static const u_char *sniffedPacket;
      static const struct iphdr* ip;
      static const struct tcphdr* tcp;
!     unsigned int max_pload_size;
!     int packet_pload_size, total_pload_size;
!     int pload_offset;
!     u_int8_t *p;
! 
      //printf("achnowledge\n");
      //static size_t x = 0;
      sniffedPacket = pcap_next(pcapHandle, &header);
***************
*** 758,766 ****
                  printf("While: url: %d, ref: %d\n", url_number, ref_number);
              }
          }
!         if(urls.size > 1){
!             connections[key].referer = url_number;
!         }
          
          // build the request with url, referer and useragent numbers
          buildRequest(request, url_number, ref_number, useragent_number, urls, useragents);
--- 784,790 ----
                  printf("While: url: %d, ref: %d\n", url_number, ref_number);
              }
          }
! 
          
          // build the request with url, referer and useragent numbers
          buildRequest(request, url_number, ref_number, useragent_number, urls, useragents);
***************
*** 771,789 ****
          
          uint32_t remoteAck = ntohl(tcp->ack_seq);
          uint32_t remoteSeq = ntohl(tcp->seq);
!         libnet_clear_packet(libnetHandle);
!         if(libnet_build_tcp(origSrcPort, dstPort, remoteAck, remoteSeq+1, 
!                 TH_ACK, WINDOW_SIZE, 0, 0, LIBNET_IPV4_H + LIBNET_TCP_H - 20 + strlen(request),
!                 (unsigned char*)request, strlen(request), libnetHandle, 0)==-1) {
!             fprintf(stderr, "Can't build tcp header: %s\n", libnet_geterror(libnetHandle));
!         }
!         buildIp(strlen(request), libnetHandle, 0, sIp);
!         if (libnet_write(libnetHandle) == -1) {
!             fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
          }
      // -- acknowledge every but reset packets and the final ack packet --
!     } else if(! tcp->rst && (connections[key].status == ESTABLISHED || connections[key].status == CONNECTING)) {
          sendAck(libnetHandle, ip, tcp, key);
      // -- connection probably closed -> 'clear' port --
      } else if (tcp->ack) {
          connections[key].status = NOT_CONNECTED; // no connection
--- 795,1008 ----
          
          uint32_t remoteAck = ntohl(tcp->ack_seq);
          uint32_t remoteSeq = ntohl(tcp->seq);
!         max_pload_size = (MTU - LIBNET_IPV4_H - LIBNET_TCP_H);
!         max_pload_size -= (max_pload_size % 8);
!         total_pload_size = strlen(request);
!         if (max_pload_size > total_pload_size) {
!             // -- packet is smaller than MTU --
!             if(urls.size > 1){
!                 connections[key].referer = url_number;
!             }
!             libnet_clear_packet(libnetHandle);
!             if(libnet_build_tcp(origSrcPort, dstPort, remoteAck, remoteSeq+1, 
!                     TH_ACK, WINDOW_SIZE, 0, 0, LIBNET_IPV4_H + LIBNET_TCP_H - 20 + total_pload_size,
!                     (unsigned char*)request, total_pload_size, libnetHandle, 0)==-1) {
!                 fprintf(stderr, "Can't build tcp header: %s\n", libnet_geterror(libnetHandle));
!             }
!             buildIp(total_pload_size, libnetHandle, 0, sIp);
!             if (libnet_write(libnetHandle) == -1) {
!                 fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
!             }
!         } else {
!             // -- fragmentation goes here --
!             if (fragMode == 0) {
!                 // -- using IP fragmentation --
!                 if(urls.size > 1){
!                     connections[key].referer = url_number;
!                 }
! 
!                 int hdr_offset = IP_MF;
!                 u_int16_t ip_id;
!                 u_int32_t pkt_chksum, pbuf_size, pbuf_size2;
!                 libnet_ptag_t tcp_tag, ip_tag;
!                 struct libnet_ipv4_hdr *iph_p;
!                 struct libnet_tcp_hdr *tcph_p;
!                 u_int8_t *packet;
! 
!                 libnet_clear_packet(libnetHandle);
!                 ip_id = (u_int16_t)libnet_get_prand(LIBNET_PR16);
!                 packet_pload_size = max_pload_size;
! 
!                 tcp_tag = libnet_build_tcp(origSrcPort, dstPort, remoteAck, remoteSeq+1, 
!                         TH_ACK, WINDOW_SIZE, 0, 0, LIBNET_IPV4_H + LIBNET_TCP_H - 20 + total_pload_size,
!                         (unsigned char*)request, total_pload_size, libnetHandle, 0);
!                 if(tcp_tag==-1) {
!                     fprintf(stderr, "Can't build tcp header: %s\n", libnet_geterror(libnetHandle));
!                 }
! 
!                 ip_tag = libnet_build_ipv4(
!                             LIBNET_IPV4_H + total_pload_size,
!                             0, /* TOS */
!                             ip_id,
!                             0, /* IP Frag */
!                             (rand() % 253) + 3, /* TTL */
!                             proto,
!                             0, /* checksum */ 
!                             sIp, dstIp,
!                             NULL, /* payload */
!                             0, /* payload size */
!                             libnetHandle, ipTag);
!                 if (ip_tag == -1) {
!                         fprintf(stderr, "Can't build ipv4 header: %s\n", libnet_geterror(libnetHandle));
!                 }
! 
!                 u_int8_t *pkt_buf;
! 
!                 pbuf_size = libnet_getpbuf_size(libnetHandle, ip_tag);
!                 pbuf_size2 = libnet_getpbuf_size(libnetHandle, tcp_tag);
!                 pkt_buf = malloc(pbuf_size+pbuf_size2+total_pload_size);
! 
!                 p = pkt_buf;
!                 packet = libnet_getpbuf(libnetHandle, ip_tag);
!                 memcpy(p, packet, pbuf_size);
!                 p += pbuf_size;
!                 packet = libnet_getpbuf(libnetHandle, tcp_tag);
!                 memcpy(p, packet, pbuf_size2);
!                 p += pbuf_size2;
!                 memcpy(p, request, total_pload_size);
! 
!                 iph_p = (struct libnet_ipv4_hdr *)(pkt_buf);
!                 tcph_p = (struct libnet_tcp_hdr *)(pkt_buf + (iph_p->ip_hl << 2));
!                 libnet_do_checksum(libnetHandle, pkt_buf, IPPROTO_TCP, pbuf_size2+total_pload_size);
! 
!                 libnet_clear_packet(libnetHandle);
! 
!                 p = (u_int8_t *)tcph_p;
!                 total_pload_size += pbuf_size2;
! 
!                 if (libnet_build_ipv4(
!                         LIBNET_IPV4_H + packet_pload_size,
!                         0, /* TOS */
!                         ip_id,
!                         hdr_offset, /* IP Frag */
!                         (rand() % 253) + 3, /* TTL */
!                         proto,
!                         0, /* checksum */ 
!                         sIp, dstIp,
!                         (unsigned char *)p, /* payload */
!                         packet_pload_size, /* payload size */
!                         libnetHandle, ipTag) == -1) {
!                     fprintf(stderr, "Can't build ipv4 header: %s\n", libnet_geterror(libnetHandle));
!                 }
!                 if (libnet_write(libnetHandle) == -1) {
!                     fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
!                 }
!                 pload_offset = packet_pload_size;
!                 libnet_clear_packet(libnetHandle);
!             
!                 max_pload_size = (MTU - LIBNET_IPV4_H);
!                 max_pload_size -= (max_pload_size % 8);
!         
!                 while (total_pload_size > pload_offset) {
!                     if (max_pload_size > (total_pload_size - pload_offset)) {
!                         hdr_offset = pload_offset/8;
!                         packet_pload_size = total_pload_size - pload_offset;
!                     } else {
!                         hdr_offset = IP_MF + pload_offset/8;
!                         packet_pload_size = max_pload_size;
!                     }
!                     if (libnet_build_ipv4(
!                             LIBNET_IPV4_H + packet_pload_size,
!                             0, /* TOS */
!                             ip_id,
!                             hdr_offset, /* IP Frag */
!                             (rand() % 253) + 3, /* TTL */
!                             proto,
!                             0, /* checksum */ 
!                             sIp, dstIp,
!                             (unsigned char*)(p + pload_offset), /* payload */
!                             packet_pload_size, /* payload size */
!                             libnetHandle, ipTag) == -1) {
!                         fprintf(stderr, "Can't build ipv4 header: %s\n", libnet_geterror(libnetHandle));
!                     }
!                     if (libnet_write(libnetHandle) == -1) {
!                         fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
!                     }
!                     pload_offset += packet_pload_size;
!                     libnet_clear_packet(libnetHandle);
!                 }
!                 free(pkt_buf);
!             } else if (fragMode == 1) {
!                 // -- using TCP fragments --
!                 libnet_clear_packet(libnetHandle);
! 
!                 // we send only first packet here, all the others will be sent in Ack handler
!                 if(libnet_build_tcp(origSrcPort, dstPort, remoteAck, remoteSeq+1, 
!                         TH_ACK, WINDOW_SIZE, 0, 0, LIBNET_IPV4_H + LIBNET_TCP_H - 20 + max_pload_size,
!                         (unsigned char*)request, max_pload_size, libnetHandle, 0)==-1) {
!                         fprintf(stderr, "Can't build tcp header: %s\n", libnet_geterror(libnetHandle));
!                 }
!                 buildIp(max_pload_size, libnetHandle, 0, sIp);
!                 if (libnet_write(libnetHandle) == -1) {
!                     fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
!                 }
!                 libnet_clear_packet(libnetHandle);
! 
!                 connections[key].pload_offset = max_pload_size;
!                 connections[key].url = url_number;            }
          }
      // -- acknowledge every but reset packets and the final ack packet --
!     } else if(! tcp->rst && connections[key].status == CONNECTING) {
          sendAck(libnetHandle, ip, tcp, key);
+     } else if(! tcp->rst && connections[key].status == ESTABLISHED) {
+         if (fragMode == 1) {
+             if (tcp->ack) {
+ 
+                 max_pload_size = (MTU - LIBNET_IPV4_H - LIBNET_TCP_H);
+                 max_pload_size -= (max_pload_size % 8);
+ 
+                 uint32_t remoteAck = htonl(tcp->ack_seq);
+                 uint32_t remoteSeq = htonl(tcp->seq);
+ 
+                 int url_number = connections[key].url;
+                 int ref_number = connections[key].referer;
+                 int useragent_number = connections[key].useragent;
+                 buildRequest(request, url_number, ref_number, useragent_number, urls, useragents);
+                 p = (unsigned char *)request;
+                 total_pload_size = strlen(request);
+                 pload_offset = connections[key].pload_offset;
+ 
+                 if ((total_pload_size - pload_offset) == 0) {
+                     sendAck(libnetHandle, ip, tcp, key);
+                     connections[key].status = CLOSED;
+                     if(urls.size > 1){
+                         connections[key].referer = url_number;
+                     }
+                 } else {
+                     if (max_pload_size > (total_pload_size - pload_offset)) {
+                         packet_pload_size = total_pload_size - pload_offset;
+                     } else {
+                         packet_pload_size = max_pload_size;
+                     }
+ 
+                     libnet_clear_packet(libnetHandle);
+                     if(libnet_build_tcp(origSrcPort, dstPort, remoteAck, remoteSeq, 
+                             TH_ACK, WINDOW_SIZE, 0, 0, LIBNET_IPV4_H + LIBNET_TCP_H - 20 + packet_pload_size,
+                             (unsigned char*)(p + pload_offset), packet_pload_size, libnetHandle, 0)==-1) {
+                         fprintf(stderr, "Can't build tcp header _ : %s\n", libnet_geterror(libnetHandle));
+                     }
+                     buildIp(packet_pload_size, libnetHandle, 0, sIp);
+                     if (libnet_write(libnetHandle) == -1) {
+                         fprintf(stderr, "Can't send tcp ack/fin packet: %s\n", libnet_geterror(libnetHandle));
+                     }
+                     libnet_clear_packet(libnetHandle);
+ 
+                     connections[key].pload_offset = pload_offset + packet_pload_size;
+                 }
+             }
+         } else {
+             sendAck(libnetHandle, ip, tcp, key);
+         }
      // -- connection probably closed -> 'clear' port --
      } else if (tcp->ack) {
          connections[key].status = NOT_CONNECTED; // no connection
