1f72e25a8SJan Engelhardt /* 2f72e25a8SJan Engelhardt * xt_iprange - Netfilter module to match IP address ranges 3f72e25a8SJan Engelhardt * 4f72e25a8SJan Engelhardt * (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 51a50c5a1SJan Engelhardt * (C) CC Computer Consultants GmbH, 2008 6f72e25a8SJan Engelhardt * 7f72e25a8SJan Engelhardt * This program is free software; you can redistribute it and/or modify 8f72e25a8SJan Engelhardt * it under the terms of the GNU General Public License version 2 as 9f72e25a8SJan Engelhardt * published by the Free Software Foundation. 10f72e25a8SJan Engelhardt */ 11ff67e4e4SJan Engelhardt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12f72e25a8SJan Engelhardt #include <linux/module.h> 13f72e25a8SJan Engelhardt #include <linux/skbuff.h> 14f72e25a8SJan Engelhardt #include <linux/ip.h> 151a50c5a1SJan Engelhardt #include <linux/ipv6.h> 16f72e25a8SJan Engelhardt #include <linux/netfilter/x_tables.h> 175da621f1SJan Engelhardt #include <linux/netfilter/xt_iprange.h> 18f72e25a8SJan Engelhardt 191a50c5a1SJan Engelhardt static bool 2062fc8051SJan Engelhardt iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par) 211a50c5a1SJan Engelhardt { 22f7108a20SJan Engelhardt const struct xt_iprange_mtinfo *info = par->matchinfo; 231a50c5a1SJan Engelhardt const struct iphdr *iph = ip_hdr(skb); 241a50c5a1SJan Engelhardt bool m; 251a50c5a1SJan Engelhardt 261a50c5a1SJan Engelhardt if (info->flags & IPRANGE_SRC) { 271a50c5a1SJan Engelhardt m = ntohl(iph->saddr) < ntohl(info->src_min.ip); 281a50c5a1SJan Engelhardt m |= ntohl(iph->saddr) > ntohl(info->src_max.ip); 296def1eb4SAlexey Dobriyan m ^= !!(info->flags & IPRANGE_SRC_INV); 301a50c5a1SJan Engelhardt if (m) { 3114d5e834SHarvey Harrison pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n", 3214d5e834SHarvey Harrison &iph->saddr, 331a50c5a1SJan Engelhardt (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "", 3414d5e834SHarvey Harrison &info->src_max.ip, 3514d5e834SHarvey Harrison &info->src_max.ip); 361a50c5a1SJan Engelhardt return false; 371a50c5a1SJan Engelhardt } 381a50c5a1SJan Engelhardt } 391a50c5a1SJan Engelhardt if (info->flags & IPRANGE_DST) { 401a50c5a1SJan Engelhardt m = ntohl(iph->daddr) < ntohl(info->dst_min.ip); 411a50c5a1SJan Engelhardt m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip); 426def1eb4SAlexey Dobriyan m ^= !!(info->flags & IPRANGE_DST_INV); 431a50c5a1SJan Engelhardt if (m) { 4414d5e834SHarvey Harrison pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n", 4514d5e834SHarvey Harrison &iph->daddr, 461a50c5a1SJan Engelhardt (info->flags & IPRANGE_DST_INV) ? "(INV) " : "", 4714d5e834SHarvey Harrison &info->dst_min.ip, 4814d5e834SHarvey Harrison &info->dst_max.ip); 491a50c5a1SJan Engelhardt return false; 501a50c5a1SJan Engelhardt } 511a50c5a1SJan Engelhardt } 521a50c5a1SJan Engelhardt return true; 531a50c5a1SJan Engelhardt } 541a50c5a1SJan Engelhardt 551a50c5a1SJan Engelhardt static inline int 5608b5194bSThomas Jacob iprange_ipv6_lt(const struct in6_addr *a, const struct in6_addr *b) 571a50c5a1SJan Engelhardt { 581a50c5a1SJan Engelhardt unsigned int i; 591a50c5a1SJan Engelhardt 601a50c5a1SJan Engelhardt for (i = 0; i < 4; ++i) { 6108b5194bSThomas Jacob if (a->s6_addr32[i] != b->s6_addr32[i]) 6208b5194bSThomas Jacob return ntohl(a->s6_addr32[i]) < ntohl(b->s6_addr32[i]); 631a50c5a1SJan Engelhardt } 641a50c5a1SJan Engelhardt 651a50c5a1SJan Engelhardt return 0; 661a50c5a1SJan Engelhardt } 671a50c5a1SJan Engelhardt 681a50c5a1SJan Engelhardt static bool 6962fc8051SJan Engelhardt iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par) 701a50c5a1SJan Engelhardt { 71f7108a20SJan Engelhardt const struct xt_iprange_mtinfo *info = par->matchinfo; 721a50c5a1SJan Engelhardt const struct ipv6hdr *iph = ipv6_hdr(skb); 731a50c5a1SJan Engelhardt bool m; 741a50c5a1SJan Engelhardt 751a50c5a1SJan Engelhardt if (info->flags & IPRANGE_SRC) { 7608b5194bSThomas Jacob m = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6); 7708b5194bSThomas Jacob m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr); 786def1eb4SAlexey Dobriyan m ^= !!(info->flags & IPRANGE_SRC_INV); 791a50c5a1SJan Engelhardt if (m) 801a50c5a1SJan Engelhardt return false; 811a50c5a1SJan Engelhardt } 821a50c5a1SJan Engelhardt if (info->flags & IPRANGE_DST) { 8308b5194bSThomas Jacob m = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6); 8408b5194bSThomas Jacob m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr); 856def1eb4SAlexey Dobriyan m ^= !!(info->flags & IPRANGE_DST_INV); 861a50c5a1SJan Engelhardt if (m) 871a50c5a1SJan Engelhardt return false; 881a50c5a1SJan Engelhardt } 891a50c5a1SJan Engelhardt return true; 901a50c5a1SJan Engelhardt } 911a50c5a1SJan Engelhardt 921a50c5a1SJan Engelhardt static struct xt_match iprange_mt_reg[] __read_mostly = { 931a50c5a1SJan Engelhardt { 94f72e25a8SJan Engelhardt .name = "iprange", 951a50c5a1SJan Engelhardt .revision = 1, 96ee999d8bSJan Engelhardt .family = NFPROTO_IPV4, 971a50c5a1SJan Engelhardt .match = iprange_mt4, 981a50c5a1SJan Engelhardt .matchsize = sizeof(struct xt_iprange_mtinfo), 991a50c5a1SJan Engelhardt .me = THIS_MODULE, 1001a50c5a1SJan Engelhardt }, 1011a50c5a1SJan Engelhardt { 1021a50c5a1SJan Engelhardt .name = "iprange", 1031a50c5a1SJan Engelhardt .revision = 1, 104ee999d8bSJan Engelhardt .family = NFPROTO_IPV6, 1051a50c5a1SJan Engelhardt .match = iprange_mt6, 1061a50c5a1SJan Engelhardt .matchsize = sizeof(struct xt_iprange_mtinfo), 1071a50c5a1SJan Engelhardt .me = THIS_MODULE, 1081a50c5a1SJan Engelhardt }, 109f72e25a8SJan Engelhardt }; 110f72e25a8SJan Engelhardt 111f72e25a8SJan Engelhardt static int __init iprange_mt_init(void) 112f72e25a8SJan Engelhardt { 1131a50c5a1SJan Engelhardt return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); 114f72e25a8SJan Engelhardt } 115f72e25a8SJan Engelhardt 116f72e25a8SJan Engelhardt static void __exit iprange_mt_exit(void) 117f72e25a8SJan Engelhardt { 1181a50c5a1SJan Engelhardt xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); 119f72e25a8SJan Engelhardt } 120f72e25a8SJan Engelhardt 121f72e25a8SJan Engelhardt module_init(iprange_mt_init); 122f72e25a8SJan Engelhardt module_exit(iprange_mt_exit); 123f72e25a8SJan Engelhardt MODULE_LICENSE("GPL"); 12436d4084dSJan Engelhardt MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 12536d4084dSJan Engelhardt MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); 126f72e25a8SJan Engelhardt MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); 12701b7a314SPhil Oester MODULE_ALIAS("ipt_iprange"); 12801b7a314SPhil Oester MODULE_ALIAS("ip6t_iprange"); 129