diff --git a/extensions/Kbuild b/extensions/Kbuild index 6596b50..1921a71 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -34,5 +34,7 @@ obj-${build_pknock} += pknock/ obj-${build_psd} += xt_psd.o obj-${build_quota2} += xt_quota2.o +obj-${build_ipaddr} += xt_ipaddr.o + -include ${M}/*.Kbuild -include ${M}/Kbuild.* diff --git a/extensions/Mbuild b/extensions/Mbuild index 31a7e22..80fcee0 100644 --- a/extensions/Mbuild +++ b/extensions/Mbuild @@ -16,6 +16,7 @@ obj-${build_condition} += libxt_condition.so obj-${build_fuzzy} += libxt_fuzzy.so obj-${build_geoip} += libxt_geoip.so obj-${build_iface} += libxt_iface.so +obj-${build_ipaddr} += libxt_ipaddr.so obj-${build_ipp2p} += libxt_ipp2p.so obj-${build_ipv4options} += libxt_ipv4options.so obj-${build_length2} += libxt_length2.so diff --git a/extensions/libxt_ipaddr.c b/extensions/libxt_ipaddr.c new file mode 100644 index 0000000..9a86965 --- /dev/null +++ b/extensions/libxt_ipaddr.c @@ -0,0 +1,254 @@ +/* + * "ipaddr" demo match extension for iptables + * written by Jan Engelhardt , 2008 - 2009 + * released in the Public Domain + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "xt_ipaddr.h" + +static const struct option ipaddr_mt_opts[] = { + {.name = "ipsrc", .has_arg = true, .val = '1'}, + {.name = "ipdst", .has_arg = true, .val = '2'}, + {NULL}, +}; + +static void ipaddr_mt_help(void) +{ + printf( +"ipaddr match options:\n" +"[!] --ipsrc addr Match source address of packet\n" +"[!] --ipdst addr Match destination address of packet\n" +); +} + +static void ipaddr_mt_init(struct xt_entry_match *match) +{ + struct xt_ipaddr_mtinfo *info = (void *)match->data; + + inet_pton(PF_INET, "192.0.2.137", &info->dst.in); +} + +static int ipaddr_mt4_parse(int c, char **argv, int invert, + unsigned int *flags, const void *entry, struct xt_entry_match **match) +{ + struct xt_ipaddr_mtinfo *info = (void *)(*match)->data; + struct in_addr *addrs, mask; + unsigned int naddrs; + + switch (c) { + case '1': /* --ipsrc */ + if (*flags & XT_IPADDR_SRC) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Only use \"--ipsrc\" once!"); + *flags |= XT_IPADDR_SRC; + info->flags |= XT_IPADDR_SRC; + if (invert) + info->flags |= XT_IPADDR_SRC_INV; + xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); + if (naddrs != 1) + xtables_error(PARAMETER_PROBLEM, + "%s does not resolve to exactly " + "one address", optarg); + memcpy(&info->src.in, addrs, sizeof(*addrs)); + return true; + + + case '2': /* --ipdst */ + if (*flags & XT_IPADDR_DST) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Only use \"--ipdst\" once!"); + *flags |= XT_IPADDR_DST; + info->flags |= XT_IPADDR_DST; + if (invert) + info->flags |= XT_IPADDR_DST_INV; + addrs = xtables_numeric_to_ipaddr(optarg); + if (addrs == NULL) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Parse error at %s\n", optarg); + memcpy(&info->dst.in, addrs, sizeof(*addrs)); + return true; + } + + return false; +} + +static int ipaddr_mt6_parse(int c, char **argv, int invert, + unsigned int *flags, const void *entry, struct xt_entry_match **match) +{ + struct xt_ipaddr_mtinfo *info = (void *)(*match)->data; + struct in6_addr *addrs; + + switch (c) { + case '1': /* --ipsrc */ + if (*flags & XT_IPADDR_SRC) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Only use \"--ipsrc\" once!"); + *flags |= XT_IPADDR_SRC; + info->flags |= XT_IPADDR_SRC; + if (invert) + info->flags |= XT_IPADDR_SRC_INV; + addrs = xtables_numeric_to_ip6addr(optarg); + if (addrs == NULL) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Parse error at %s", optarg); + memcpy(&info->src.in6, addrs, sizeof(*addrs)); + return true; + + case '2': /* --ipdst */ + if (*flags & XT_IPADDR_DST) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Only use \"--ipdst\" once!"); + *flags |= XT_IPADDR_DST; + info->flags |= XT_IPADDR_DST; + if (invert) + info->flags |= XT_IPADDR_DST_INV; + addrs = xtables_numeric_to_ip6addr(optarg); + if (addrs == NULL) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: " + "Parse error at %s", optarg); + memcpy(&info->dst.in6, addrs, sizeof(*addrs)); + return true; + } + + return false; +} + +static void ipaddr_mt_check(unsigned int flags) +{ + if (flags == 0) + xtables_error(PARAMETER_PROBLEM, "xt_ipaddr: You need to " + "specify at least \"--ipsrc\" or \"--ipdst\"."); +} + +static void ipaddr_mt4_print(const void *entry, + const struct xt_entry_match *match, int numeric) +{ + const struct xt_ipaddr_mtinfo *info = (const void *)match->data; + + if (info->flags & XT_IPADDR_SRC) { + printf("src IP "); + if (info->flags & XT_IPADDR_SRC_INV) + printf("! "); + printf("%s ", numeric ? + xtables_ipaddr_to_numeric(&info->src.in) : + xtables_ipaddr_to_anyname(&info->src.in)); + } + + if (info->flags & XT_IPADDR_DST) { + printf("dst IP "); + if (info->flags & XT_IPADDR_DST_INV) + printf("! "); + printf("%s ", numeric ? + xtables_ipaddr_to_numeric(&info->dst.in) : + xtables_ipaddr_to_anyname(&info->dst.in)); + } +} + +static void ipaddr_mt6_print(const void *entry, + const struct xt_entry_match *match, int numeric) +{ + const struct xt_ipaddr_mtinfo *info = (const void *)match->data; + + if (info->flags & XT_IPADDR_SRC) { + printf("src IP "); + if (info->flags & XT_IPADDR_SRC_INV) + printf("! "); + printf("%s ", numeric ? + xtables_ip6addr_to_numeric(&info->src.in6) : + xtables_ip6addr_to_anyname(&info->src.in6)); + } + + if (info->flags & XT_IPADDR_DST) { + printf("dst IP "); + if (info->flags & XT_IPADDR_DST_INV) + printf("! "); + printf("%s ", numeric ? + xtables_ip6addr_to_numeric(&info->dst.in6) : + xtables_ip6addr_to_anyname(&info->dst.in6)); + } +} + +static void ipaddr_mt4_save(const void *entry, + const struct xt_entry_match *match) +{ + const struct xt_ipaddr_mtinfo *info = (const void *)match->data; + + if (info->flags & XT_IPADDR_SRC) { + if (info->flags & XT_IPADDR_SRC_INV) + printf("! "); + printf("--ipsrc %s ", + xtables_ipaddr_to_numeric(&info->src.in)); + } + + if (info->flags & XT_IPADDR_DST) { + if (info->flags & XT_IPADDR_DST_INV) + printf("! "); + printf("--ipdst %s ", + xtables_ipaddr_to_numeric(&info->dst.in)); + } +} + +static void ipaddr_mt6_save(const void *entry, + const struct xt_entry_match *match) +{ + const struct xt_ipaddr_mtinfo *info = (const void *)match->data; + + if (info->flags & XT_IPADDR_SRC) { + if (info->flags & XT_IPADDR_SRC_INV) + printf("! "); + printf("--ipsrc %s ", + xtables_ip6addr_to_numeric(&info->src.in6)); + } + + if (info->flags & XT_IPADDR_DST) { + if (info->flags & XT_IPADDR_DST_INV) + printf("! "); + printf("--ipdst %s ", + xtables_ip6addr_to_numeric(&info->dst.in6)); + } +} + +static struct xtables_match ipaddr_mt_reg = { + .version = XTABLES_VERSION, + .name = "ipaddr", + .revision = 0, + .family = PF_INET, + .size = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .help = ipaddr_mt_help, + .init = ipaddr_mt_init, + .parse = ipaddr_mt4_parse, + .final_check = ipaddr_mt_check, + .print = ipaddr_mt4_print, + .save = ipaddr_mt4_save, + .extra_opts = ipaddr_mt_opts, +}; + +static struct xtables_match ipaddr_mt6_reg = { + .version = XTABLES_VERSION, + .name = "ipaddr", + .revision = 0, + .family = PF_INET6, + .size = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .help = ipaddr_mt_help, + .init = ipaddr_mt_init, + .parse = ipaddr_mt6_parse, + .final_check = ipaddr_mt_check, + .print = ipaddr_mt6_print, + .save = ipaddr_mt6_save, + .extra_opts = ipaddr_mt_opts, +}; + +static void _init(void) +{ + xtables_register_match(&ipaddr_mt_reg); + xtables_register_match(&ipaddr_mt6_reg); +} diff --git a/extensions/libxt_ipaddr.man b/extensions/libxt_ipaddr.man new file mode 100644 index 0000000..9083467 --- /dev/null +++ b/extensions/libxt_ipaddr.man @@ -0,0 +1,9 @@ +.TP +[\fB!\fP] \fB--ipsrc\fP \fIaddr\fP +Match packets that have \fIaddr\fP as source address. +.TP +[\fB!\fP] \fB--ipdst\fP \fIaddr\fP +Match packets that have \fIaddr\fP as destination address. +.PP +The ipaddr module serves only as a demonstration. It is equivalent to the +iptables \fB-s\fP and \fB-d\fP options, but ipaddr does not support masks. diff --git a/extensions/xt_ipaddr.c b/extensions/xt_ipaddr.c new file mode 100644 index 0000000..77daa26 --- /dev/null +++ b/extensions/xt_ipaddr.c @@ -0,0 +1,141 @@ +/* + * "ipaddr" demo match for Xtables + * Copyright © Jan Engelhardt, 2008-2009 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the WTF Public License version 2 or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include "compat_xtables.h" +#include "xt_ipaddr.h" + +static bool ipaddr_mt4(const struct sk_buff *skb, struct xt_action_param *par) +{ + const struct xt_ipaddr_mtinfo *info = par->matchinfo; + const struct iphdr *iph = ip_hdr(skb); + + printk(KERN_INFO + "xt_ipaddr: IN=%s OUT=%s " + "SRC=" NIPQUAD_FMT " DST=" NIPQUAD_FMT " " + "IPSRC=" NIPQUAD_FMT " IPDST=" NIPQUAD_FMT "\n", + (par->in != NULL) ? par->in->name : "", + (par->out != NULL) ? par->out->name : "", + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), + NIPQUAD(info->src), NIPQUAD(info->dst)); + + if (info->flags & XT_IPADDR_SRC) + if ((iph->saddr != info->src.ip) ^ + !!(info->flags & XT_IPADDR_SRC_INV)) { + printk(KERN_NOTICE "src IP - no match\n"); + return false; + } + + if (info->flags & XT_IPADDR_DST) + if ((iph->daddr != info->dst.ip) ^ + !!(info->flags & XT_IPADDR_DST_INV)) { + printk(KERN_NOTICE "dst IP - no match\n"); + return false; + } + + return true; +} + +static bool ipaddr_mt6(const struct sk_buff *skb, struct xt_action_param *par) +{ + const struct xt_ipaddr_mtinfo *info = par->matchinfo; + const struct ipv6hdr *iph = ipv6_hdr(skb); + + printk(KERN_INFO + "xt_ipaddr: IN=%s OUT=%s " + "SRC=" NIP6_FMT " DST=" NIP6_FMT " " + "IPSRC=" NIP6_FMT " IPDST=" NIP6_FMT "\n", + (par->in != NULL) ? par->in->name : "", + (par->out != NULL) ? par->out->name : "", + NIP6(iph->saddr), NIP6(iph->daddr), + NIP6(info->src.in6), NIP6(info->dst.in6)); + + if (info->flags & XT_IPADDR_SRC) + if ((ipv6_addr_cmp(&iph->saddr, &info->src.in6) != 0) ^ + !!(info->flags & XT_IPADDR_SRC_INV)) { + printk(KERN_NOTICE "src IP - no match\n"); + return false; + } + + if (info->flags & XT_IPADDR_DST) + if ((ipv6_addr_cmp(&iph->daddr, &info->dst.in6) != 0) ^ + !!(info->flags & XT_IPADDR_DST_INV)) { + printk(KERN_NOTICE "dst IP - no match\n"); + return false; + } + + return true; +} + +static int ipaddr_mt_check(const struct xt_mtchk_param *par) +{ + const struct xt_ipaddr_mtinfo *info = par->matchinfo; + + printk(KERN_INFO "xt_ipaddr: Added a rule with -m ipaddr in " + "the %s table; this rule is reachable through hooks 0x%x\n", + par->table, par->hook_mask); + + if (par->match->family == NFPROTO_IPV4 && + ntohl(info->src.ip) == 0xDEADBEEF) { + printk(KERN_INFO "xt_ipaddr: I just thought I do not want " + "to let you match on 222.173.190.239\n"); + return -EPERM; + } + + return 0; +} + +static void ipaddr_mt_destroy(const struct xt_mtdtor_param *par) +{ + printk(KERN_INFO "One rule with ipaddr match got deleted\n"); +} + +static struct xt_match ipaddr_mt_reg[] __read_mostly = { + { + .name = "ipaddr", + .revision = 0, + .family = NFPROTO_IPV4, + .match = ipaddr_mt4, + .checkentry = ipaddr_mt_check, + .destroy = ipaddr_mt_destroy, + .matchsize = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .me = THIS_MODULE, + }, + { + .name = "ipaddr", + .revision = 0, + .family = NFPROTO_IPV6, + .match = ipaddr_mt6, + .checkentry = ipaddr_mt_check, + .destroy = ipaddr_mt_destroy, + .matchsize = XT_ALIGN(sizeof(struct xt_ipaddr_mtinfo)), + .me = THIS_MODULE, + }, +}; + +static int __init ipaddr_mt_init(void) +{ + return xt_register_matches(ipaddr_mt_reg, ARRAY_SIZE(ipaddr_mt_reg)); +} + +static void __exit ipaddr_mt_exit(void) +{ + xt_unregister_matches(ipaddr_mt_reg, ARRAY_SIZE(ipaddr_mt_reg)); +} + +module_init(ipaddr_mt_init); +module_exit(ipaddr_mt_exit); +MODULE_DESCRIPTION("Xtables: Match source/destination address"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_ipaddr"); +MODULE_ALIAS("ip6t_ipaddr"); diff --git a/extensions/xt_ipaddr.h b/extensions/xt_ipaddr.h new file mode 100644 index 0000000..76efea1 --- /dev/null +++ b/extensions/xt_ipaddr.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_NETFILTER_XT_IPADDR_H +#define _LINUX_NETFILTER_XT_IPADDR_H 1 + +enum { + XT_IPADDR_SRC = 1 << 0, + XT_IPADDR_DST = 1 << 1, + XT_IPADDR_SRC_INV = 1 << 2, + XT_IPADDR_DST_INV = 1 << 3, +}; + +struct xt_ipaddr_mtinfo { + union nf_inet_addr src, dst; + __u8 flags; +}; + +#endif /* _LINUX_NETFILTER_XT_IPADDR_H */ diff --git a/mconfig b/mconfig index 6418bb4..62575f2 100644 --- a/mconfig +++ b/mconfig @@ -17,6 +17,7 @@ build_fuzzy=m build_geoip=m build_gradm=m build_iface=m +build_ipaddr=m build_ipp2p=m build_ipv4options=m build_length2=m