Browse Source

added queue struct, delay processing of misordered packets, fixed bugs

cecylia 7 years ago
parent
commit
88d8f705d2

+ 3 - 0
relay_station/crypto.c

@@ -845,6 +845,7 @@ err:
 	free(pre_master_secret);
 	if(dh_srvr != NULL){
 		DH_free(dh_srvr);
+                f->dh = NULL;
 	}
 	if(dh_clnt != NULL) {
 		DH_free(dh_clnt);
@@ -1504,6 +1505,7 @@ void check_handshake(struct packet_info *info){
 #endif
 
 				flow_ptr->ref_ctr--;
+                                printf("Flow added. %p ref_ctr %d\n", flow_ptr, flow_ptr->ref_ctr);
 
 			} else { /* else update saved flow with new key and random nonce */
 				for(int i=0; i<16; i++){
@@ -1512,6 +1514,7 @@ void check_handshake(struct packet_info *info){
 
 				memcpy(flow_ptr->client_random, hello_rand, SSL3_RANDOM_SIZE);
 				flow_ptr->ref_ctr--;
+                                printf("Flow updated in check_flow. %p ref_ctr %d\n", flow_ptr, flow_ptr->ref_ctr);
 			}
 
 		}

+ 197 - 191
relay_station/flow.c

@@ -30,9 +30,10 @@
 #include "relay.h"
 #include "util.h"
 
+#define DEBUG_HS
+
 static flow_table *table;
 static session_cache *sessions;
-data_queue *downstream_queue;
 client_table *clients;
 
 sem_t flow_table_lock;
@@ -69,6 +70,7 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->dst_port = info->tcp_hdr->dst_port;
 
 	new_flow->ref_ctr = 1;
+        printf("Adding new flow (%p ref ctr %d)\n", new_flow, 1);
 	new_flow->removed = 0;
 
 	new_flow->upstream_app_data = emalloc(sizeof(app_data_queue));
@@ -97,14 +99,16 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->resume_session = 0;
 	new_flow->current_session = NULL;
 
+        new_flow->us_hs_queue = init_queue();
+        new_flow->ds_hs_queue = init_queue();
+
 	new_flow->us_packet_chain = emalloc(sizeof(packet_chain));
-	
 	new_flow->us_packet_chain->expected_seq_num = ntohl(info->tcp_hdr->sequence_num);
 	new_flow->us_packet_chain->record_len = 0;
 	new_flow->us_packet_chain->remaining_record_len = 0;
 	new_flow->us_packet_chain->first_packet = NULL;
-	new_flow->ds_packet_chain = emalloc(sizeof(packet_chain));
 
+	new_flow->ds_packet_chain = emalloc(sizeof(packet_chain));
 	new_flow->ds_packet_chain->expected_seq_num = ntohl(info->tcp_hdr->ack_num);
 	new_flow->ds_packet_chain->record_len = 0;
 	new_flow->ds_packet_chain->remaining_record_len = 0;
@@ -125,7 +129,7 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->replace_response = 0;
 
 	new_flow->ecdh = NULL;
-
+	new_flow->dh = NULL;
 
 	new_flow->finish_md_ctx = EVP_MD_CTX_create();
 	const EVP_MD *md = EVP_sha384();
@@ -384,6 +388,7 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 
 					if((f->in_encrypted == 2) && (f->out_encrypted == 2)){
 						f->application = 1;
+                                                printf("Handshake complete!\n");
 					}
 
 					break;
@@ -461,22 +466,23 @@ err:
  */
 int remove_flow(flow *f) {
 
-	sem_wait(&flow_table_lock);
-	//decrement reference counter
-	f->ref_ctr--;
-	if(f->ref_ctr){ //if there are still references to f, wait to free it
-		printf("Cannot free, still %d reference(s)\n", f->ref_ctr);
-		f->removed = 1; 
-		sem_post(&flow_table_lock);
-		return 0;
-	}
+    sem_wait(&flow_table_lock);
+    //decrement reference counter
+    f->ref_ctr--;
+    if(f->ref_ctr){ //if there are still references to f, wait to free it
+        printf("Cannot free %p, still %d reference(s)\n", f, f->ref_ctr);
+        f->removed = 1; 
+        sem_post(&flow_table_lock);
+        return 0;
+    }
 
-	if(f->removed)
-		printf("Trying again to free\n");
+    if(f->removed)
+        printf("Trying again to free\n");
 
     frame *first_frame = f->us_frame_queue->first_frame;
     while(first_frame != NULL){
-        inject_packet(first_frame->handle, first_frame->header, first_frame->packet);
+        printf("Injecting delayed frame (seq = %u )\n", first_frame->seq_num);
+        inject_packet(first_frame->iargs, first_frame->header, first_frame->packet);
         frame *tmp = first_frame->next;
         free(first_frame);
         first_frame = tmp;
@@ -485,7 +491,8 @@ int remove_flow(flow *f) {
 
     first_frame = f->ds_frame_queue->first_frame;
     while(first_frame != NULL){
-        inject_packet(first_frame->handle, first_frame->header, first_frame->packet);
+        printf("Injecting delayed frame (seq = %u )\n", first_frame->seq_num);
+        inject_packet(first_frame->iargs, first_frame->header, first_frame->packet);
         frame *tmp = first_frame->next;
         free(first_frame);
         first_frame = tmp;
@@ -511,6 +518,19 @@ int remove_flow(flow *f) {
 	}
 	free(f->downstream_app_data);
 
+    if(f->ds_hs_queue != NULL){
+        remove_queue(f->ds_hs_queue);
+    }
+    if(f->us_hs_queue != NULL){
+        remove_queue(f->us_hs_queue);
+    }
+
+    //free partial record headers
+    if(f->partial_record_header_len > 0){
+        f->partial_record_header_len = 0;
+        free(f->partial_record_header);
+    }
+
 	//Clean up cipher ctxs
 	EVP_MD_CTX_cleanup(f->finish_md_ctx);
 	if(f->finish_md_ctx != NULL){
@@ -537,6 +557,10 @@ int remove_flow(flow *f) {
 		EC_KEY_free(f->ecdh);
 	}
 
+    if(f->dh != NULL){
+        DH_free(f->dh);
+    }
+
 	if(f->current_session != NULL && f->resume_session == 1){
 		if( f->current_session->session_ticket != NULL){
 			free(f->current_session->session_ticket);
@@ -675,7 +699,8 @@ flow *check_flow(struct packet_info *info){
 	}
 
 	if(found != NULL){
-		found->ref_ctr++;
+            found->ref_ctr++;
+            printf("Acquiring flow (%p ref ctr %d)\n", found, found->ref_ctr);
 	}
 
 	sem_post(&flow_table_lock);
@@ -1037,198 +1062,179 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
  * expected sequence number
  */
 int add_packet(flow *f, struct packet_info *info){
-	if (info->tcp_hdr == NULL || info->app_data_len <= 0){
-		return 0;
-	}
+    if (info->tcp_hdr == NULL || info->app_data_len <= 0){
+        return 0;
+    }
 
-	packet *new_packet = emalloc(sizeof(packet));
+    packet *new_packet = emalloc(sizeof(packet));
 
-	new_packet->seq_num = ntohl(info->tcp_hdr->sequence_num);
-	new_packet->len = info->app_data_len;
+    new_packet->seq_num = ntohl(info->tcp_hdr->sequence_num);
+    new_packet->len = info->app_data_len;
 
-	uint8_t *packet_data = emalloc(new_packet->len);
-	memcpy(packet_data, info->app_data, new_packet->len);
+    uint8_t *packet_data = emalloc(new_packet->len);
+    memcpy(packet_data, info->app_data, new_packet->len);
 
-	new_packet->data = packet_data;
-	new_packet->next = NULL;
-	uint8_t incoming = (info->ip_hdr->src.s_addr == f->src_ip.s_addr) ? 0 : 1;
-	packet_chain *chain = 
-		(info->ip_hdr->src.s_addr == f->src_ip.s_addr) ? f->us_packet_chain : f->ds_packet_chain;
+    new_packet->data = packet_data;
+    new_packet->next = NULL;
+    uint8_t incoming = (info->ip_hdr->src.s_addr == f->src_ip.s_addr) ? 0 : 1;
+    packet_chain *chain = (incoming) ? f->ds_packet_chain : f->us_packet_chain;
+    queue *packet_queue = (incoming) ? f->ds_hs_queue : f->us_hs_queue;
 
-	if(new_packet->seq_num < chain->expected_seq_num){
-		//see if this packet contains any data we are missing
+    if(new_packet->seq_num < chain->expected_seq_num){
+        //see if this packet contains any data we are missing
         //TODO: figure out how/why this happens and what should follow
-		printf("ERROR: Received replayed packet O.o\n");
+        printf("ERROR: Received replayed packet O.o\n");
 
-		free(new_packet->data);
-		free(new_packet);
+        free(new_packet->data);
+        free(new_packet);
+        remove_flow(f);
+        return 1;
 
-    } else {//new_packet->seq_num >= chain->expected_seq_num
+    }
         
-        if(new_packet->seq_num > chain->expected_seq_num) {
-            printf("ERROR: Received future packet O.o\n");
+    if(new_packet->seq_num > chain->expected_seq_num) {
+        printf("ERROR: Received future packet O.o\n");
+        free(new_packet->data);
+        free(new_packet);
+        remove_flow(f);
+        return 1;
+    }
+    
+    //temporary: see if it's the only packet, if so is new record
+    if(peek(packet_queue, 0) == NULL){
+        if(new_packet->seq_num == chain->expected_seq_num){
+            const struct record_header *record_hdr = (struct record_header *) new_packet->data;
+            chain->record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
+            chain->remaining_record_len = chain->record_len;
         }
-	
-		//Find appropriate place in chain
-        //TODO: this can be simplified; slitheen-proxy code already takes care of it
-		packet *previous = NULL;
-		packet *next = chain->first_packet;
-		while(next != NULL && (next->seq_num <= new_packet->seq_num)){
-			previous = next;
-			next = next->next;
-		}
-
-		//place packet after current
-		if(previous == NULL){
-			//goes at the beginning of chain
-			new_packet->next = chain->first_packet;
-			chain->first_packet = new_packet;
-
-			//if this is a new record, find lengths
-			if(new_packet->seq_num == chain->expected_seq_num){
-				const struct record_header *record_hdr = (struct record_header *) new_packet->data;
-				chain->record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
-				chain->remaining_record_len = chain->record_len;
-			}
-			
-		} else {
-			new_packet->next = next;
-			previous->next = new_packet;
-		}
+    }
 
-		if(new_packet->seq_num == chain->expected_seq_num){
-			chain->expected_seq_num += new_packet->len;
-
-			uint32_t record_offset = 0; //offset into record for updating info with any changes
-			uint32_t info_offset = 0; //offset into info for updating with changes
-			uint32_t info_len = 0; //number of bytes that possibly changed
-
-			//while there is still data left:
-			uint32_t available_data = new_packet->len;
-
-			while(available_data > 0){
-
-				//if full record, give to update_flow
-				if(chain->remaining_record_len <= new_packet->len){
-					chain->remaining_record_len = 0;
-					uint8_t *record = emalloc(chain->record_len);
-					uint32_t record_len = chain->record_len;
-					uint32_t tmp_len = chain->record_len;
-
-					packet *next = chain->first_packet;
-					while(tmp_len > 0){
-						if(tmp_len >= next->len){
-							memcpy(record+chain->record_len - tmp_len, next->data, next->len);
-							if(next == new_packet){
-								new_packet = NULL;
-								record_offset = chain->record_len - tmp_len;
-								info_len = next->len;
-							}
-
-							tmp_len -= next->len;
-							chain->first_packet = next->next;
-							free(next->data);
-							free(next);
-							next = chain->first_packet;
-							available_data = 0;
-						} else {
-							memcpy(record+chain->record_len - tmp_len, next->data, tmp_len);
-							if(next == new_packet){
-								record_offset = chain->record_len - tmp_len;
-								info_len = tmp_len;
-							}
-
-							memmove(next->data, next->data+tmp_len, next->len - tmp_len);
-							next->len -= tmp_len;
-							available_data -= tmp_len;
-							tmp_len = 0;
-							//this is going to be a new record
-							const struct record_header *record_hdr = (struct record_header *) next->data;
-							chain->record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
-							chain->remaining_record_len = chain->record_len;
+    //append packet to queue
+    enqueue(packet_queue, new_packet);
+
+
+    chain->expected_seq_num += new_packet->len;
+
+    uint32_t record_offset = 0; //offset into record for updating info with any changes
+    uint32_t info_offset = 0; //offset into info for updating with changes
+    uint32_t info_len = 0; //number of bytes that possibly changed
+
+    //while there is still data left:
+    uint32_t available_data = new_packet->len;
+
+    while(available_data > 0){
+
+        //if full record, give to update_flow
+        if(chain->remaining_record_len <= new_packet->len){//we have enough to make a record
+            chain->remaining_record_len = 0;
+            uint8_t *record = emalloc(chain->record_len);
+            uint32_t record_len = chain->record_len;
+            uint32_t tmp_len = chain->record_len;
+
+            packet *next = peek(packet_queue, 0);
+            while(tmp_len > 0){
+                if(tmp_len >= next->len){
+                    memcpy(record+chain->record_len - tmp_len, next->data, next->len);
+                    if(next == new_packet){
+                        new_packet = NULL;//TODO: why?
+                        record_offset = chain->record_len - tmp_len;
+                        info_len = next->len;
+                    }
+
+                    tmp_len -= next->len;
+                    //remove packet from queue
+                    next = dequeue(packet_queue);
+                    free(next->data);
+                    free(next);
+                    next = peek(packet_queue, 0); //TODO: Do we need this???
+                    available_data = 0;
+
+                } else { //didn't use up entire packet
+
+                    memcpy(record+chain->record_len - tmp_len, next->data, tmp_len);
+                    if(next == new_packet){//TODO: opposite shouldn't happen?
+                        record_offset = chain->record_len - tmp_len;
+                        info_len = tmp_len;
+                    }
+
+                    memmove(next->data, next->data+tmp_len, next->len - tmp_len);
+                    next->len -= tmp_len;
+                    available_data -= tmp_len;
+                    tmp_len = 0;
+
+                    //Last part of packet is a new record
+                    const struct record_header *record_hdr = (struct record_header *) next->data;
+                    chain->record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
+                    chain->remaining_record_len = chain->record_len;
 #ifdef DEBUG
-							printf("Found record of type %d\n", record_hdr->type);
-							fflush(stdout);
+                    printf("Found record of type %d\n", record_hdr->type);
+                    fflush(stdout);
 #endif
 
-						}
-					}
-					//if handshake is complete, send to relay code
-					
-					if(f->application == 1){
-						//update packet info and send to replace_packet
-						struct packet_info *copy_info = copy_packet_info(info);
-						copy_info->app_data = record;
-						copy_info->app_data_len = record_len;
-						replace_packet(f, copy_info);
-						free(copy_info->app_data);
-						free(copy_info);
-					} else {
-						if(update_flow(f, record, incoming)){
-							free(record);
-							return 1;//error occurred and flow was removed
-						}
-
-						//check to see if server finished message received
-						if(f->in_encrypted ==2){
+                }
+            }
+
+            //if handshake is complete, send to relay code
+            if(f->application == 1){
+                //update packet info and send to replace_packet
+                struct packet_info *copy_info = copy_packet_info(info);
+                copy_info->app_data = record;
+                copy_info->app_data_len = record_len;
+                replace_packet(f, copy_info);
+                free(copy_info->app_data);
+                free(copy_info);
+            } else {
+                if(update_flow(f, record, incoming)){
+                    free(record);
+                    return 1;//error occurred and flow was removed
+                }
+
+                if(f->in_encrypted ==2){
+                    //if server finished message was received, copy changes back to packet
 
 #ifdef DEBUG
-							printf("Replacing info->data with finished message (%d bytes).\n", info_len);
-
-							printf("Previous bytes:\n");
-							for(int i=0; i<info_len; i++){
-								printf("%02x ", info->app_data[info_offset+i]);
-							}
-							printf("\n");
-							printf("New bytes:\n");
-							for(int i=0; i<info_len; i++){
-								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");
+                    printf("Replacing info->data with finished message (%d bytes).\n", info_len);
+
+                    printf("Previous bytes:\n");
+                    for(int i=0; i<info_len; i++){
+                        printf("%02x ", info->app_data[info_offset+i]);
+                    }
+                    printf("\n");
+                    printf("New bytes:\n");
+                    for(int i=0; i<info_len; i++){
+                        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);
+                    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");
+                    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);
+                }
+                free(record);
+
+                if(new_packet != NULL){
+                    info_offset += info_len;
+                }
+
+            }
+        } else {//can't make a full record yet
+            chain->remaining_record_len -= new_packet->len;
+            available_data = 0;
+        }
+    } //exhausted new packet len
 
-							//update TCP checksum
-							tcp_checksum(info);
-						}
-						free(record);
-
-						if(new_packet != NULL){
-							info_offset += info_len;
-						}
-
-					}
-				} else {
-					chain->remaining_record_len -= new_packet->len;
-					//see if this packet filled a hole
-					new_packet = new_packet->next;
-					if(new_packet != NULL &&
-							new_packet->seq_num == chain->expected_seq_num){
-						available_data = new_packet->len;
-						chain->expected_seq_num += new_packet->len;
-					} else {
-						available_data = 0;
-					}
-				}
-			}
-		
-		} else {//
-			//add to end of packet_chain
-			printf("Missing packet (expected %d, received %d)\n", chain->expected_seq_num, new_packet->seq_num);
-		}
-	}
-	return 0;
+    return 0;
 
 }

+ 7 - 4
relay_station/flow.h

@@ -7,6 +7,7 @@
 #include <openssl/ssl.h>
 #include "ptwist.h"
 #include "slitheen.h"
+#include "util.h"
 
 #define MAX_FLOWS 10
 #define SLITHEEN_ID_LEN 28
@@ -70,8 +71,8 @@ typedef struct app_data_queue_st {
 typedef struct frame_st {
     uint8_t *packet;
     const struct pcap_pkthdr *header;
-    pcap_t *handle;
-	uint32_t seq_num;
+    struct inject_args *iargs;
+    uint32_t seq_num;
     struct frame_st *next;
 } frame;
 
@@ -120,12 +121,14 @@ typedef struct flow_st {
 	int application; /* indicates handshake is complete */
 	int stall; /* indicates the Finished message is expected and relay station should stall */
 	int resume_session;
-	stream_table *streams;
-	data_queue *downstream_queue;
+	stream_table *streams; //TODO delete (reference client)
+	data_queue *downstream_queue; //TODO: delete (reference client)
 	client *client_ptr;
 
 	packet_chain *ds_packet_chain;
 	packet_chain *us_packet_chain;
+        queue *ds_hs_queue;
+        queue *us_hs_queue;
 	sem_t packet_chain_lock;
 
 	queue_block *upstream_queue;

+ 22 - 18
relay_station/relay.c

@@ -80,7 +80,6 @@ int replace_packet(flow *f, struct packet_info *info){
 		/* if incoming, replace with data from queue */
 		process_downstream(f, offset, info);
 
-
 #ifdef DEBUG2
 		uint8_t *p = (uint8_t *) info->tcp_hdr;
 		fprintf(stdout, "ip hdr length: %d\n", htons(info->ip_hdr->len));
@@ -914,23 +913,28 @@ 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;
-					fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16));
-
-					//encrypt (not a re-encryption)
-					int32_t n = encrypt(f, f->outbox, f->outbox,
-									record_len - 16, 1,
-									record_hdr->type, 1, 0);
-					if(n < 0){
-						fprintf(stdout,"outbox encryption failed\n");
-					} else {
-						
-						memcpy(p, f->outbox, remaining_packet_len);
-						changed = 1;
-						increment_ctr = 0;
-						f->outbox_len -= remaining_packet_len;
-						f->outbox_offset += remaining_packet_len;
-					}
-
+					if(!fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16))){
+
+                                            //encrypt (not a re-encryption)
+                                            int32_t n = encrypt(f, f->outbox, f->outbox,
+                                                                            record_len - 16, 1,
+                                                                            record_hdr->type, 1, 0);
+                                            if(n < 0){
+                                                    fprintf(stdout,"outbox encryption failed\n");
+                                            } else {
+                                                    
+                                                    memcpy(p, f->outbox, remaining_packet_len);
+                                                    changed = 1;
+                                                    increment_ctr = 0;
+                                                    f->outbox_len -= remaining_packet_len;
+                                                    f->outbox_offset += remaining_packet_len;
+                                            }
+                                        } else { //failed to fill with downstream data, client unknown
+                                            free(f->outbox);
+                                            f->outbox = NULL;
+                                            f->outbox_len = 0;
+                                            f->replace_response = 0;
+                                        }
 				}
 
 				if(f->remaining_response_len == 0){

+ 116 - 92
relay_station/slitheen-proxy.c

@@ -12,6 +12,8 @@
 #include <unistd.h>
 #include <string.h>
 #include <pthread.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
 #include <openssl/ssl.h>
 
 #include "util.h"
@@ -79,6 +81,7 @@ void *sniff_packets(void *args){
 	pcap_t *wr_handle;
 	char rd_errbuf[BUFSIZ];
 	char wr_errbuf[BUFSIZ];
+        uint8_t MAC[ETHER_ADDR_LEN];
 	bpf_u_int32 mask;
 	bpf_u_int32 net;
 
@@ -87,12 +90,20 @@ void *sniff_packets(void *args){
 	readdev = arg_st->readdev;
 	writedev = arg_st->writedev;
 
+        //Find MAC address of each interface
+        struct ifreq ifr;
+        int s = socket(AF_INET, SOCK_DGRAM, 0);
+        strcpy(ifr.ifr_name, writedev);
+        ioctl(s, SIOCGIFHWADDR, &ifr);
+        memcpy(MAC, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+        close(s);
+
 	if (pcap_lookupnet(readdev, &net, &mask, rd_errbuf) == -1){
 		fprintf(stderr, "Can't get netmask for device %s\n", readdev);
 		exit(2);
 	}
 
-	rd_handle = pcap_open_live(readdev, BUFSIZ, 1, 0, rd_errbuf);
+	rd_handle = pcap_open_live(readdev, BUFSIZ, 0, 0, rd_errbuf);
 	if (rd_handle == NULL){
 		fprintf(stderr, "Couldn't open device %s: %s\n", readdev, rd_errbuf);
 	}
@@ -107,13 +118,18 @@ void *sniff_packets(void *args){
 		exit(2);
 	}
 
-	wr_handle = pcap_open_live(writedev, BUFSIZ, 1, 0, wr_errbuf);
+	wr_handle = pcap_open_live(writedev, BUFSIZ, 0, 0, wr_errbuf);
 	if (wr_handle == NULL){
 		fprintf(stderr, "Couldn't open device %s: %s\n", writedev, wr_errbuf);
 	}
 
+        struct inject_args iargs;
+        iargs.mac_addr = MAC;
+        iargs.write_dev = wr_handle;
+
+
 	/*callback function*/
-	pcap_loop(rd_handle, -1, got_packet, (unsigned char *) wr_handle);
+	pcap_loop(rd_handle, -1, got_packet, (unsigned char *) &iargs);
 
 	/*Sniff a packet*/
 	pcap_close(rd_handle);
@@ -125,22 +141,27 @@ void *sniff_packets(void *args){
 /*
  * Injects a packet back out the opposite interface
  */
-void inject_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet){
+void inject_packet(struct inject_args *iargs, const struct pcap_pkthdr *header, uint8_t *packet){
+    pcap_t *handle = iargs->write_dev;
 
+    //write back out to the MAC ADDR it came in on
+    memmove(packet, packet+ETHER_ADDR_LEN, ETHER_ADDR_LEN);
+    memcpy(packet+ETHER_ADDR_LEN, iargs->mac_addr, ETHER_ADDR_LEN);
 
-	if((pcap_inject(handle, packet, header->len)) < 0 ){
-		fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
-	}
+    if((pcap_inject(handle, packet, header->len)) < 0 ){
+        fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
+        printf("Length: %d\n", header->len);
+    }
 
 #ifdef DEBUG
-	fprintf(stderr, "injected the following packet:\n");
-	for(int i=0; i< header->len; i++){
-		fprintf(stderr, "%02x ", packet[i]);
-	}
-	fprintf(stderr, "\n");
+    fprintf(stderr, "injected the following packet:\n");
+    for(int i=0; i< header->len; i++){
+        fprintf(stderr, "%02x ", packet[i]);
+    }
+    fprintf(stderr, "\n");
 
 #endif
-	free(packet);
+    free(packet);
 }
 
 /**
@@ -150,15 +171,12 @@ void inject_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *pa
  *
  */
 void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet){
-	pcap_t *handle = (pcap_t *) args;
-
-	uint8_t *tmp_packet = emalloc(header->len);
-	memcpy(tmp_packet, packet, header->len);
-
-	process_packet(handle, header, tmp_packet);
-
+    struct inject_args *iargs = (struct inject_args *) args;
 
+    uint8_t *tmp_packet = emalloc(header->len);
+    memcpy(tmp_packet, packet, header->len);
 
+    process_packet(iargs, header, tmp_packet);
 }
 
 /* This function receives a full ip packet and then:
@@ -166,73 +184,76 @@ void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *
  * 	2) adds the packet to the flow's data chain
  * 	3) updates the flow's state
  */
-void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet){
+void process_packet(struct inject_args *iargs, const struct pcap_pkthdr *header, uint8_t *packet){
 
-	struct packet_info *info = emalloc(sizeof(struct packet_info));
-	extract_packet_headers(packet, info);
+    struct packet_info *info = emalloc(sizeof(struct packet_info));
+    extract_packet_headers(packet, info);
 
     //Ignore non-TCP packets (shouldn't actually get any)
-	if((info->ip_hdr == NULL) || (info->tcp_hdr == NULL))
-		goto err;
-
-	/* 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);
-	}
+    if((info->ip_hdr == NULL) || (info->tcp_hdr == NULL)){
+        free(info);
+        free(packet);
+        return;
+    }
 
+    /* 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){
-	
+    /* Now if flow is in table, update state */
+    flow *observed;
+    if((observed = check_flow(info)) != NULL){
+    
 #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));
+        /*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;
+        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);
+        fprintf(stdout,"Expected sequence number: %u\n", expected_seq);
 #endif
 
-		/* Remove acknowledged data from queue after TCP window is exceeded */
+        /* Remove acknowledged data from queue after TCP window is exceeded */
         update_window_expiration(observed, info);
 
-		/* 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;
-		}
+        /* 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;
+        uint8_t *p = info->app_data;
 
-		if(data_to_fill){ //retransmit
+        if(data_to_fill){ //retransmit
+            printf("Retransmiting data (%u:%u)\n", seq_num, seq_num + info->app_data_len);
             retransmit(observed, info, data_to_fill);
-		}
+        }
 
         p += data_to_fill;
 
-		if(data_to_process){
+        if(data_to_process){
 
-			if(p != info->app_data){
-				printf("UH OH something weird might happen\n");
-			}
+            if(p != info->app_data){
+                printf("UH OH something weird might happen\n");
+            }
 
-			if(observed->application){
+            if(observed->application){
                 if(seq_num > expected_seq){
                     //For now, enters into FORFEIT state
                     //TODO: change upstream behaviour to try to mask slitheen hdr
@@ -241,21 +262,20 @@ void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *p
                     goto err;
                 }
 
-				replace_packet(observed, info);
-			} else {
+                replace_packet(observed, info);
+            } else {
                 //We're still in the TLS handshake; hold packets misordered packets
 
                 if(seq_num > expected_seq){
                     //Delay and process later
                     frame *new_frame = ecalloc(1, sizeof(frame));
-                    new_frame->handle = handle;
+                    new_frame->iargs = iargs;
                     new_frame->packet = packet;
                     new_frame->header = header;
                     new_frame->seq_num = seq_num;
                     new_frame->next = NULL;
                     frame_queue *queue = (incoming) ? observed->ds_frame_queue : observed->us_frame_queue;
-
-                    printf("Used frame queue\n");
+                    printf("Delay processing of frame (seq = %u )\n", seq_num);
 
                     //add to end of list
                     if(queue->first_frame == NULL){
@@ -270,35 +290,37 @@ void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *p
 
                     free(info);
                     observed->ref_ctr--;
+                    printf("Misordered packet. %p ref_ctr %d\n", observed, observed->ref_ctr);
+
                     return; //TODO: fix terrible spaghetti returns
                 }
 
-				/* Pass data to packet chain */
-				if(observed->stall){
+                /* Pass data to packet chain */
+                if(observed->stall){
 
-				}
-				if(add_packet(observed, info)){//removed_flow
-					goto err;
-				}
-			}
+                }
+                if(add_packet(observed, info)){//removed_flow
+                    goto err;
+                }
+            }
 
-			/* Update TCP state */
-			if(info->tcp_hdr->flags & (FIN | RST) ){
-				/* Remove flow from table, connection ended */
-				remove_flow(observed);
-				goto err;
-			}
+            /* Update TCP state */
+            if(info->tcp_hdr->flags & (FIN | RST) ){
+                /* Remove flow from table, connection ended */
+                remove_flow(observed);
+                goto err;
+            }
 
-			/* add packet to application data queue */
+            /* add packet to application data queue */
             save_packet(observed, info);
-		}
+        }
         
 
         /*process and release held frames with current sequence numbers*/
         frame_queue *queue = (incoming) ? observed->ds_frame_queue : observed->us_frame_queue;
         frame *first = queue->first_frame;
         frame *prev = queue->first_frame;
-		expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
+        expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
 
         while (first != NULL){
 
@@ -309,7 +331,8 @@ void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *p
                 } else {
                     prev->next = first->next;
                 }
-                process_packet(handle, first->header, first->packet);
+                printf("Now processing frame (seq = %u )\n", first->seq_num);
+                process_packet(iargs, first->header, first->packet);
                 free(first);
                 first = queue->first_frame;
                 prev = queue->first_frame;
@@ -319,13 +342,14 @@ void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *p
             }
         }
 
-		observed->ref_ctr--;
-	}
+        observed->ref_ctr--;
+        printf("Finished processing packet. %p ref_ctr %d\n", observed, observed->ref_ctr);
+    }
 
 err:
-	free(info);//Note: don't free this while a thread is using it
+    free(info);//Note: don't free this while a thread is using it
 
-    inject_packet(handle, header, packet);
+    inject_packet(iargs, header, packet);
 
     return;
 

+ 7 - 2
relay_station/slitheen.h

@@ -100,11 +100,16 @@ struct sniff_args {
 	char *writedev;
 };
 
+struct inject_args {
+    uint8_t *mac_addr;
+    pcap_t *write_dev;
+};
+
 void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet);
 void *sniff_packets(void *);
-void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet);
+void process_packet(struct inject_args *iargs, const struct pcap_pkthdr *header, uint8_t *packet);
 void extract_packet_headers(uint8_t *packet, struct packet_info *info);
 struct packet_info *copy_packet_info(struct packet_info *src_info);
-void inject_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet);
+void inject_packet(struct inject_args *iargs, const struct pcap_pkthdr *header, uint8_t *packet);
 
 #endif /* _SLITHEEN_H_ */

+ 111 - 14
relay_station/util.c

@@ -1,7 +1,8 @@
 /* Name: util.c
  * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
  *
- * This file contains helper functions and macros
+ * This file contains safe wrappers for common functions and implementations of
+ * data structures
  */
 
 
@@ -12,22 +13,118 @@
 
 //malloc macro that exits on error
 void *emalloc(size_t size){
-	void *ptr = malloc(size);
-	if (ptr == NULL){
-		fprintf(stderr, "Memory failure. Exiting...\n");
-		exit(1);
-	}
-	
-	return ptr;
+    void *ptr = malloc(size);
+    if (ptr == NULL){
+        fprintf(stderr, "Memory failure. Exiting...\n");
+	exit(1);
+    }
+
+    return ptr;
 }
 
 //calloc macro that exits on error
 void *ecalloc(size_t nmemb, size_t size){
-	void *ptr = calloc(nmemb, size);
-	if(ptr == NULL){
-		fprintf(stderr, "Memory failure. Exiting...\n");
-		exit(1);
-	}
+    void *ptr = calloc(nmemb, size);
+    if(ptr == NULL){
+        fprintf(stderr, "Memory failure. Exiting...\n");
+        exit(1);
+    }
+
+    return ptr;
+}
+
+/**
+ * Initializes a generic queue structure
+ */
+
+queue *init_queue(){
+    queue *new_queue = emalloc(sizeof(queue));
+
+    new_queue->first = NULL;
+    new_queue->last = NULL;
+
+    return new_queue;
+}
+
+/**
+ * Function to append a struct to the end of a list
+ */
+void enqueue(queue *list, void *data){
+    element *new_elem = emalloc(sizeof(element));
+    new_elem->data = data;
+    new_elem->next = NULL;
+
+    if(list->first == NULL){
+        list->first = new_elem;
+        list->last = new_elem;
+    } else {
+        list->last->next = new_elem;
+        list->last = new_elem;
+    }
+
+}
+
+/**
+ * Removes and returns the first element from the front of the list. Returns NULL
+ * if list is empty
+ */
+void *dequeue(queue *list){
+
+    if(list->first == NULL){
+        return NULL;
+    }
 
-	return ptr;
+    void *data = list->first->data;
+    element *target =list->first;
+    
+    list->first = target->next;
+
+    free(target);
+
+    return data;
 }
+
+/**
+ * Returns the nth element of the queue (as provided)
+ *
+ * An input of -1 peeks at last element
+ *
+ * Returns data on success, NULL on failure
+ */
+
+void *peek(queue *list, int32_t n){
+    
+    int32_t i;
+    element *target = list->first;
+
+    if(n == -1){
+        target = list->last;
+    }
+
+    for(i=0; (i< n) && (target == NULL); i++){
+        target = target->next;
+    }
+
+    if(target == NULL){
+        return NULL;
+    } else {
+        return target->data;
+    }
+
+}
+
+/**
+ * Removes (frees the data in) all elements from the list and then frees the list itself
+ */
+void remove_queue(queue *list){
+
+    void *data = dequeue(list);
+    while(data != NULL){
+        free(data);
+        data = dequeue(list);
+    
+    }
+    
+    free(list);
+}
+

+ 19 - 1
relay_station/util.h

@@ -1,14 +1,32 @@
 /* until.h by Cecylia Bocovich <cbocovic@uwaterloo.ca>
  *
- * Macros and wrapper functions
+ * Wrapper functions and data structures
  */
 
 #ifndef _UTIL_H_
 #define _UTIL_H_
 
 #include <stddef.h>
+#include <stdint.h>
 
 void *emalloc(size_t size);
 void *ecalloc(size_t nmemb, size_t size);
 
+//Standard queue data structure
+typedef struct element_st {
+    void *data;
+    struct element_st *next;
+} element;
+
+typedef struct queue_st {
+    element *first;
+    element *last;
+} queue;
+
+queue *init_queue();
+void enqueue(queue *list, void *data);
+void *dequeue(queue *list);
+void *peek(queue *list, int32_t n);
+void remove_queue(queue *list);
+
 #endif /*_UTIL_H_*/