Quellcode durchsuchen

fixed missing resource chunk bug and removed extraneous print statements. Rewrote all retransmit code

cecylia vor 7 Jahren
Ursprung
Commit
91d7753ee1
6 geänderte Dateien mit 343 neuen und 86 gelöschten Zeilen
  1. 15 43
      relay_station/crypto.c
  2. 33 7
      relay_station/flow.c
  3. 8 2
      relay_station/flow.h
  4. 36 24
      relay_station/relay.c
  5. 250 9
      relay_station/slitheen-proxy.c
  6. 1 1
      relay_station/slitheen.h

+ 15 - 43
relay_station/crypto.c

@@ -110,11 +110,13 @@ int update_finish_hash(flow *f, uint8_t *hs){
 	
 	EVP_DigestUpdate(f->finish_md_ctx, hs, hs_len+4);
 
+#ifdef DEBUG
 	printf("SLITHEEN: adding to finish mac computation:\n");
 	for(int i=0; i< hs_len + 4; i++){
 		printf("%02x ", hs[i]);
 	}
 	printf("\n");
+#endif
 
 	return 0;
 }
@@ -295,20 +297,20 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 	seq = (incoming) ? f->read_seq : f->write_seq;
 
 	if(f->application && (ds->iv[EVP_GCM_TLS_FIXED_IV_LEN] == 0)){
-		printf("MERP\n");
+		//printf("MERP\n");
 		//fill in rest of iv
 		for(int i = EVP_GCM_TLS_FIXED_IV_LEN; i< ds->cipher->iv_len; i++){
 			ds->iv[i] = p[i- EVP_GCM_TLS_FIXED_IV_LEN];
 		}
 	}
 
-//#ifdef DEBUG
+#ifdef DEBUG
 	printf("\t\tiv: ");
 	for(int i=0; i<ds->cipher->iv_len; i++){
 		printf("%02X ", ds->iv[i]);
 	}
 	printf("\n");
-//#endif
+#endif
 
 	uint8_t buf[13];
 	memcpy(buf, seq, 8);
@@ -330,18 +332,16 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 	if(enc)
 		len += pad;
 
-	printf("len: %d\n", len);
-
 	int32_t n = EVP_Cipher(ds, p, p, len); //decrypt in place
 	if(n<0) return 0;
 
-//#ifdef DEBUG
+#ifdef DEBUG
 	printf("decrypted data:\n");
 	for(int i=0; i< len; i++){
 		printf("%02x ", p[EVP_GCM_TLS_EXPLICIT_IV_LEN+i]);
 	}
 	printf("\n");
-//#endif
+#endif
 
 	if(!enc)
 		p[EVP_GCM_TLS_EXPLICIT_IV_LEN+n] = '\0';
@@ -381,14 +381,6 @@ int verify_finish_hash(flow *f, uint8_t *hs, int32_t incoming){
 	EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
 	EVP_DigestFinal_ex(&ctx, hash, &hash_len);
 
-	if(incoming){
-		printf("expected md hash:\n");
-		for(int i=0; i< hash_len; i++){
-			printf("%02x ", hash[i]);
-		}
-		printf("\n");
-	}
-
 	//now use pseudorandom function
 	uint8_t *output = ecalloc(1, fin_length);
 
@@ -414,34 +406,16 @@ int verify_finish_hash(flow *f, uint8_t *hs, int32_t incoming){
 			NULL, 0, NULL, 0, NULL, 0,
 			extra_input, extra_input_len);
 
-		printf("extra input:\n");
-		for(int i=0; i< extra_input_len; i++){
-			printf("%02x ", extra_input[i]);
-		}
-		printf("\n");
-
 		EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
 		EVP_DigestUpdate(&ctx, extra_input, extra_input_len);
 
 		EVP_DigestFinal_ex(&ctx, hash, &hash_len);
 
-		printf("updated md hash:\n");
-		for(int i=0; i< hash_len; i++){
-			printf("%02x ", hash[i]);
-		}
-		printf("\n");
-
 		PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE,
 			(uint8_t *) TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE ,
 			hash, hash_len, NULL, 0, NULL, 0,
 			output, fin_length);
 
-		printf("modified mac:\n");
-		for(int i=0; i< fin_length; i++){
-			printf("%02x ", output[i]);
-		}
-		printf("\n");
-
 		//replace existing MAC with modified one
 		memcpy(p, output, fin_length);
 
@@ -1176,11 +1150,13 @@ int super_encrypt(client *c, uint8_t *data, uint32_t len){
 	uint8_t output[EVP_MAX_MD_SIZE];
 
 	//first encrypt the header	
+#ifdef DEBUG
 	printf("Plaintext Header:\n");
 	for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 		printf("%02x ", p[i]);
 	}
 	printf("\n");
+#endif
 
 	hdr_ctx = EVP_CIPHER_CTX_new();
 
@@ -1191,11 +1167,13 @@ int super_encrypt(client *c, uint8_t *data, uint32_t len){
 		return 0;
 	}
 
+#ifdef DEBUG
 	printf("Encrypted Header (%d bytes)\n", out_len);
 	for(int i=0; i< out_len; i++){
 		printf("%02x ", p[i]);
 	}
 	printf("\n");
+#endif
 
 	if(len == 0){ //only encrypt header: body contains garbage bytes
 		return 1;
@@ -1214,42 +1192,36 @@ int super_encrypt(client *c, uint8_t *data, uint32_t len){
 	
 	p+= 16;
 
+#ifdef DEBUG
 	printf("Plaintext:\n");
 	for(int i=0; i< len; i++){
 		printf("%02x ", p[i]);
 	}
 	printf("\n");
+#endif
 
 	if(!EVP_CipherUpdate(bdy_ctx, p, &out_len, p, len)){
 		printf("Failed!\n");
 		return 0;
 	}
 
+#ifdef DEBUG
 	printf("Encrypted %d bytes\n", out_len);
 	printf("Encrypted data:\n");
 	for(int i=0; i< out_len; i++){
 		printf("%02x ", p[i]);
 	}
 	printf("\n");
+#endif
 	
 	//MAC at the end
 	EVP_DigestSignUpdate(c->mac_ctx, p, out_len);
 
 	EVP_DigestSignFinal(c->mac_ctx, output, &mac_len);
-	printf("Produced a %zd byte mac:\n", mac_len);
-	for(int i=0; i< mac_len; i++){
-		printf("%02x ", output[i]);
-	}
-	printf("\n");
 
 	p += out_len;
 	memcpy(p, output, 16);
 
-	printf("Copied 16 bytes:\n");
-	for(int i=0; i< 16; i++){
-		printf("%02x ", p[i]);
-	}
-	printf("\n");
 	EVP_CIPHER_CTX_free(bdy_ctx);
 	EVP_CIPHER_CTX_free(hdr_ctx);
 

+ 33 - 7
relay_station/flow.c

@@ -68,8 +68,13 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->src_port = info->tcp_hdr->src_port;
 	new_flow->dst_port = info->tcp_hdr->dst_port;
 
+	new_flow->upstream_app_data = emalloc(sizeof(app_data_queue));
+	new_flow->upstream_app_data->first_packet = NULL;
+	new_flow->downstream_app_data = emalloc(sizeof(app_data_queue));
+	new_flow->downstream_app_data->first_packet = NULL;
+
 	new_flow->upstream_seq_num = ntohl(info->tcp_hdr->sequence_num);
-	new_flow->downstream_seq_num = 0;
+	new_flow->downstream_seq_num = ntohl(info->tcp_hdr->ack_num);
 
 	new_flow->streams=NULL;
 	new_flow->downstream_queue=NULL;
@@ -168,14 +173,14 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			p += RECORD_HEADER_LEN;
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-//#ifdef DEBUG_HS
+#ifdef DEBUG_HS
 				printf("Decrypting finished (%d bytes) (%x:%d -> %x:%d)\n", record_len - RECORD_HEADER_LEN, f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
 				printf("Finished ciphertext:\n");
 				for(int i=0; i< record_len; i++){
 					printf("%02x ", record[i]);
 				}
 				printf("\n");
-//#endif
+#endif
 				int32_t n = encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
 				if(n<=0){
 					printf("Error decrypting finished  (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
@@ -360,11 +365,13 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 
 						int32_t n =  encrypt(f, record+RECORD_HEADER_LEN, record+RECORD_HEADER_LEN, record_len - (RECORD_HEADER_LEN+16), incoming, 0x16, 1);
 
+#ifdef HS_DEBUG
 						printf("New finished ciphertext:\n");
 						for(int i=0; i< record_len; i++){
 							printf("%02x ", record[i]);
 						}
 						printf("\n");
+#endif
 
 						if(n<=0){
 							printf("Error re-encrypting finished  (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port),
@@ -443,11 +450,28 @@ err:
  */
 int remove_flow(flow *f) {
 
+	//Empty application data queues
+	packet *tmp = f->upstream_app_data->first_packet;
+	while(tmp != NULL){
+		f->upstream_app_data->first_packet = tmp->next;
+		free(tmp->data);
+		free(tmp);
+		tmp = f->upstream_app_data->first_packet;
+	}
+
+	tmp = f->downstream_app_data->first_packet;
+	while(tmp != NULL){
+		f->downstream_app_data->first_packet = tmp->next;
+		free(tmp->data);
+		free(tmp);
+		tmp = f->downstream_app_data->first_packet;
+	}
+
+	//Clean up cipher ctxs
 	EVP_MD_CTX_cleanup(f->finish_md_ctx);
 	if(f->finish_md_ctx != NULL){
 		EVP_MD_CTX_destroy(f->finish_md_ctx);
 	}
-	//Clean up cipher ctxs
 	if(f->clnt_read_ctx != NULL){
 		EVP_CIPHER_CTX_cleanup(f->clnt_read_ctx);
 		OPENSSL_free(f->clnt_read_ctx);
@@ -1053,7 +1077,8 @@ int add_packet(flow *f, struct packet_info *info){
 
 						//check to see if last finished message received
 						if(f->application ==1){
-							//TODO: replace finish message hash
+
+#ifdef DEBUG
 							printf("Replacing info->data with finished message (%d bytes).\n", info_len);
 
 							printf("Previous bytes:\n");
@@ -1066,18 +1091,20 @@ int add_packet(flow *f, struct packet_info *info){
 								printf("%02x ", record[record_offset+i]);
 							}
 							printf("\n");
-
 							printf("SLITHEEN: Previous packet contents:\n");
 							for(int i=0; i< info->app_data_len; i++){
 								printf("%02x ", info->app_data[i]);
 							}
 							printf("\n");
+#endif
 							memcpy(info->app_data+info_offset, record+record_offset, info_len);
+#ifdef DEBUG
 							printf("SLITHEEN: Current packet contents:\n");
 							for(int i=0; i< info->app_data_len; i++){
 								printf("%02x ", info->app_data[i]);
 							}
 							printf("\n");
+#endif
 
 							//update TCP checksum
 							tcp_checksum(info);
@@ -1086,7 +1113,6 @@ int add_packet(flow *f, struct packet_info *info){
 
 						if(new_packet != NULL){
 							info_offset += info_len;
-							printf("updating info_offset to %d.\n", info_offset);
 						}
 
 					}

+ 8 - 2
relay_station/flow.h

@@ -41,7 +41,6 @@ typedef struct packet_st{
 	uint16_t len;
 	uint8_t *data;
 	struct packet_st *next;
-	int incoming; //0 for outgoing, 1 for incoming
 } packet;
 
 typedef struct packet_chain_st {
@@ -63,6 +62,10 @@ typedef struct data_queue_st {
 	queue_block *first_block;
 } data_queue;
 
+typedef struct app_data_queue_st {
+	packet *first_packet;
+} app_data_queue;
+
 typedef struct session_st {
 	uint8_t session_id_len;
 	uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
@@ -85,9 +88,12 @@ typedef struct flow_st {
 	struct in_addr src_ip, dst_ip; /* Source (client) and Destination (server) addresses */
 	uint16_t src_port, dst_port;	/* Source and Destination ports */
 
-	uint32_t upstream_seq_num;		/* sequence number */
+	uint32_t upstream_seq_num;		/* sequence number TODO: are these used?*/
 	uint32_t downstream_seq_num;		/* sequence number */
 
+	app_data_queue *upstream_app_data;	/* Saved application-layer data for packet retransmits */
+	app_data_queue *downstream_app_data;
+
 	byte key[16];		/* negotiated key */
 	int state;		/* TLS handshake state */
 	int in_encrypted;		/* indicates whether incoming flow is encrypted */

+ 36 - 24
relay_station/relay.c

@@ -78,9 +78,7 @@ int replace_packet(flow *f, struct packet_info *info){
 			f->downstream_seq_num += info->app_data_len;
 
 		/* if incoming, replace with data from queue */
-		//if(htonl(tcp_hdr->sequence_num) >= f->seq_num){
-			process_downstream(f, offset, info);
-		//}//TODO: need to do something about replaying packets (maybe store previously sent data??
+		process_downstream(f, offset, info);
 
 
 #ifdef DEBUG2
@@ -316,13 +314,13 @@ int read_header(flow *f, struct packet_info *info){
 
 		if(i== 0){
 			//this is the Slitheen ID
-//#ifdef DEBUG
+#ifdef DEBUG
 			printf("Slitheen ID:");
 			for(int j=0; j< output_len; j++){
 				printf("%02x ", p[j]);
 			}
 			printf("\n");
-//#endif
+#endif
 
 			//find stream table or create new one
 
@@ -679,14 +677,14 @@ void *proxy_covert_site(void *data){
 			int32_t bytes_read = read(thread_data->pipefd, buffer, buffer_len);
 
 			if(bytes_read > 0){
-//#ifdef DEBUG
+#ifdef DEBUG
 				printf("PROXY (id %d): read %d bytes from pipe\n", stream_id, bytes_read);
 				for(int i=0; i< bytes_read; i++){
 					printf("%02x ", buffer[i]);
 				}
 				printf("\n");
 				printf("%s\n", buffer);
-//#endif
+#endif
 				bytes_sent = send(handle, buffer,
 						bytes_read, 0);
 				if( bytes_sent <= 0){
@@ -708,13 +706,15 @@ void *proxy_covert_site(void *data){
 			if(bytes_read > 0){
 				uint8_t *new_data = emalloc(bytes_read);
 				memcpy(new_data, buffer, bytes_read);
-//#ifdef DEBUG
+#ifdef DEBUG
 				printf("PROXY (id %d): read %d bytes from censored site\n",stream_id, bytes_read);
 				for(int i=0; i< bytes_read; i++){
 					printf("%02x ", buffer[i]);
 				}
 				printf("\n");
-//#endif
+
+	
+#endif
 
 				//make a new queue block
 				queue_block *new_block = emalloc(sizeof(queue_block));
@@ -915,6 +915,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 					f->outbox = emalloc(record_len+1);
 					f->outbox_len = record_len;
 					f->outbox_offset = 0;
+					printf("FILLED: mid content or mid chunk and could not decrypt\n");
 					fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16)); //for now hard coded length of padding. TODO: fix this
 					//encrypt
 					int32_t n = encrypt(f, f->outbox, f->outbox,
@@ -976,6 +977,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 		printf("\n");
 		printf("Text:\n");
 		printf("%s\n", record_ptr+EVP_GCM_TLS_EXPLICIT_IV_LEN);
+		fflush(stdout);
 #endif
 
 		p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
@@ -1003,11 +1005,16 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						f->replace_response = 0;
 					}
 
+					//check for 200 OK message
+					len_ptr = strstr((const char *) p, "200 OK");
+					if(len_ptr == NULL){
+						f->replace_response = 0;
+					}
+
 					len_ptr = strstr((const char *) p, "Transfer-Encoding");
 					if(len_ptr != NULL){
 						if(!memcmp(len_ptr + 19, "chunked", 7)){
 							//now find end of header
-							//printf("chunked encoding\n");
 							
 							len_ptr = strstr((const char *) p, "\r\n\r\n");
 							if(len_ptr != NULL){
@@ -1021,19 +1028,28 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						if(len_ptr != NULL){
 							len_ptr += 15;
 							f->remaining_response_len = strtol((const char *) len_ptr, NULL, 10);
-							//printf("content-length: %d\n", f->remaining_response_len);
+#ifdef RESOURCE_DEBUG
+							printf("content-length: %d\n", f->remaining_response_len);
+#endif
 							len_ptr = strstr((const char *) p, "\r\n\r\n");
 							if(len_ptr != NULL){
 								f->httpstate = MID_CONTENT;
 								remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
 								p = (uint8_t *) len_ptr + 4;
+#ifdef RESOURCE_DEBUG
+								printf("Remaining record len: %d\n", remaining_record_len);
+#endif
 							} else {
 								remaining_record_len = 0;
-								//printf("Missing end of header. Sending to FORFEIT_REST\n");
+#ifdef RESOURCE_DEBUG
+								printf("Missing end of header. Sending to FORFEIT_REST\n");
+#endif
 								f->httpstate = FORFEIT_REST;
 							}
 						} else {
-							//printf("No content length of transfer encoding field, sending to FORFEIT_REST\n");
+#ifdef RESOURCE_DEBUG
+							printf("No content length of transfer encoding field, sending to FORFEIT_REST\n");
+#endif
 							f->httpstate = FORFEIT_REST;
 							remaining_record_len = 0;
 						}
@@ -1094,7 +1110,6 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						p = (uint8_t *) needle + 2;
 					} else {
 						remaining_record_len = 0;
-						printf("Couldn't find chunk, sending to FORFEIT_REST\n");
 						f->httpstate = FORFEIT_REST;
 					}
 					}
@@ -1177,6 +1192,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 		if((n = encrypt(f, record_ptr, record_ptr,
 						n + EVP_GCM_TLS_EXPLICIT_IV_LEN, 1, record_hdr->type,
 						1)) < 0){
+			printf("UH OH, failed to re-encrypt record\n");
 			if(f->partial_record_header_len > 0){
 				f->partial_record_header_len = 0;
 				free(f->partial_record_header);
@@ -1219,7 +1235,6 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 	data_queue *downstream_queue = f->downstream_queue;
 	client *client_ptr = f->client_ptr;
 
-	printf("Filling with %d bytes\n", length);
 
 	//Fill as much as we can from the censored_queue
 	//Note: need enough for the header and one block of data (16 byte IV, 16 byte
@@ -1230,8 +1245,6 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		int32_t fill_amount = remaining - SLITHEEN_HEADER_LEN - 32;
 		fill_amount -= fill_amount % 16; //rounded down to nearest block size
 
-		printf("Fill amount: %d\n", fill_amount);
-
 		queue_block *first_block = downstream_queue->first_block;
 		int32_t block_length = first_block->len;
 		int32_t offset = first_block->offset;
@@ -1259,10 +1272,12 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		if(block_length > offset + fill_amount){
 			//use part of the block, update offset
 			memcpy(p, first_block->data+offset, fill_amount);
+
 			first_block->offset += fill_amount;
 			p += fill_amount;
 			sl_hdr->len = fill_amount;
 			remaining -= fill_amount;
+
 		} else {
 			//use all of the block and free it
 			memcpy(p, first_block->data+offset, block_length - offset);
@@ -1285,13 +1300,11 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 			p += padding;
 		}
 
-		printf("Filled with %d bytes\n", sl_hdr->len);
 		p += 16;
 		remaining -= 16;
 
 		//fill rest of packet with padding, if needed
 		if(remaining < SLITHEEN_HEADER_LEN){
-			printf("Padding with %d garbage bytes\n", remaining);
 			RAND_bytes(p, remaining);
 			sl_hdr->garbage = htons(remaining);
 			p += remaining;
@@ -1305,7 +1318,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		super_encrypt(client_ptr, encrypted_data, data_len + padding);
 
 
-//#ifdef DEBUG
+#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ",((uint8_t *) sl_hdr)[i]);
@@ -1316,7 +1329,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 			printf("%02x ", ((uint8_t *) sl_hdr)[i+SLITHEEN_HEADER_LEN]);
 		}
 		printf("\n");
-//#endif
+#endif
 	}
 	//now, if we need more data, fill with garbage
 	if(remaining >= SLITHEEN_HEADER_LEN ){
@@ -1329,13 +1342,13 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		sl_hdr->garbage = htons(remaining);
 		sl_hdr->zeros = 0x0000;
 
-//#ifdef DEBUG
+#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
-//#endif
+#endif
 
 		//encrypt slitheen header
 		super_encrypt(client_ptr, p, 0);
@@ -1344,7 +1357,6 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		RAND_bytes(p, remaining);
 	} else if(remaining > 0){
 		//fill with random data
-		printf("UH OH! Less than 16 bytes remaining, had to fill with random\n");
 		RAND_bytes(p, remaining);
 	}
 

+ 250 - 9
relay_station/slitheen-proxy.c

@@ -181,32 +181,273 @@ end:
  */
 void process_packet(struct packet_info *info){
 
-
 	/* Checks to see if this is a possibly tagged hello msg */
 	if ((info->record_hdr != NULL) && (info->record_hdr->type == HS)){ /* This is a TLS handshake */
 		check_handshake(info);
 	}
 
+
 	/* Now if flow is in table, update state */
 	flow *observed;
 	if((observed = check_flow(info)) != NULL){
 	
-		if(observed->application){
-			replace_packet(observed, info);
+#ifdef DEBUG
+		/*Check sequence number and replay application data if necessary*/
+		fprintf(stdout,"Flow: %x:%d > %x:%d (%s)\n", info->ip_hdr->src.s_addr, ntohs(info->tcp_hdr->src_port), info->ip_hdr->dst.s_addr, ntohs(info->tcp_hdr->dst_port), (info->ip_hdr->src.s_addr != observed->src_ip.s_addr)? "incoming":"outgoing");
+		fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
+		fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
+		fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
+#endif
+
+		uint8_t incoming = (info->ip_hdr->src.s_addr != observed->src_ip.s_addr)? 1 : 0;
+		uint32_t seq_num = htonl(info->tcp_hdr->sequence_num);
+		uint32_t expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
+#ifdef DEBUG
+		fprintf(stdout,"Expected sequence number: %u\n", expected_seq);
+#endif
+
+
+		//remove acked data from opposite queue
+		uint32_t ack_num = htonl(info->tcp_hdr->ack_num);
+		packet *saved_data = (incoming)? observed->upstream_app_data->first_packet :
+			observed->downstream_app_data->first_packet;
+		while((saved_data != NULL) &&(ack_num > saved_data->seq_num)){
+			//remove acked data
+			if(ack_num >= saved_data->seq_num + saved_data->len){
+				//remove entire block
+				if(incoming){
+					observed->upstream_app_data->first_packet = saved_data->next;
+				} else {
+					observed->downstream_app_data->first_packet = saved_data->next;
+				}
+
+				free(saved_data->data);
+				free(saved_data);
+				saved_data = (incoming)? observed->upstream_app_data->first_packet :
+					observed->downstream_app_data->first_packet;
+			} else {
+				//remove partial block
+				uint32_t amt_acked = ack_num - saved_data->seq_num;
+				memmove(saved_data->data, saved_data->data+amt_acked, saved_data->len - amt_acked);
+				saved_data->len -= amt_acked;
+				saved_data->seq_num += amt_acked;
+			}
+#ifdef DEBUG
+			if(saved_data != NULL){
+				printf("Currently saved seq_num is now %u\n", saved_data->seq_num);
+			} else {
+				printf("Acked all data, queue is empty\n");
+			}
+#endif
+
+		}
+
+		//fill with retransmit data, process new data
+		uint32_t data_to_fill;
+		uint32_t data_to_process;
+
+		if(seq_num > expected_seq){
+			data_to_process = info->app_data_len;
+			data_to_fill = 0;
+		} else if (seq_num + info->app_data_len > expected_seq){
+			data_to_fill = expected_seq - seq_num;
+			data_to_process = seq_num + info->app_data_len - expected_seq;
 		} else {
+			data_to_fill = info->app_data_len;
+			data_to_process = 0;
+		}
+
+		uint8_t *p = info->app_data;
+
+		if(data_to_fill){ //retransmit
+			packet *saved_data = (incoming)? observed->downstream_app_data->first_packet :
+				observed->upstream_app_data->first_packet;
+
+
+			while(data_to_fill > 0){
+				if(saved_data == NULL){
+					//have already acked all data
+					p += data_to_fill;
+					seq_num += data_to_fill;
+					data_to_fill -= data_to_fill;
+					continue;
+				}
+
+				if(seq_num < saved_data->seq_num){
+					//we are missing a block. Use what was given
+					if(saved_data->seq_num - seq_num > data_to_fill){
+						//skip the rest
+						p += data_to_fill;
+						seq_num += data_to_fill;
+						data_to_fill -= data_to_fill;
+					} else {
+						p += saved_data->seq_num - seq_num;
+						seq_num += saved_data->seq_num - seq_num;
+						data_to_fill -= saved_data->seq_num - seq_num;
+					}
+				} else if ( seq_num == saved_data->seq_num) {
+
+					if(data_to_fill >= saved_data->len){
+						//exhaust this block and move onto next one
+						memcpy(p, saved_data->data, saved_data->len);
+						p += saved_data->len;
+						seq_num += saved_data->len;
+						data_to_fill -= saved_data->len;
+						saved_data = saved_data->next;
+					} else {
+						//fill with partial block
+						memcpy(p, saved_data->data, data_to_fill);
+						p += data_to_fill;
+						seq_num += data_to_fill;
+						data_to_fill -= data_to_fill;
+					}
+				} else { //seq_num > saved_data->seq_num
+					uint32_t offset = seq_num - saved_data->seq_num;
+					
+					if(offset > saved_data->len){
+						saved_data = saved_data->next;
+						offset -= saved_data->len;
+					} else {
+						if(data_to_fill > saved_data->len - offset){
+							memcpy(p, saved_data->data + offset, saved_data->len - offset);
+							p += saved_data->len - offset;
+							seq_num += saved_data->len - offset;
+							data_to_fill -= saved_data->len - offset;
+							saved_data = saved_data->next;
+						} else {
+							memcpy(p, saved_data->data + offset, data_to_fill);
+							p += data_to_fill;
+							seq_num += data_to_fill;
+							data_to_fill -= data_to_fill;
+						}
+					}
+				}
+			}
 
-			/* Pass data to packet chain */
-			add_packet(observed, info);
 		}
+		tcp_checksum(info);//update checksum
+
+		if(data_to_process){
+
+			if(p != info->app_data){
+				printf("UH OH something weird might happen\n");
+			}
+
+			if(observed->application){
+				replace_packet(observed, info);
+			} else {
+
+				/* Pass data to packet chain */
+				add_packet(observed, info);
+			}
+
+			/* Update TCP state */
+			if(info->tcp_hdr->flags & (FIN | RST) ){
+				/* Remove flow from table, connection ended */
+				remove_flow(observed);
+			} else {
+				/* add packet to application data queue */
+
+				//add new app block
+				packet *new_block = ecalloc(1, sizeof(packet));
+				new_block->seq_num = seq_num;
+				new_block->data = ecalloc(1, info->app_data_len);
+				memcpy(new_block->data, info->app_data, info->app_data_len);
+				new_block->len = info->app_data_len;
+				new_block->next = NULL;
+
+				packet *saved_data = (incoming)? observed->downstream_app_data->first_packet :
+					observed->upstream_app_data->first_packet;
+
+				//put app data block in queue
+				if(saved_data == NULL){
+					if(incoming){
+						observed->downstream_app_data->first_packet = new_block;
+						if(new_block->seq_num ==
+								observed->downstream_seq_num){
+							observed->downstream_seq_num += new_block->len;
+#ifdef DEBUG
+							printf("Updated downstream expected seqnum to %u\n",
+									observed->downstream_seq_num );
+#endif
+						}
+					} else {
+						observed->upstream_app_data->first_packet = new_block;
+						if(new_block->seq_num ==
+								observed->upstream_seq_num){
+							observed->upstream_seq_num += new_block->len;
+#ifdef DEBUG
+							printf("Updated upstream expected seqnum to %u\n",
+									observed->upstream_seq_num );
+#endif
+						}
+					}
+
+				}
+				else{
+					uint8_t saved = 0;
+					while(saved_data->next != NULL){
+						if(!saved && (saved_data->next->seq_num > seq_num)){
+							new_block->next = saved_data->next;
+							saved_data->next = new_block;
+							saved = 1;
+						}
+
+						//update expected sequence number
+						if(incoming){
+							if(saved_data->next->seq_num ==
+									observed->downstream_seq_num){
+								observed->downstream_seq_num += saved_data->next->len;
+#ifdef DEBUG
+								printf("Updated downstream expected seqnum to %u\n",
+										observed->downstream_seq_num );
+#endif
+							}
+						} else {//outgoing
+							if(saved_data->next->seq_num ==
+									observed->upstream_seq_num){
+								observed->upstream_seq_num += saved_data->next->len;
+#ifdef DEBUG
+								printf("Updated upstream expected seqnum to %u\n",
+										observed->upstream_seq_num );
+#endif
+							}
+						}
+							
+						saved_data = saved_data->next;
+
+					}
+					if(!saved){
+						saved_data->next = new_block;
+						//update expected sequence number
+						if(incoming){
+							if(saved_data->next->seq_num ==
+									observed->downstream_seq_num){
+								observed->downstream_seq_num += saved_data->next->len;
+#ifdef DEBUG
+								printf("Updated downstream expected seqnum to %u\n",
+										observed->downstream_seq_num );
+#endif
+							}
+						} else {//outgoing
+							if(saved_data->next->seq_num ==
+									observed->upstream_seq_num){
+								observed->upstream_seq_num += saved_data->next->len;
+#ifdef DEBUG
+								printf("Updated upstream expected seqnum to %u\n",
+										observed->upstream_seq_num );
+#endif
+							}
+						}
 
-		/* Update TCP state */
-		if(info->tcp_hdr->flags & (FIN | RST) ){
-			/* Remove flow from table, connection ended */
-			remove_flow(observed);
+					}
+				}
+			}
 		}
 
 	}
 
+
 }
 
 /** This function extracts the ip, tcp, and tls record headers

+ 1 - 1
relay_station/slitheen.h

@@ -71,7 +71,7 @@ struct packet_info {
 	uint32_t size_ip_hdr;
 
 	uint8_t *app_data;
-	uint32_t app_data_len;
+	uint16_t app_data_len;
 };
 
 struct __attribute__((__packed__)) slitheen_header {