Hi developers, I encountered difficulties during integrating a new target in mangle table (iptables-1.4.0 (from www.netfilter.org), kernel-2.6.23 (from www.kernel.org)). I have a master from iptables-1.2.9 and kernel-2.6.3. But there were too many differences and changes be made. The idea behind to add the target is, that a user who has a fix-ip entry in his network settings can be handled from a gateway, for which the new targets should be implemented. for example: # iptables -t mangle -I PREROUTING -i eth2 -s 192.168.0.168 -j SADDR --to-source 10.0.19.2 iptables: Target problem -> dmesg shows: ... SADDR: targinfosize 3290890384 != 4 ... There should be a user request management in the gateway, that nobody should care about the network-settings. It should doesn't matter if a user has dhcp activated or a fix IP entry. It works with the iptables-1.2.9 and kernel-2.6.3: Code posted: kernel-sources 2.6.3: ipt_SADDR.h ipt_SADDR.c iptables-sources 1.2.9: libipt_SADDR.c kernel-sources 2.6.23: ipt_SADDR.h ipt_SADDR.c iptables-sources 1.4.0: libipt_SADDR.c nearly the same for DADDR-target! I have attached all the important files - I think!? Any help would be greatly appreciated! Thanks in advance. Regards Manu kernel-sources 2.6.3: ipt_SADDR.h: ------------------------------ #ifndef _IPT_SADDR_H_target #define _IPT_SADDR_H_target struct ipt_saddr_target_info { u_int32_t saddr; }; #endif /*_IPT_SADDR_H_target*/ ------------------------------ ipt_SADDR.c: ------------------------------ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/tcp.h> #include <net/tcp.h> #include <net/checksum.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Uli Konrad"); MODULE_DESCRIPTION("iptables IP Source Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const void *targinfo, void *userinfo) { const struct ipt_saddr_target_info *saddrinfo = targinfo; if ((*pskb)->nh.iph->saddr != saddrinfo->saddr) { u_int32_t diffs[2]; if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~((*pskb)->nh.iph->saddr); (*pskb)->nh.iph->saddr = saddrinfo->saddr; diffs[1] = saddrinfo->saddr; (*pskb)->nh.iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), (*pskb)->nh.iph->check ^0xFFFF)); if ((*pskb)->nh.iph->protocol == 0x06) { struct iphdr *iph; struct tcphdr *tcph; int datalen; iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl*4; tcph->check = 0; tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0)); } if ((*pskb)->nh.iph->protocol == 0x11) { struct iphdr *iph; struct udphdr *udph; int datalen; iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } (*pskb)->nfcache |= NFC_ALTERED; } return IPT_CONTINUE; } static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_saddr_target_info))) { printk(KERN_WARNING "SADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_saddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "SADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct ipt_target ipt_saddr_reg = { .name = "SADDR", .target = target, .checkentry = checkentry, .me = THIS_MODULE, }; static int __init init(void) { return ipt_register_target(&ipt_saddr_reg); } static void __exit fini(void) { ipt_unregister_target(&ipt_saddr_reg); } module_init(init); module_exit(fini); ---------------------------- iptables-1.2.9: libipt_SADDR.c: ---------------------------- #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> struct saddrinfo { struct ipt_entry_target t; struct ipt_saddr_target_info saddr; }; /* Function which prints out usage message. */ static void help(void) { printf( "SADDR target v%s options:\n" " --to-source ip-address set source address\n", IPTABLES_VERSION); } static struct option opts[] = { { "to-source", 1, 0, '1' }, { 0 } }; /* Initialize the target. */ static void init(struct ipt_entry_target *t, unsigned int *nfcache) { } static void parse_saddr(const unsigned char *s, struct ipt_saddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->saddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_saddr_target_info *saddrinfo = (struct ipt_saddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Cant specify --to-source twice"); parse_saddr(optarg, saddrinfo); *flags = 1; break; default: return 0; } return 1; } static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Parameter --to-source is required"); } /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric) { struct in_addr a; const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; a.s_addr = saddrinfo->saddr; printf("SADDR set %s ", addr_to_dotted(&a)); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) { struct in_addr a; const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; a.s_addr = saddrinfo->saddr; printf("--to-source %s ", addr_to_dotted(&a)); } static struct iptables_target saddr = { NULL, "SADDR", IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_target(&saddr); } -------------------------------- kernel-sources 2.6.23: ipt_SADDR.h -------------------------------- #ifndef _IPT_SADDR_H #define _IPT_SADDR_H struct ipt_saddr_target_info { u_int8_t saddr; }; #endif /*_IPT_SADDR_H*/ ------------------------------- ipt_SADDR.c ------------------------------- #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/in.h> #include <linux/netfilter.h> #include <net/checksum.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> #include <linux/netfilter_ipv4/ip_tables.h> #define NFC_ALTERED 0x8000 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Manuel Scheub"); MODULE_DESCRIPTION("iptables IP Source Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct ipt_saddr_target_info *saddrinfo = targinfo; struct iphdr *iph = ip_hdr(*pskb); if (iph->saddr != saddrinfo->saddr) { u_int32_t diffs[2]; if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~(iph->saddr); iph->saddr = saddrinfo->saddr; diffs[1] = saddrinfo->saddr; iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), iph->check ^0xFFFF)); if (iph->protocol == 0x06) { // struct iphdr *iph; struct tcphdr *tcph; int datalen; // iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; tcph->check = 0; tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP, csum_partial((char *)tcph, datalen, 0)); } if (iph->protocol == 0x11) { // struct iphdr *iph; struct udphdr *udph; int datalen; // iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } // (*pskb)->nfcache |= NFC_ALTERED; } return XT_CONTINUE; } bool checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_saddr_target_info))) { printk(KERN_WARNING "SADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_saddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "SADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct xt_target ipt_saddr_reg __read_mostly = { .name = "SADDR", .family = AF_INET, .target = target, .targetsize = sizeof(struct ipt_saddr_target_info), .table = "mangle", .checkentry = checkentry, .me = THIS_MODULE, }; static int __init ipt_saddr_init(void) { return xt_register_target(&ipt_saddr_reg); } static void __exit ipt_saddr_fini(void) { xt_unregister_target(&ipt_saddr_reg); } module_init(ipt_saddr_init); module_exit(ipt_saddr_fini); ----------------------------------- iptables-sources 1.4.0 libipt_SADDR.c: ----------------------------------#include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> struct saddrinfo { struct xt_entry_target t; struct ipt_saddr_target_info saddr; }; /* Function which prints out usage message. */ static void SADDR_help(void) { printf( "SADDR target v%s options:\n" " --to-source ip-address set source address\n", IPTABLES_VERSION); } static const struct option SADDR_opts[] = { { "to-source", 1, NULL, '1' }, { 0 } }; static void parse_saddr(const char *s, struct ipt_saddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->saddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int SADDR_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_saddr_target_info *saddrinfo = (struct ipt_saddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Cant specify --to-source twice"); parse_saddr(optarg, saddrinfo); *flags = 1; break; default: return 0; } return 1; } static void SADDR_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Parameter --to-source is required"); } static void print_saddr(u_int8_t saddr, int numeric) { unsigned int i; if (!numeric) { for (i = 0; i<sizeof(SADDR_values)/sizeof(struct SADDR_value); i++) if (SADDR_values[i].SADDR == saddr) { printf("%s ", SADDR_values[i].name); return; } } printf("0x%02x ", saddr); } /* Prints out the targinfo. */ static void SADDR_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; printf("SADDR set "); print_saddr(saddrinfo->saddr, numeric); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void SADDR_save(const void *ip, const struct xt_entry_target *target) { const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; printf("--to-source 0x%02x ", saddrinfo->saddr); } static struct iptables_target saddr_target = { .name = "SADDR", .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), .help = SADDR_help, .parse = SADDR_parse, .final_check = SADDR_check, .print = SADDR_print, .save = SADDR_save, .extra_opts = SADDR_opts, }; void _init(void) { register_target(&saddr_target); } ----------------------------------------
/* This is a module which is used for setting the DADDR field of a packet. */ /* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@xxxxxxxxxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/tcp.h> #include <net/tcp.h> #include <net/checksum.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_DADDR.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Uli Konrad"); MODULE_DESCRIPTION("iptables IP Destination Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const void *targinfo, void *userinfo) { const struct ipt_daddr_target_info *daddrinfo = targinfo; if ((*pskb)->nh.iph->daddr != daddrinfo->daddr) { u_int32_t diffs[2]; if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~((*pskb)->nh.iph->daddr); (*pskb)->nh.iph->daddr = daddrinfo->daddr; diffs[1] = daddrinfo->daddr; (*pskb)->nh.iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), (*pskb)->nh.iph->check ^0xFFFF)); if ((*pskb)->nh.iph->protocol == 0x06) { struct iphdr *iph; struct tcphdr *tcph; int datalen; iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl*4; tcph->check = 0; tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0)); } if ((*pskb)->nh.iph->protocol == 0x11) { struct iphdr *iph; struct udphdr *udph; int datalen; iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } (*pskb)->nfcache |= NFC_ALTERED; } return IPT_CONTINUE; } static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_daddr_target_info))) { printk(KERN_WARNING "DADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_daddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "DADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct ipt_target ipt_daddr_reg = { .name = "DADDR", .target = target, .checkentry = checkentry, .me = THIS_MODULE, }; static int __init init(void) { return ipt_register_target(&ipt_daddr_reg); } static void __exit fini(void) { ipt_unregister_target(&ipt_daddr_reg); } module_init(init); module_exit(fini);
#ifndef _IPT_DADDR_H_target #define _IPT_DADDR_H_target struct ipt_daddr_target_info { u_int32_t daddr; }; #endif /*_IPT_DADDR_H_target*/
/* This is a module which is used for setting the DADDR field of a packet. */ /* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@xxxxxxxxxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/in.h> #include <linux/netfilter.h> #include <net/checksum.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_DADDR.h> #include <linux/netfilter_ipv4/ip_tables.h> #define NFC_ALTERED 0x8000 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Manuel Scheub"); MODULE_DESCRIPTION("iptables IP Destination Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct ipt_daddr_target_info *daddrinfo = targinfo; struct iphdr *iph = ip_hdr(*pskb); if (iph->daddr != daddrinfo->daddr) { u_int32_t diffs[2]; if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~(iph->daddr); iph->daddr = daddrinfo->daddr; diffs[1] = daddrinfo->daddr; iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), iph->check ^0xFFFF)); if (iph->protocol == 0x06) { // struct iphdr *iph; struct tcphdr *tcph; int datalen; // iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; tcph->check = 0; tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP, csum_partial((char *)tcph, datalen, 0)); // tcph->check = tcp_v4_check( datalen, // iph->saddr, // iph->daddr, // csum_partial((char *)tcph, // datalen, 0)); } if (iph->protocol == 0x11) { // struct iphdr *iph; struct udphdr *udph; int datalen; // iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } // (*pskb)->nfcache |= NFC_ALTERED; } return XT_CONTINUE; } static bool checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_daddr_target_info))) { printk(KERN_WARNING "DADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_daddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "DADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct xt_target ipt_daddr_reg __read_mostly = { .name = "DADDR", .family = AF_INET, .target = target, .targetsize = sizeof(struct ipt_daddr_target_info), .table = "mangle", .checkentry = checkentry, .me = THIS_MODULE, }; static int __init ipt_daddr_init(void) { return xt_register_target(&ipt_daddr_reg); } static void __exit ipt_daddr_fini(void) { xt_unregister_target(&ipt_daddr_reg); } module_init(ipt_daddr_init); module_exit(ipt_daddr_fini);
/* Set DADDR field in header to any value * * ipt_DADDR.h borrowed heavily from ipt_TOS.h 11/09/2000 */ #ifndef _IPT_DADDR_H #define _IPT_DADDR_H struct ipt_daddr_target_info { u_int8_t daddr; }; #endif /*_IPT_DADDR_H*/
/* This is a module which is used for setting the SADDR field of a packet. */ /* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@xxxxxxxxxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/tcp.h> #include <net/tcp.h> #include <net/checksum.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Uli Konrad"); MODULE_DESCRIPTION("iptables IP Source Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const void *targinfo, void *userinfo) { const struct ipt_saddr_target_info *saddrinfo = targinfo; if ((*pskb)->nh.iph->saddr != saddrinfo->saddr) { u_int32_t diffs[2]; if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~((*pskb)->nh.iph->saddr); (*pskb)->nh.iph->saddr = saddrinfo->saddr; diffs[1] = saddrinfo->saddr; (*pskb)->nh.iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), (*pskb)->nh.iph->check ^0xFFFF)); if ((*pskb)->nh.iph->protocol == 0x06) { struct iphdr *iph; struct tcphdr *tcph; int datalen; iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl*4; tcph->check = 0; tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0)); } if ((*pskb)->nh.iph->protocol == 0x11) { struct iphdr *iph; struct udphdr *udph; int datalen; iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } (*pskb)->nfcache |= NFC_ALTERED; } return IPT_CONTINUE; } static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_saddr_target_info))) { printk(KERN_WARNING "SADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_saddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "SADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct ipt_target ipt_saddr_reg = { .name = "SADDR", .target = target, .checkentry = checkentry, .me = THIS_MODULE, }; static int __init init(void) { return ipt_register_target(&ipt_saddr_reg); } static void __exit fini(void) { ipt_unregister_target(&ipt_saddr_reg); } module_init(init); module_exit(fini);
#ifndef _IPT_SADDR_H_target #define _IPT_SADDR_H_target struct ipt_saddr_target_info { u_int32_t saddr; }; #endif /*_IPT_SADDR_H_target*/
/* This is a module which is used for setting the SADDR field of a packet. */ /* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@xxxxxxxxxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/in.h> #include <linux/netfilter.h> #include <net/checksum.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> #include <linux/netfilter_ipv4/ip_tables.h> #define NFC_ALTERED 0x8000 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Manuel Scheub"); MODULE_DESCRIPTION("iptables IP Source Address mangling module"); static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, const void *targinfo) { const struct ipt_saddr_target_info *saddrinfo = targinfo; struct iphdr *iph = ip_hdr(*pskb); if (iph->saddr != saddrinfo->saddr) { u_int32_t diffs[2]; if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; diffs[0] = ~(iph->saddr); iph->saddr = saddrinfo->saddr; diffs[1] = saddrinfo->saddr; iph->check = csum_fold(csum_partial((char *)diffs, sizeof(diffs), iph->check ^0xFFFF)); if (iph->protocol == 0x06) { // struct iphdr *iph; struct tcphdr *tcph; int datalen; // iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; tcph->check = 0; tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP, csum_partial((char *)tcph, datalen, 0)); // tcph->check = tcp_v4_check( datalen, // iph->saddr, // iph->daddr, // csum_partial((char *)tcph, // datalen, 0)); } if (iph->protocol == 0x11) { // struct iphdr *iph; struct udphdr *udph; int datalen; // iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); } // (*pskb)->nfcache |= NFC_ALTERED; } return XT_CONTINUE; } bool checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_saddr_target_info))) { printk(KERN_WARNING "SADDR: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_saddr_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "SADDR: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; } static struct xt_target ipt_saddr_reg __read_mostly = { .name = "SADDR", .family = AF_INET, .target = target, .targetsize = sizeof(struct ipt_saddr_target_info), .table = "mangle", .checkentry = checkentry, .me = THIS_MODULE, }; static int __init ipt_saddr_init(void) { return xt_register_target(&ipt_saddr_reg); } static void __exit ipt_saddr_fini(void) { xt_unregister_target(&ipt_saddr_reg); } module_init(ipt_saddr_init); module_exit(ipt_saddr_fini);
/* Set SADDR field in header to any value * * ipt_SADDR.h borrowed heavily from ipt_TOS.h 11/09/2000 */ #ifndef _IPT_SADDR_H #define _IPT_SADDR_H struct ipt_saddr_target_info { u_int8_t saddr; }; #endif /*_IPT_SADDR_H*/
/* Shared library add-on to iptables to add DADDR target support. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_DADDR.h> struct daddrinfo { struct ipt_entry_target t; struct ipt_daddr_target_info daddr; }; /* Function which prints out usage message. */ static void help(void) { printf( "DADDR target v%s options:\n" " --to-dest ip-address set dest address\n", IPTABLES_VERSION); } static struct option opts[] = { { "to-dest", 1, 0, '1' }, { 0 } }; /* Initialize the target. */ static void init(struct ipt_entry_target *t, unsigned int *nfcache) { } static void parse_daddr(const unsigned char *s, struct ipt_daddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->daddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_daddr_target_info *daddrinfo = (struct ipt_daddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "DADDR target: Cant specify --to-dest twice"); parse_daddr(optarg, daddrinfo); *flags = 1; break; default: return 0; } return 1; } static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "DADDR target: Parameter --to-dest is required"); } /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric) { struct in_addr a; const struct ipt_daddr_target_info *daddrinfo = (const struct ipt_daddr_target_info *)target->data; a.s_addr = daddrinfo->daddr; printf("DADDR set %s ", addr_to_dotted(&a)); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) { struct in_addr a; const struct ipt_daddr_target_info *daddrinfo = (const struct ipt_daddr_target_info *)target->data; a.s_addr = daddrinfo->daddr; printf("--to-dest %s ", addr_to_dotted(&a)); } static struct iptables_target daddr = { NULL, "DADDR", IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_daddr_target_info)), IPT_ALIGN(sizeof(struct ipt_daddr_target_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_target(&daddr); }
/* Shared library add-on to iptables to add DADDR target support. */ /* Adopted from TOS target support*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_DADDR.h> struct daddrinfo { struct xt_entry_target t; struct ipt_daddr_target_info daddr; }; /* Function which prints out usage message. */ static void DADDR_help(void) { printf( "DADDR target v%s options:\n" " --to-dest ip-address set dest address\n", IPTABLES_VERSION); } static const struct option DADDR_opts[] = { { "to-dest", 1, NULL, '1' }, { 0 } }; static void parse_daddr(const char *s, struct ipt_daddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->daddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int DADDR_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_daddr_target_info *daddrinfo = (struct ipt_daddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "DADDR target: Cant specify --to-dest twice"); parse_daddr(optarg, daddrinfo); *flags = 1; break; default: return 0; } return 1; } static void DADDR_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "DADDR target: Parameter --to-dest is required"); } static void print_daddr(u_int8_t daddr, int numeric) { unsigned int i; if (!numeric) { for (i = 0; i<sizeof(DADDR_values)/sizeof(struct DADDR_value); i++) if (DADDR_values[i].DADDR == daddr) { printf("%s ", DADDR_values[i].name); return; } } printf("0x%02x ", daddr); } /* Prints out the targinfo. */ static void DADDR_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct ipt_daddr_target_info *daddrinfo = (const struct ipt_daddr_target_info *)target->data; printf("DADDR set "); print_daddr(daddrinfo->daddr, numeric); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void DADDR_save(const void *ip, const struct xt_entry_target *target) { const struct ipt_daddr_target_info *daddrinfo = (const struct ipt_daddr_target_info *)target->data; printf("--to-dest 0x%02x ", daddrinfo->daddr); } static struct iptables_target daddr_target = { .name = "DADDR", .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_daddr_target_info)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_daddr_target_info)), .help = DADDR_help, .parse = DADDR_parse, .final_check = DADDR_check, .print = DADDR_print, .save = DADDR_save, .extra_opts = DADDR_opts, }; void _init(void) { register_target(&daddr_target); }
/* Shared library add-on to iptables to add SADDR target support. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> struct saddrinfo { struct ipt_entry_target t; struct ipt_saddr_target_info saddr; }; /* Function which prints out usage message. */ static void help(void) { printf( "SADDR target v%s options:\n" " --to-source ip-address set source address\n", IPTABLES_VERSION); } static struct option opts[] = { { "to-source", 1, 0, '1' }, { 0 } }; /* Initialize the target. */ static void init(struct ipt_entry_target *t, unsigned int *nfcache) { } static void parse_saddr(const unsigned char *s, struct ipt_saddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->saddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_saddr_target_info *saddrinfo = (struct ipt_saddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Cant specify --to-source twice"); parse_saddr(optarg, saddrinfo); *flags = 1; break; default: return 0; } return 1; } static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Parameter --to-source is required"); } /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric) { struct in_addr a; const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; a.s_addr = saddrinfo->saddr; printf("SADDR set %s ", addr_to_dotted(&a)); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) { struct in_addr a; const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; a.s_addr = saddrinfo->saddr; printf("--to-source %s ", addr_to_dotted(&a)); } static struct iptables_target saddr = { NULL, "SADDR", IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_target(&saddr); }
/* Shared library add-on to iptables to add SADDR target support. */ /* Adopted from TOS target support*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_SADDR.h> struct saddrinfo { struct xt_entry_target t; struct ipt_saddr_target_info saddr; }; /* Function which prints out usage message. */ static void SADDR_help(void) { printf( "SADDR target v%s options:\n" " --to-source ip-address set source address\n", IPTABLES_VERSION); } static const struct option SADDR_opts[] = { { "to-source", 1, NULL, '1' }, { 0 } }; static void parse_saddr(const char *s, struct ipt_saddr_target_info *info) { struct in_addr *ip; ip = dotted_to_addr(s); if (!ip) exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", s); info->saddr = ip->s_addr; } /* Function which parses command options; returns true if it ate an option */ static int SADDR_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_saddr_target_info *saddrinfo = (struct ipt_saddr_target_info *)(*target)->data; switch (c) { case '1': if (*flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Cant specify --to-source twice"); parse_saddr(optarg, saddrinfo); *flags = 1; break; default: return 0; } return 1; } static void SADDR_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "SADDR target: Parameter --to-source is required"); } static void print_saddr(u_int8_t saddr, int numeric) { unsigned int i; if (!numeric) { for (i = 0; i<sizeof(SADDR_values)/sizeof(struct SADDR_value); i++) if (SADDR_values[i].SADDR == saddr) { printf("%s ", SADDR_values[i].name); return; } } printf("0x%02x ", saddr); } /* Prints out the targinfo. */ static void SADDR_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; printf("SADDR set "); print_saddr(saddrinfo->saddr, numeric); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void SADDR_save(const void *ip, const struct xt_entry_target *target) { const struct ipt_saddr_target_info *saddrinfo = (const struct ipt_saddr_target_info *)target->data; printf("--to-source 0x%02x ", saddrinfo->saddr); } static struct iptables_target saddr_target = { .name = "SADDR", .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_saddr_target_info)), .help = SADDR_help, .parse = SADDR_parse, .final_check = SADDR_check, .print = SADDR_print, .save = SADDR_save, .extra_opts = SADDR_opts, }; void _init(void) { register_target(&saddr_target); }