/* 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 "packet_in.h" /**************************************************** packet_in ---------------------------------------------------- When netfilter intercepts a packet coming into the system it passes it to Packet in to handle ****************************************************/ extern u_int32_t g_broadcast_ip; extern u_int32_t g_my_ip; extern struct flood_id_queue_entry *multicast_id_queue; #ifdef AODV_MULTICAST extern struct socket * multicast_sock; #endif /* ******************************** * * check_packet * * Description: * Checks to make sure that the packet is the correct size for * the packet type it says it is * ******************************** */ /**************************************************** check_packet ---------------------------------------------------- Checks to make sure that the packet is the correct size for the packet type it says it is ****************************************************/ int check_packet (int numbytes, int type, void *data_in) { int *data; struct rerr *tmp_rerr; data=(int *) data_in; switch (type) { //RREQ case 1: //If it is a normal route rreq if (numbytes == 24) return 0; if (numbytes<=26) //smaller than RREQ plus minimum exstension header return 1; if (data[25]==3 && data[26]==8 && numbytes==24+2+8) //Multicast Group Leader Extension return 0; if (data[25]==4 && data[26]==2 && numbytes==24+2+2) //Multicast Group Rebuild Extension return 0; break; //RREP case 2: if (numbytes == 20) //Normal RREP return 0; if (numbytes<= 22) //smaller than RREP plus minimum exstension header return 1; if (data[21]==5 && data[22]==6 && numbytes==20+2+6) //Multicast Group Information Exstension break; //RERR case 3: // Normal RERR tmp_rerr=data_in; if (numbytes == sizeof(struct rerr) + (sizeof(struct rerrdst) * tmp_rerr->dst_count)) { return 0; } break; case 4: //Normal RREP-ACK if (numbytes == 2) return 0; break; default: break; } return 1; } /**************************************************** packet_in ---------------------------------------------------- This function handles all the packets which come and either pass them to the correct function if they are from another AODV program or allows them to pass through if they are no of AODV type ****************************************************/ int packet_in(struct sk_buff *packet) { struct net_device *dev; struct route_table_entry *tmp_route; struct iphdr *ip; u_int32_t tmp_ip; // Create aodv message types u_int8_t aodv_type; //The packets which come in still have their headers from the IP and UDP int start_point=sizeof(struct udphdr)+sizeof(struct iphdr); //get pointers to the important parts of the message ip = packet->nh.iph; dev = packet->dev; //don't want to look at packets coming from us! tmp_ip=find_dev_ip(dev); if (tmp_ip==ip->saddr) { return NF_DROP; } if ((strcmp(dev->name,"lo")==0) && !USE_LO) { return NF_DROP; } if ((ip->daddr!=g_broadcast_ip) && (adhoc_subnet_test(ip->daddr))) { tmp_route=find_route_table_entry(ip->daddr); if ((tmp_route==NULL) || !tmp_route->route_valid) { printk( KERN_NOTICE "AODV: Undestination, %s, unable to forward...\n", inet_ntoa(ip->daddr)); host_unr(ip->daddr); } } //For all AODV packets the type is the first byte. aodv_type = (int)packet->data[start_point]; if (check_packet(packet->len-start_point,aodv_type,packet->data+start_point)) { printk(KERN_NOTICE "AODV: Packet of type: %d and of size %u failed packet check!\n",aodv_type,packet->len-start_point); return NF_DROP; } tmp_route=find_route_table_entry(ip->saddr); if ((tmp_route!=NULL) && (tmp_route->route_valid)) { tmp_route->lifetime=(HELLO_INTERVAL * ALLOWED_HELLO_LOSS) + getcurrtime(); } //place packet in the event queue! insert_event_queue_entry(aodv_type,packet); return NF_ACCEPT; } /**************************************************** input_handler ---------------------------------------------------- The actaul function which gets called by netfilter ****************************************************/ unsigned int input_handler(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct iphdr *ip = (*skb)->nh.iph; void *p = (uint32_t *) ip + ip->ihl; struct udphdr *hdr=p;// (struct udphdr *) (ip + ip->ihl); //p; struct ethhdr *mac = (*skb)->mac.ethernet; //Thanks to Randy Pitz for adding this extra check... #ifdef AODV_MULTICAST unsigned char *ucp; #endif #ifdef AODV_MULTICAST if ((ip!=NULL) && (multicast_test(ip->daddr)) && (ip->saddr!=g_my_ip)) { if (check_check(ip->saddr,ntohs(ip->id))) { ucp=(unsigned char *)&(ip->saddr); // if (((ucp[3] & 0xff)<111) &&((ucp[3] & 0xff)>100)) // { if (sock_wspace(multicast_sock->sk)>40000) insert_rebroadcast_queue_entry(ip->daddr,(*skb)->len,(*skb)->data,ip->ttl); // } } else { return NF_DROP; } } #endif if ((*skb)->h.uh!=NULL) { if ((hdr->dest==htons(AODVPORT)) && (mac->h_proto==htons(ETH_P_IP)) ) { return packet_in(*(skb)); } } return NF_ACCEPT; }