static int kaodv_netlink_receive_peer(unsigned char type, void *msg, unsigned int len) { int ret = 0; struct kaodv_rt_msg *m; struct kaodv_conf_msg *cm; struct expl_entry e; KAODV_DEBUG("Received msg: %s", kaodv_msg_type_to_str(type)); switch (type) { case KAODVM_ADDROUTE: if (len < sizeof(struct kaodv_rt_msg)) return -EINVAL; m = (struct kaodv_rt_msg *)msg; ret = kaodv_expl_get(m->dst, &e); if (ret > 0) { ret = kaodv_expl_update(m->dst, m->nhop, m->time, m->flags, m->ifindex); } else { ret = kaodv_expl_add(m->dst, m->nhop, m->time, m->flags, m->ifindex); } printk(KERN_DEBUG "kaodv: KAODVM_ADDROUTE!\n"); kaodv_queue_set_verdict(KAODV_QUEUE_SEND, m->dst); break; case KAODVM_DELROUTE: if (len < sizeof(struct kaodv_rt_msg)) return -EINVAL; m = (struct kaodv_rt_msg *)msg; kaodv_expl_del(m->dst); kaodv_queue_set_verdict(KAODV_QUEUE_DROP, m->dst); break; case KAODVM_NOROUTE_FOUND: if (len < sizeof(struct kaodv_rt_msg)) return -EINVAL; m = (struct kaodv_rt_msg *)msg; KAODV_DEBUG("No route found for %s", print_ip(m->dst)); kaodv_queue_set_verdict(KAODV_QUEUE_DROP, m->dst); break; case KAODVM_CONFIG: if (len < sizeof(struct kaodv_conf_msg)) return -EINVAL; cm = (struct kaodv_conf_msg *)msg; active_route_timeout = cm->active_route_timeout; qual_th = cm->qual_th; is_gateway = cm->is_gateway; break; default: printk("kaodv-netlink: Unknown message type\n"); ret = -EINVAL; } return ret; }
void kaodv_update_route_timeouts(int hooknum, const struct net_device *dev, struct iphdr *iph) { struct expl_entry e; struct in_addr bcaddr; int res; bcaddr.s_addr = 0; /* Stop compiler from complaining about * uninitialized bcaddr */ res = if_info_from_ifindex(NULL, &bcaddr, dev->ifindex); if (res < 0) return; if (hooknum == NF_INET_PRE_ROUTING) kaodv_netlink_send_rt_update_msg(PKT_INBOUND, iph->saddr, iph->daddr, dev->ifindex); else if (iph->daddr != INADDR_BROADCAST && iph->daddr != bcaddr.s_addr) kaodv_netlink_send_rt_update_msg(PKT_OUTBOUND, iph->saddr, iph->daddr, dev->ifindex); /* First update forward route and next hop */ if (kaodv_expl_get(iph->daddr, &e)) { kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags, dev->ifindex); if (e.nhop != e.daddr && kaodv_expl_get(e.nhop, &e)) kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags, dev->ifindex); } /* Update reverse route */ if (kaodv_expl_get(iph->saddr, &e)) { kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags, dev->ifindex); if (e.nhop != e.daddr && kaodv_expl_get(e.nhop, &e)) kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags, dev->ifindex); } }
static void kaodv_update_route_timeouts(int hooknum, const struct net_device *dev, struct iphdr *iph) { struct expl_entry e; struct netdev_info *netdi; netdi = netdev_info_from_ifindex(dev->ifindex); if (!netdi) return; if (hooknum == NF_IP_PRE_ROUTING) kaodv_netlink_send_rt_update_msg(PKT_INBOUND, iph->saddr, iph->daddr, dev->ifindex); else if (iph->daddr != INADDR_BROADCAST && iph->daddr != netdi->bc_addr) kaodv_netlink_send_rt_update_msg(PKT_OUTBOUND, iph->saddr, iph->daddr, dev->ifindex); /* First update forward route and next hop */ if (kaodv_expl_get(iph->daddr, &e)) { kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags); if (e.nhop != e.daddr && kaodv_expl_get(e.nhop, &e)) kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags); } /* Update reverse route */ if (kaodv_expl_get(iph->saddr, &e)) { kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags); if (e.nhop != e.daddr && kaodv_expl_get(e.nhop, &e)) kaodv_expl_update(e.daddr, e.nhop, ACTIVE_ROUTE_TIMEOUT, e.flags); } }
static unsigned int kaodv_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn) (struct sk_buff *)) { struct iphdr *iph = SKB_NETWORK_HDR_IPH(skb); struct expl_entry e; struct in_addr ifaddr, bcaddr; int res = 0; memset(&ifaddr, 0, sizeof(struct in_addr)); memset(&bcaddr, 0, sizeof(struct in_addr)); /* We are only interested in IP packets */ if (iph == NULL) return NF_ACCEPT; /* We want AODV control messages to go through directly to the * AODV socket.... */ if (iph && iph->protocol == IPPROTO_UDP) { struct udphdr *udph; udph = (struct udphdr *)((char *)iph + (iph->ihl << 2)); if (ntohs(udph->dest) == AODV_PORT || ntohs(udph->source) == AODV_PORT) { #ifdef CONFIG_QUAL_THRESHOLD #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) qual = (int)(skb)->__unused; #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) qual = (skb)->iwq.qual; #endif if (qual_th && hooknum == NF_INET_PRE_ROUTING) { if (qual && qual < qual_th) { pkts_dropped++; return NF_DROP; } } #endif /* CONFIG_QUAL_THRESHOLD */ if (hooknum == NF_INET_PRE_ROUTING && in) kaodv_update_route_timeouts(hooknum, in, iph); return NF_ACCEPT; } } if (hooknum == NF_INET_PRE_ROUTING) res = if_info_from_ifindex(&ifaddr, &bcaddr, in->ifindex); else res = if_info_from_ifindex(&ifaddr, &bcaddr, out->ifindex); if (res < 0) return NF_ACCEPT; /* Ignore broadcast and multicast packets */ if (iph->daddr == INADDR_BROADCAST || IN_MULTICAST(ntohl(iph->daddr)) || iph->daddr == bcaddr.s_addr) return NF_ACCEPT; /* Check which hook the packet is on... */ switch (hooknum) { case NF_INET_PRE_ROUTING: kaodv_update_route_timeouts(hooknum, in, iph); /* If we are a gateway maybe we need to decapsulate? */ if (is_gateway && iph->protocol == IPPROTO_MIPE && iph->daddr == ifaddr.s_addr) { ip_pkt_decapsulate(skb); iph = SKB_NETWORK_HDR_IPH(skb); return NF_ACCEPT; } /* Ignore packets generated locally or that are for this * node. */ if (iph->saddr == ifaddr.s_addr || iph->daddr == ifaddr.s_addr) { return NF_ACCEPT; } /* Check for unsolicited data packets */ else if (!kaodv_expl_get(iph->daddr, &e)) { kaodv_netlink_send_rerr_msg(PKT_INBOUND, iph->saddr, iph->daddr, in->ifindex); return NF_DROP; } /* Check if we should repair the route */ else if (e.flags & KAODV_RT_REPAIR) { kaodv_netlink_send_rt_msg(KAODVM_REPAIR, iph->saddr, iph->daddr); kaodv_queue_enqueue_packet(skb, okfn); return NF_STOLEN; } break; case NF_INET_LOCAL_OUT: if (!kaodv_expl_get(iph->daddr, &e) || (e.flags & KAODV_RT_REPAIR)) { if (!kaodv_queue_find(iph->daddr)) kaodv_netlink_send_rt_msg(KAODVM_ROUTE_REQ, 0, iph->daddr); kaodv_queue_enqueue_packet(skb, okfn); return NF_STOLEN; } else if (e.flags & KAODV_RT_GW_ENCAP) { /* Make sure that also the virtual Internet * dest entry is refreshed */ kaodv_update_route_timeouts(hooknum, out, iph); skb = ip_pkt_encapsulate(skb, e.nhop); if (!skb) return NF_STOLEN; ip_route_me_harder(skb, RTN_LOCAL); } break; case NF_INET_POST_ROUTING: kaodv_update_route_timeouts(hooknum, out, iph); } return NF_ACCEPT; }
static unsigned int kaodv_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn) (struct sk_buff *)) { struct iphdr *iph = SKB_NETWORK_HDR_IPH(skb); struct expl_entry e; struct in_addr ifaddr, bcaddr; int res = 0; memset(&ifaddr, 0, sizeof(struct in_addr)); memset(&bcaddr, 0, sizeof(struct in_addr)); /* We are only interested in IP packets */ if (iph == NULL) return NF_ACCEPT; /* Hook FORWARD only takecare of gateway packets */ if(hooknum == NF_INET_FORWARD) { //we are only handle forwarded packets in gateway mode if(!is_gateway) return NF_ACCEPT; //we don't process packets from binded interface if(!in || if_info_from_ifindex(NULL, NULL, in->ifindex) == 0) return NF_ACCEPT; } /* We want AODV control messages to go through directly to the * AODV socket.... */ if (iph && iph->protocol == IPPROTO_UDP) { struct udphdr *udph; udph = (struct udphdr *)((char *)iph + (iph->ihl << 2)); if (ntohs(udph->dest) == AODV_PORT || ntohs(udph->source) == AODV_PORT) { #ifdef CONFIG_QUAL_THRESHOLD qual = (skb)->iwq.qual; if (qual_th && hooknum == NF_INET_PRE_ROUTING) { if (qual && qual < qual_th) { pkts_dropped++; return NF_DROP; } } #endif /* CONFIG_QUAL_THRESHOLD */ if (hooknum == NF_INET_PRE_ROUTING && in) kaodv_update_route_timeouts(hooknum, in, iph); return NF_ACCEPT; } } if (hooknum == NF_INET_PRE_ROUTING) { res = if_info_from_ifindex(&ifaddr, &bcaddr, in->ifindex); printk(KERN_DEBUG "kaodv: in->ifindex %d, res %d.\n", in->ifindex, res); } else { res = if_info_from_ifindex(&ifaddr, &bcaddr, out->ifindex); printk(KERN_DEBUG "kaodv: out->ifindex %d, res %d.\n", out->ifindex, res); } if (res < 0) { printk(KERN_DEBUG "kaodv: No information!\n"); return NF_ACCEPT; } /* Ignore broadcast and multicast packets */ if (iph->daddr == INADDR_BROADCAST || IN_MULTICAST(ntohl(iph->daddr)) || iph->daddr == bcaddr.s_addr) { printk(KERN_DEBUG "kaodv: Broadcast packet!\n"); return NF_ACCEPT; } /* Check which hook the packet is on... */ printk(KERN_DEBUG "kaodv: Check which hook the packet is on...\n"); switch (hooknum) { case NF_INET_PRE_ROUTING: printk(KERN_DEBUG "kaodv: NF_INET_PRE_ROUTING\n"); kaodv_update_route_timeouts(hooknum, in, iph); /* If we are a gateway maybe we need to decapsulate? */ if (is_gateway && iph->protocol == IPPROTO_MIPE && iph->daddr == ifaddr.s_addr) { ip_pkt_decapsulate(skb); printk(KERN_DEBUG "kaodv: successfully returned from ip_pkt_decapsulate!\n"); iph = SKB_NETWORK_HDR_IPH(skb); return NF_ACCEPT; } /* Ignore packets generated locally or that are for this * node. */ if (iph->saddr == ifaddr.s_addr || iph->daddr == ifaddr.s_addr) { return NF_ACCEPT; } /* Check for unsolicited data packets */ else if (!kaodv_expl_get(iph->daddr, &e)) { kaodv_netlink_send_rerr_msg(PKT_INBOUND, iph->saddr, iph->daddr, in->ifindex); return NF_DROP; } /* Check if we should repair the route */ else if (e.flags & KAODV_RT_REPAIR) { kaodv_netlink_send_rt_msg(KAODVM_REPAIR, iph->saddr, iph->daddr); kaodv_queue_enqueue_packet(skb, okfn); return NF_STOLEN; } break; case NF_INET_FORWARD: case NF_INET_LOCAL_OUT: printk(KERN_DEBUG "kaodv: NF_INET_LOCAL_OUT\n"); if (!kaodv_expl_get(iph->daddr, &e) || (e.flags & KAODV_RT_REPAIR)) { if (!kaodv_queue_find(iph->daddr)) kaodv_netlink_send_rt_msg(KAODVM_ROUTE_REQ, 0, iph->daddr); kaodv_queue_enqueue_packet(skb, okfn); return NF_STOLEN; } else if (e.flags & KAODV_RT_GW_ENCAP) { /* Make sure that also the virtual Internet * dest entry is refreshed */ kaodv_update_route_timeouts(hooknum, out, iph); skb = ip_pkt_encapsulate(skb, e.nhop); if (!skb) return NF_STOLEN; printk(KERN_DEBUG "kaodv: successfully returned from ip_pkt_encapsulate!\n"); ip_route_me_harder(skb, RTN_LOCAL); } break; case NF_INET_POST_ROUTING: printk(KERN_DEBUG "kaodv: NF_INET_POST_ROUTING\n"); kaodv_update_route_timeouts(hooknum, out, iph); break; } printk(KERN_DEBUG "kaodv: Succesfully returned from NF_HOOK!\n"); return NF_ACCEPT; }