/* 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 "interface_list.h" /**************************************************** interface_list ---------------------------------------------------- This is a list of the interfaces available on the computer ****************************************************/ struct interface_list_entry *interface_list; extern struct route_table_entry *g_my_entry; extern u_int32_t g_my_ip; extern u_int32_t g_broadcast_ip; /**************************************************** start_HELLO ---------------------------------------------------- Starts sending hello messages out for a given IP address ****************************************************/ int start_HELLO (u_int32_t ip) { struct rrep *tmp_rrep; u_int32_t random_number; //creates the RREP you wish to send out as the hello message if ((tmp_rrep = kmalloc(sizeof(struct rrep),GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "AODV: Not enough memory to create a Hello Message\n"); return -ENOMEM; } //fillin the RREP tmp_rrep->dst_ip=ip; tmp_rrep->src_ip=ip; tmp_rrep->hop_count=0; tmp_rrep->lifetime=htonl (ALLOWED_HELLO_LOSS * HELLO_INTERVAL); tmp_rrep->dst_seq=0; tmp_rrep->type=2; tmp_rrep->r=0; tmp_rrep->reserved1=0; tmp_rrep->reserved2=0; tmp_rrep->prefix_sz=0; tmp_rrep->a=0; //Insert it into the timer queue! get_random_bytes(&random_number,sizeof(u_int32_t)); random_number=(43*random_number)%HELLO_INTERVAL; insert_timer_queue_entry(getcurrtime() + random_number, tmp_rrep, sizeof(struct rrep), tmp_rrep->dst_ip,0,1,EVENT_HELLO); update_timer_queue(); return 0; } /**************************************************** init_interface_list ---------------------------------------------------- Discover the available interfaces and add them to the list ****************************************************/ int init_interface_list() { struct route_table_entry *tmp_route; struct interface_list_entry *new_entry=NULL; struct net_device *dev; struct in_device *tmp_indev; struct in_device *in_dev; int error; //dev_base is a kernel variable pointing to a list of //all the available netdevices and is maintained //by the kernel dev= dev_base; interface_list=NULL; //look at all the devices read_lock(&dev_base_lock); read_lock(&inetdev_lock); for (dev=dev_base; dev; dev=dev->next) { if ((in_dev=__in_dev_get(dev)) == NULL) continue; read_lock(&in_dev->lock); for_primary_ifa(in_dev) { //we don't want to include the loopback device //or any device which doesn't have a completed //ip section if ((strcmp(dev->name,g_block_dev)!=0) && ((strcmp(g_aodv_dev,"")==0) || (strcmp(dev->name,g_aodv_dev)==0))) { tmp_route=create_route_table_entry(); tmp_route->dst_ip = ifa->ifa_address; printk(KERN_INFO "INTERFACE LIST: Adding interface: %s IP: %s\n",dev->name, inet_ntoa(ifa->ifa_address)); //fill in the info for the route tmp_route->self_route=1; tmp_route->dst_seq = 1; tmp_route->old_dst_seq=0; tmp_route->rreq_id = 1; tmp_route->hop_count = 0; tmp_route->next_hop = tmp_route->dst_ip; tmp_route->lifetime = -1; tmp_route->route_valid = 1; tmp_route->route_seq_valid = 1; tmp_route->precursors=NULL; tmp_route->dev=dev; //save the entry as being our own... so the last dev read in //becomes our default dev. g_my_entry = tmp_route; g_my_ip=g_my_entry->dst_ip; if ((strcmp(dev->name,"lo")!=0) || USE_LO) { if ((new_entry = kmalloc(sizeof(struct interface_list_entry),GFP_ATOMIC)) == NULL) { /* Couldn't create a new entry in the routing table */ printk(KERN_WARNING "AODV: Not enough memory to create Route Table Entry\n"); return -ENOMEM; } //fill in the info on the dev new_entry->ip=tmp_route->dst_ip; new_entry->route_entry=tmp_route; new_entry->next=interface_list; new_entry->dev=dev; new_entry->last_hello=getcurrtime(); new_entry->last_broadcast=0; interface_list=new_entry; strncpy(new_entry->name,dev->name,IFNAMSIZ); //start sending out a hello message for this dev start_HELLO(new_entry->ip); //insert a broadcast address into the kernel routing table using this dev //create the socket... set it to type datagram error = sock_create(PF_INET,SOCK_DGRAM,0,&(new_entry->sock)); if (error<0) { kfree(new_entry); printk(KERN_ERR "Error during creation of socket; terminating, %d\n",error); return error; } init_sock(new_entry->sock,new_entry->ip,dev->name); insert_kernel_route_entry(tmp_route->dst_ip,tmp_route->dst_ip,new_entry->name); } } } endfor_ifa(in_dev); read_unlock(&in_dev->lock); } read_unlock(&inetdev_lock); read_unlock(&dev_base_lock); return 0; } struct interface_list_entry *find_first_interface_entry() { return interface_list; } /**************************************************** find_dev_ip ---------------------------------------------------- It will find the IP for a dev ****************************************************/ u_int32_t find_dev_ip(struct net_device *dev) { struct in_device *tmp_indev; //make sure we get a valid DEV if (dev==NULL) { printk (KERN_WARNING "AODV: FIND_DEV_IP gotta NULL DEV! "); return -EFAULT; } //make sure that dev has an IP section if (dev->ip_ptr==NULL) { printk (KERN_WARNING "AODV: FIND_DEV_IP gotta NULL ip_ptr!! "); return -EFAULT; } //find that ip! tmp_indev=(struct in_device *) dev->ip_ptr; if (tmp_indev && (tmp_indev->ifa_list!=NULL)) return (tmp_indev->ifa_list->ifa_address); else return 0; } /**************************************************** find_interface_by_dev ---------------------------------------------------- Finds an interface by matching up the dev to the dev in the interface list ****************************************************/ struct interface_list_entry *find_interface_by_dev(struct net_device *dev) { struct interface_list_entry *tmp_entry=interface_list; struct in_device *tmp_indev; u_int32_t tmp_ip; //Make sure the dev is legit if (dev==NULL) { printk (KERN_WARNING "AODV: FIND_INTERFACE_BY_DEV gotta NULL DEV! \n"); return NULL; } //make sure it has a legit ip section if (dev->ip_ptr==NULL) { printk (KERN_WARNING "AODV: FIND_INTERFACE_BY_DEV gotta NULL ip_ptr!! \n"); return NULL; } //find the ip address for the dev tmp_indev=(struct in_device *) dev->ip_ptr; if (tmp_indev->ifa_list==NULL) { printk (KERN_WARNING "AODV: FIND_INTERFACE_BY_DEV gotta NULL ifa_list!! \n"); return NULL; } tmp_ip = tmp_indev->ifa_list->ifa_address; //search the interface list for a device with the same ip while (tmp_entry!=NULL) { if (tmp_entry->ip==tmp_ip) return tmp_entry; tmp_entry=tmp_entry->next; } printk(KERN_WARNING "AODV: Failed search for matching interface for: %s which has an ip of: %s\n",dev->name,inet_ntoa(tmp_ip)); return NULL; } /**************************************************** find_interface_by_ip ---------------------------------------------------- Finds an interface list entry by comparing IPs ****************************************************/ struct interface_list_entry *find_interface_by_ip(u_int32_t ip) { struct interface_list_entry *tmp_entry=interface_list; //go through the whole list while (tmp_entry!=NULL) { //if it finds a match if (tmp_entry->ip==ip) return tmp_entry; tmp_entry=tmp_entry->next; } return NULL; }