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> 5f72e25a8SJan Engelhardt * 6f72e25a8SJan Engelhardt * This program is free software; you can redistribute it and/or modify 7f72e25a8SJan Engelhardt * it under the terms of the GNU General Public License version 2 as 8f72e25a8SJan Engelhardt * published by the Free Software Foundation. 9f72e25a8SJan Engelhardt */ 10f72e25a8SJan Engelhardt #include <linux/module.h> 11f72e25a8SJan Engelhardt #include <linux/skbuff.h> 12f72e25a8SJan Engelhardt #include <linux/ip.h> 13f72e25a8SJan Engelhardt #include <linux/netfilter/x_tables.h> 14f72e25a8SJan Engelhardt #include <linux/netfilter_ipv4/ipt_iprange.h> 15f72e25a8SJan Engelhardt 16f72e25a8SJan Engelhardt static bool 17f72e25a8SJan Engelhardt iprange_mt_v0(const struct sk_buff *skb, const struct net_device *in, 18f72e25a8SJan Engelhardt const struct net_device *out, const struct xt_match *match, 19f72e25a8SJan Engelhardt const void *matchinfo, int offset, unsigned int protoff, 20f72e25a8SJan Engelhardt bool *hotdrop) 21f72e25a8SJan Engelhardt { 22f72e25a8SJan Engelhardt const struct ipt_iprange_info *info = matchinfo; 23f72e25a8SJan Engelhardt const struct iphdr *iph = ip_hdr(skb); 24f72e25a8SJan Engelhardt 25f72e25a8SJan Engelhardt if (info->flags & IPRANGE_SRC) { 26f72e25a8SJan Engelhardt if ((ntohl(iph->saddr) < ntohl(info->src.min_ip) 27f72e25a8SJan Engelhardt || ntohl(iph->saddr) > ntohl(info->src.max_ip)) 28f72e25a8SJan Engelhardt ^ !!(info->flags & IPRANGE_SRC_INV)) { 29f72e25a8SJan Engelhardt pr_debug("src IP %u.%u.%u.%u NOT in range %s" 30f72e25a8SJan Engelhardt "%u.%u.%u.%u-%u.%u.%u.%u\n", 31f72e25a8SJan Engelhardt NIPQUAD(iph->saddr), 32f72e25a8SJan Engelhardt info->flags & IPRANGE_SRC_INV ? "(INV) " : "", 33f72e25a8SJan Engelhardt NIPQUAD(info->src.min_ip), 34f72e25a8SJan Engelhardt NIPQUAD(info->src.max_ip)); 35f72e25a8SJan Engelhardt return false; 36f72e25a8SJan Engelhardt } 37f72e25a8SJan Engelhardt } 38f72e25a8SJan Engelhardt if (info->flags & IPRANGE_DST) { 39f72e25a8SJan Engelhardt if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip) 40f72e25a8SJan Engelhardt || ntohl(iph->daddr) > ntohl(info->dst.max_ip)) 41f72e25a8SJan Engelhardt ^ !!(info->flags & IPRANGE_DST_INV)) { 42f72e25a8SJan Engelhardt pr_debug("dst IP %u.%u.%u.%u NOT in range %s" 43f72e25a8SJan Engelhardt "%u.%u.%u.%u-%u.%u.%u.%u\n", 44f72e25a8SJan Engelhardt NIPQUAD(iph->daddr), 45f72e25a8SJan Engelhardt info->flags & IPRANGE_DST_INV ? "(INV) " : "", 46f72e25a8SJan Engelhardt NIPQUAD(info->dst.min_ip), 47f72e25a8SJan Engelhardt NIPQUAD(info->dst.max_ip)); 48f72e25a8SJan Engelhardt return false; 49f72e25a8SJan Engelhardt } 50f72e25a8SJan Engelhardt } 51f72e25a8SJan Engelhardt return true; 52f72e25a8SJan Engelhardt } 53f72e25a8SJan Engelhardt 54f72e25a8SJan Engelhardt static struct xt_match iprange_mt_reg __read_mostly = { 55f72e25a8SJan Engelhardt .name = "iprange", 56f72e25a8SJan Engelhardt .family = AF_INET, 57f72e25a8SJan Engelhardt .match = iprange_mt_v0, 58f72e25a8SJan Engelhardt .matchsize = sizeof(struct ipt_iprange_info), 59f72e25a8SJan Engelhardt .me = THIS_MODULE 60f72e25a8SJan Engelhardt }; 61f72e25a8SJan Engelhardt 62f72e25a8SJan Engelhardt static int __init iprange_mt_init(void) 63f72e25a8SJan Engelhardt { 64f72e25a8SJan Engelhardt return xt_register_match(&iprange_mt_reg); 65f72e25a8SJan Engelhardt } 66f72e25a8SJan Engelhardt 67f72e25a8SJan Engelhardt static void __exit iprange_mt_exit(void) 68f72e25a8SJan Engelhardt { 69f72e25a8SJan Engelhardt xt_unregister_match(&iprange_mt_reg); 70f72e25a8SJan Engelhardt } 71f72e25a8SJan Engelhardt 72f72e25a8SJan Engelhardt module_init(iprange_mt_init); 73f72e25a8SJan Engelhardt module_exit(iprange_mt_exit); 74f72e25a8SJan Engelhardt MODULE_LICENSE("GPL"); 75f72e25a8SJan Engelhardt MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 76f72e25a8SJan Engelhardt MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); 77