#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSION_STR "0.0.1" #ifndef CONFIG_X86_64 #error "This code does not support your architecture" #endif MODULE_AUTHOR("Sapan Bhatia "); MODULE_DESCRIPTION("Transparent port forwarding for LXC."); MODULE_LICENSE("GPL"); MODULE_VERSION(VERSION_STR); static int address_in_root(unsigned int haddr) { struct net_device *dev; struct net *net = &init_net; for_each_netdev(net, dev) { unsigned int ifhaddr = inet_select_addr(dev,0,0); //printk(KERN_CRIT "Checking address: %u",ifhaddr); if (haddr == ifhaddr) return 1; } return 0; } static int inet_bind_entry(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; unsigned int snum = addr->sin_addr.s_addr; //printk(KERN_CRIT "Checking address %d",snum); if (address_in_root(snum)) { put_net(sock_net(sock->sk)); sock_net_set(sock->sk, get_net(&init_net)); //printk(KERN_CRIT "Rewiring netns"); } jprobe_return(); return 0; } static struct file *do_last_probe(struct nameidata *nd, struct path *path, const struct open_flags *op, const char *pathname) { jprobe_return(); } static struct jprobe net_probe = { .entry = (kprobe_opcode_t *) inet_bind_entry }; static void __exit transforward_exit(void) { unregister_jprobe(&net_probe); printk("Transforward: Stopped transforward.\n"); } static int __init transforward_init(void) { int ret = 0; printk("Transforward: starting transforward version %s.\n", VERSION_STR); net_probe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("inet_bind"); if (!net_probe.kp.addr) { printk("Couldn't find %s to plant kretprobe\n", "inet_bind"); return -1; } if ((ret = register_jprobe(&net_probe)) <0) { printk("register_jprobe failed, returned %u\n", ret); return -1; } //printk("Planted jprobe at %p, handler addr %p\n", //net_probe.kp.addr, net_probe.entry); return ret; } module_init(transforward_init); module_exit(transforward_exit);