12e4e6a17SHarald Welte /* Kernel module to match packet length. */ 22e4e6a17SHarald Welte /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> 32e4e6a17SHarald Welte * 42e4e6a17SHarald Welte * This program is free software; you can redistribute it and/or modify 52e4e6a17SHarald Welte * it under the terms of the GNU General Public License version 2 as 62e4e6a17SHarald Welte * published by the Free Software Foundation. 72e4e6a17SHarald Welte */ 82e4e6a17SHarald Welte 92e4e6a17SHarald Welte #include <linux/module.h> 102e4e6a17SHarald Welte #include <linux/skbuff.h> 1137d8dc82SDavid S. Miller #include <linux/ipv6.h> 122e4e6a17SHarald Welte #include <net/ip.h> 132e4e6a17SHarald Welte 142e4e6a17SHarald Welte #include <linux/netfilter/xt_length.h> 152e4e6a17SHarald Welte #include <linux/netfilter/x_tables.h> 162e4e6a17SHarald Welte 172e4e6a17SHarald Welte MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 182ae15b64SJan Engelhardt MODULE_DESCRIPTION("Xtables: Packet length (Layer3,4,5) match"); 192e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 202e4e6a17SHarald Welte MODULE_ALIAS("ipt_length"); 212e4e6a17SHarald Welte MODULE_ALIAS("ip6t_length"); 222e4e6a17SHarald Welte 231d93a9cbSJan Engelhardt static bool 24d3c5ee6dSJan Engelhardt length_mt(const struct sk_buff *skb, const struct net_device *in, 25d3c5ee6dSJan Engelhardt const struct net_device *out, const struct xt_match *match, 26d3c5ee6dSJan Engelhardt const void *matchinfo, int offset, unsigned int protoff, 27cff533acSJan Engelhardt bool *hotdrop) 282e4e6a17SHarald Welte { 292e4e6a17SHarald Welte const struct xt_length_info *info = matchinfo; 30eddc9ec5SArnaldo Carvalho de Melo u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len); 312e4e6a17SHarald Welte 322e4e6a17SHarald Welte return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 332e4e6a17SHarald Welte } 342e4e6a17SHarald Welte 351d93a9cbSJan Engelhardt static bool 36d3c5ee6dSJan Engelhardt length_mt6(const struct sk_buff *skb, const struct net_device *in, 37d3c5ee6dSJan Engelhardt const struct net_device *out, const struct xt_match *match, 38d3c5ee6dSJan Engelhardt const void *matchinfo, int offset, unsigned int protoff, 39cff533acSJan Engelhardt bool *hotdrop) 402e4e6a17SHarald Welte { 412e4e6a17SHarald Welte const struct xt_length_info *info = matchinfo; 427c4e36bcSJan Engelhardt const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) + 437c4e36bcSJan Engelhardt sizeof(struct ipv6hdr); 442e4e6a17SHarald Welte 452e4e6a17SHarald Welte return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 462e4e6a17SHarald Welte } 472e4e6a17SHarald Welte 48d3c5ee6dSJan Engelhardt static struct xt_match length_mt_reg[] __read_mostly = { 494470bbc7SPatrick McHardy { 502e4e6a17SHarald Welte .name = "length", 514470bbc7SPatrick McHardy .family = AF_INET, 52d3c5ee6dSJan Engelhardt .match = length_mt, 535d04bff0SPatrick McHardy .matchsize = sizeof(struct xt_length_info), 542e4e6a17SHarald Welte .me = THIS_MODULE, 554470bbc7SPatrick McHardy }, 564470bbc7SPatrick McHardy { 572e4e6a17SHarald Welte .name = "length", 584470bbc7SPatrick McHardy .family = AF_INET6, 59d3c5ee6dSJan Engelhardt .match = length_mt6, 605d04bff0SPatrick McHardy .matchsize = sizeof(struct xt_length_info), 612e4e6a17SHarald Welte .me = THIS_MODULE, 624470bbc7SPatrick McHardy }, 632e4e6a17SHarald Welte }; 642e4e6a17SHarald Welte 65d3c5ee6dSJan Engelhardt static int __init length_mt_init(void) 662e4e6a17SHarald Welte { 67d3c5ee6dSJan Engelhardt return xt_register_matches(length_mt_reg, ARRAY_SIZE(length_mt_reg)); 682e4e6a17SHarald Welte } 692e4e6a17SHarald Welte 70d3c5ee6dSJan Engelhardt static void __exit length_mt_exit(void) 712e4e6a17SHarald Welte { 72d3c5ee6dSJan Engelhardt xt_unregister_matches(length_mt_reg, ARRAY_SIZE(length_mt_reg)); 732e4e6a17SHarald Welte } 742e4e6a17SHarald Welte 75d3c5ee6dSJan Engelhardt module_init(length_mt_init); 76d3c5ee6dSJan Engelhardt module_exit(length_mt_exit); 77