static unsigned int ip_nat_local_fn(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { u_int32_t saddr, daddr; unsigned int ret; /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) return NF_ACCEPT; saddr = (*pskb)->nh.iph->saddr; daddr = (*pskb)->nh.iph->daddr; ret = ip_nat_fn(hooknum, pskb, in, out, okfn); if (ret != NF_DROP && ret != NF_STOLEN && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr)) return route_me_harder(*pskb) == 0 ? ret : NF_DROP; return ret; }
static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e) { int diff; struct iphdr *user_iph = (struct iphdr *)v->payload; if (v->data_len < sizeof(*user_iph)) return 0; diff = v->data_len - e->skb->len; if (diff < 0) skb_trim(e->skb, v->data_len); else if (diff > 0) { if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { struct sk_buff *newskb; newskb = skb_copy_expand(e->skb, skb_headroom(e->skb), diff, GFP_ATOMIC); if (newskb == NULL) { printk(KERN_WARNING "ip_queue: OOM " "in mangle, dropping packet\n"); return -ENOMEM; } if (e->skb->sk) skb_set_owner_w(newskb, e->skb->sk); kfree_skb(e->skb); e->skb = newskb; } skb_put(e->skb, diff); } memcpy(e->skb->data, v->payload, v->data_len); e->skb->nfcache |= NFC_ALTERED; /* * Extra routing may needed on local out, as the QUEUE target never * returns control to the table. */ if (e->info->hook == NF_IP_LOCAL_OUT) { struct iphdr *iph = e->skb->nh.iph; if (!(iph->tos == e->rt_info.tos && iph->daddr == e->rt_info.daddr && iph->saddr == e->rt_info.saddr)) return route_me_harder(e->skb); } return 0; }
static int ipq_set_verdict(ipq_queue_t *q, ipq_verdict_msg_t *v, unsigned int len) { ipq_queue_element_t *e; if (v->value > NF_MAX_VERDICT) return -EINVAL; e = ipq_dequeue(q, id_cmp, v->id); if (e == NULL) return -ENOENT; else { e->verdict = v->value; if (v->data_len && v->data_len == len) if (ipq_mangle_ipv4(v, e) < 0) e->verdict = NF_DROP; /* APE: Always re-route packets... UGLY HACK!!! */ route_me_harder(e->skb); /* END APE */ nf_reinject(e->skb, e->info, e->verdict); kfree(e); return 0; } }
unsigned int nf_aodv_hook(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn) (struct sk_buff *)) { int i; /* We are only interested in IP packets */ if ((*skb)->nh.iph == NULL) goto accept; /* We want AODV control messages to go through directly to the * AODV socket.... */ if ((*skb)->nh.iph && (*skb)->nh.iph->protocol == IPPROTO_UDP) if ((*skb)->sk) if ((*skb)->sk->dport == htons(AODV_PORT) || (*skb)->sk->sport == htons(AODV_PORT)) goto accept; /* Check which hook the packet is on... */ switch (hooknum) { case NF_IP_PRE_ROUTING: /* Loop through all AODV enabled interfaces and see if the packet * is bound to any of them. */ for (i = 0; i < nif; i++) if (ifindices[i] == in->ifindex) { (*skb)->nfmark = 3; goto queue; } break; case NF_IP_LOCAL_OUT: for (i = 0; i < nif; i++) if (ifindices[i] == out->ifindex) { (*skb)->nfmark = 4; goto queue; } break; case NF_IP_POST_ROUTING: /* Re-route all packets before sending on interface. This will make sure queued packets are routed on a newly installed route (after a successful RREQ-cycle). FIXME: Make sure only "buffered" packets are re-routed. But how? */ if ((*skb)->nfmark == 3 || (*skb)->nfmark == 4) { #ifdef USE_OLD_ROUTE_ME_HARDER route_me_harder((*skb)); #else ip_route_me_harder(skb); #endif } return NF_ACCEPT; default: } accept: (*skb)->nfmark = 2; return NF_ACCEPT; queue: return NF_QUEUE; } /* * Called when the module is inserted in the kernel. */ char *ifname[MAX_INTERFACES] = { "eth0" }; MODULE_PARM(ifname, "1-" __MODULE_STRING(MAX_INTERFACES) "s"); int init_module() { struct net_device *dev = NULL; int i; EXPORT_NO_SYMBOLS; nf_hook1.list.next = NULL; nf_hook1.list.prev = NULL; nf_hook1.hook = nf_aodv_hook; nf_hook1.pf = PF_INET; nf_hook1.hooknum = NF_IP_PRE_ROUTING; nf_register_hook(&nf_hook1); nf_hook2.list.next = NULL; nf_hook2.list.prev = NULL; nf_hook2.hook = nf_aodv_hook; nf_hook2.pf = PF_INET; nf_hook2.hooknum = NF_IP_LOCAL_OUT; nf_register_hook(&nf_hook2); nf_hook3.list.next = NULL; nf_hook3.list.prev = NULL; nf_hook3.hook = nf_aodv_hook; nf_hook3.pf = PF_INET; nf_hook3.hooknum = NF_IP_POST_ROUTING; nf_register_hook(&nf_hook3); for (i = 0; i < MAX_INTERFACES; i++) { if (!ifname[i]) break; dev = dev_get_by_name(ifname[i]); if (!dev) { printk("kaodv: No device %s available, ignoring!\n", ifname[i]); dev_put(dev); continue; } ifindices[nif++] = dev->ifindex; dev_put(dev); } return 0; } /* * Called when removing the module from memory... */ void cleanup_module() { nf_unregister_hook(&nf_hook1); nf_unregister_hook(&nf_hook2); nf_unregister_hook(&nf_hook3); }