#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 #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); struct proc_dir_entry *proc_entry; 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"); } int once_only=0; static int init_probes(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; } return ret; } /* as per http://www.tldp.org/LDP/lkmpg/2.4/html/c577.htm the declaration of write in the file_operations struct reads: ssize_t (*write) (struct file *, const char *, size_t, loff_t *); */ ssize_t procfile_write(struct file *file, const char *buffer, size_t count, loff_t *data) { if (!once_only) { once_only=1; if (init_probes()==-1) printk(KERN_CRIT "Could not install procprotect probes. Reload module to retry."); else printk(KERN_CRIT "Activated transforward module"); } return count; } static const struct file_operations transforward_fops = { .owner = THIS_MODULE, .write = procfile_write }; static int __init transforward_init(void) { int ret = 0; printk("Transforward: starting transforward version %s.\n", VERSION_STR); proc_entry = proc_create("transforward", 0644, NULL, &transforward_fops); return ret; } module_init(transforward_init); module_exit(transforward_exit);