/* Kernel AODV v2.1 National Institute of Standards and Technology Luke Klein-Berndt ----------------------------------------------------- Version 2.1 new features: * Much more stable! * Added locks around important areas * Multihop Internet gatewaying now works * Multicast hack added * Many bug fixes! ----------------------------------------------------- Originally based upon MadHoc code. I am not sure how much of it is left anymore, but MadHoc proved to be a great starting point. MadHoc was written by - Fredrik Lilieblad, Oskar Mattsson, Petra Nylund, Dan Ouchterlony and Anders Roxenhag Mail: mad-hoc@flyinglinux.net This software is Open Source under the GNU General Public Licence. */ #include "flood_id_queue.h" /**************************************************** flood_id_queue ---------------------------------------------------- This is used to keep track of messages which are flooded to prevent rebroadcast of messages ****************************************************/ extern struct flood_id_queue_entry *rreq_id_queue; rwlock_t rreq_lock = RW_LOCK_UNLOCKED; /**************************************************** init_flood_id_queue ---------------------------------------------------- Gets the ball rolling! ****************************************************/ int init_flood_id_queue( void ) { rreq_id_queue=NULL; return 0; } void flood_read_lock() { write_lock_bh(&rreq_lock); } void flood_read_unlock() { write_unlock_bh(&rreq_lock); } void flood_write_lock() { write_lock_bh(&rreq_lock); } void flood_write_unlock() { write_unlock_bh(&rreq_lock); } /**************************************************** find_flood_id_queue_entry ---------------------------------------------------- will search the queue for an entry with the matching ID and src_ip ****************************************************/ struct flood_id_queue_entry *find_flood_id_queue_entry(u_int32_t src_ip, u_int32_t flood_id ) { struct flood_id_queue_entry *tmp_entry; /* Working entry in the RREQ list */ u_int64_t curr=getcurrtime(); /*lock table*/ flood_read_lock(); tmp_entry = rreq_id_queue; /* Start at the header */ //go through the whole queue while (tmp_entry!=NULL) { if(tmp_entry->lifetimesrc_ip && flood_id == tmp_entry->flood_id) { /*unlock table*/ flood_read_unlock(); return tmp_entry; } //continue on to the next entry tmp_entry=tmp_entry->next; } /*unlock table*/ flood_read_unlock(); return NULL; } /**************************************************** read_flood_id_proc ---------------------------------------------------- prints out the flood id queue when the proc file is read ****************************************************/ int read_rreq_id_proc(char *buffer, char **buffer_location, off_t offset, int buffer_length,int *eof,void *data) { int len; static char *my_buffer; char temp_buffer[200]; struct flood_id_queue_entry *tmp_entry; char tmp[16]; u_int64_t tmp_time; /*lock table*/ flood_read_lock(); tmp_entry=rreq_id_queue; my_buffer=buffer; sprintf(my_buffer,"\nFlood Id Queue\n---------------------------------\n"); while (tmp_entry!=NULL) { tmp_time=tmp_entry->lifetime-getcurrtime(); strcpy(tmp,inet_ntoa(tmp_entry->dst_ip)); sprintf(temp_buffer,"Src IP: %-16s Dst IP: %-16s Flood ID: %-10u sec/msec: %lu/%lu \n", inet_ntoa(tmp_entry->src_ip),tmp,tmp_entry->flood_id,100,100);//,(unsigned long)(tmp_time) / 1000, (unsigned long)(tmp_time) % 1000); strcat(my_buffer,temp_buffer); tmp_entry=tmp_entry->next; } /*unlock table*/ flood_read_unlock(); sprintf(temp_buffer,"\n---------------------------------\n"); strcat(my_buffer,temp_buffer); *buffer_location=my_buffer; len = strlen(my_buffer); if (len <= offset+buffer_length) *eof = 1; *buffer_location = my_buffer + offset; len -= offset; if (len>buffer_length) len = buffer_length; if (len<0) len = 0; return len; } /**************************************************** print_flood_id_queue ---------------------------------------------------- prints out the flood id queue onto the console screen ****************************************************/ void print_flood_id_queue() { struct flood_id_queue_entry *tmp_entry; char tmp[16]; tmp_entry= rreq_id_queue; printk(KERN_INFO "Flood ID list:\n"); while (tmp_entry!=NULL) { strcpy(tmp,inet_ntoa(tmp_entry->dst_ip)); printk(KERN_INFO "Src IP: %-16s Dst IP: %-16s Flood ID: %-10u \n", inet_ntoa(tmp_entry->src_ip),tmp,tmp_entry->flood_id); tmp_entry=tmp_entry->next; } } /**************************************************** clean_up_flood_id_queue ---------------------------------------------------- Deletes everything in the flood id queue ****************************************************/ void cleanup_flood_id_queue() { struct flood_id_queue_entry *tmp_entry,*dead_entry; int count=0; tmp_entry=rreq_id_queue; print_flood_id_queue(); while (tmp_entry!=NULL) { dead_entry=tmp_entry; tmp_entry=tmp_entry->next; kfree(dead_entry); count++; } rreq_id_queue=NULL; printk(KERN_INFO "Removed %d Flood ID entries! \n",count); printk(KERN_INFO "---------------------------------------------\n"); } /**************************************************** insert_flood_id_queue_entry ---------------------------------------------------- Inserts an entry into the flood ID queue ****************************************************/ int insert_flood_id_queue_entry(u_int32_t ip, u_int32_t dst_ip,u_int32_t id, u_int64_t lt) { struct flood_id_queue_entry *new_entry; /* Pointer to the working entry */ /* Allocate memory for the new entry */ if ((new_entry = (struct flood_id_queue_entry*)kmalloc(sizeof(struct flood_id_queue_entry),GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "AODV: Not enough memory to create Flood ID queue\n"); /* Failed to allocate memory for new Flood ID queue */ return -ENOMEM; } /* Fill in the information in the new entry */ new_entry->src_ip = ip; new_entry->dst_ip = dst_ip; new_entry->flood_id = id; new_entry->lifetime = lt; /*lock table*/ flood_write_lock(); new_entry->next = rreq_id_queue; /* Put the new entry in the list */ rreq_id_queue=new_entry; /*unlock table*/ flood_write_unlock(); return 0; } /**************************************************** check_flood_id_queue_entry_lifetime ---------------------------------------------------- Checks the lifetime of a flood ID queue entry. Returns 0 if it is valid and 1 if it is not! ****************************************************/ int check_flood_id_queue_entry_lifetime(struct flood_id_queue_entry *tmp_entry) { u_int64_t curr_time = getcurrtime(); /* Current time */ /* Check if the entry is valid */ if ((tmp_entry!=NULL )&&(curr_time > tmp_entry->lifetime)) { return 1; } if (tmp_entry==NULL) { printk(KERN_WARNING "AODV: check_flood_id_queue_lifetime passed a NULL\n"); } return 0; } /**************************************************** delete_old_flood_id_queue_entries ---------------------------------------------------- Goes through the flood ID queue and deletes all of the old entries ****************************************************/ int delete_old_flood_id_queue_entries( ) { struct flood_id_queue_entry *tmp_entry,*prev_entry,*dead_entry; u_int64_t curr_time = getcurrtime(); /* Current time */ int c=0; /*lock table*/ flood_write_lock( ); tmp_entry= rreq_id_queue; prev_entry=NULL; //go through the entire queue while(tmp_entry!=NULL) { c++; //if the entry has expired if (curr_time > tmp_entry->lifetime) { //if it is the first entry if(prev_entry==NULL) rreq_id_queue=tmp_entry->next; else prev_entry->next=tmp_entry->next; //kill it! dead_entry=tmp_entry; tmp_entry=tmp_entry->next; kfree(dead_entry); } else { //next entry prev_entry=tmp_entry; tmp_entry=tmp_entry->next; } } /*unlock table*/ flood_write_unlock( ); return c; } /**************************************************** delete_flood_id_queue_entry ---------------------------------------------------- Deletes a flood id queue entry ****************************************************/ int delete_flood_id_queue_entry(struct flood_id_queue_entry *dead_entry ) { struct flood_id_queue_entry *tmp_entry, *prev_entry; tmp_entry= rreq_id_queue; prev_entry=NULL; //since we don't know the previous entry we have to go //through entire list to find it! while (tmp_entry!=NULL) { //if we find the entry we wish to delete if(tmp_entry==dead_entry) { if (prev_entry==NULL) rreq_id_queue=tmp_entry->next; else prev_entry->next=tmp_entry->next; kfree(tmp_entry); return 0; } tmp_entry=tmp_entry->next; } return 1; }