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> 112e4e6a17SHarald Welte #include <net/ip.h> 122e4e6a17SHarald Welte 132e4e6a17SHarald Welte #include <linux/netfilter/xt_length.h> 142e4e6a17SHarald Welte #include <linux/netfilter/x_tables.h> 152e4e6a17SHarald Welte 162e4e6a17SHarald Welte MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 172e4e6a17SHarald Welte MODULE_DESCRIPTION("IP tables packet length matching module"); 182e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 192e4e6a17SHarald Welte MODULE_ALIAS("ipt_length"); 202e4e6a17SHarald Welte MODULE_ALIAS("ip6t_length"); 212e4e6a17SHarald Welte 222e4e6a17SHarald Welte static int 232e4e6a17SHarald Welte match(const struct sk_buff *skb, 242e4e6a17SHarald Welte const struct net_device *in, 252e4e6a17SHarald Welte const struct net_device *out, 262e4e6a17SHarald Welte const void *matchinfo, 272e4e6a17SHarald Welte int offset, 282e4e6a17SHarald Welte unsigned int protoff, 292e4e6a17SHarald Welte int *hotdrop) 302e4e6a17SHarald Welte { 312e4e6a17SHarald Welte const struct xt_length_info *info = matchinfo; 322e4e6a17SHarald Welte u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); 332e4e6a17SHarald Welte 342e4e6a17SHarald Welte return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 352e4e6a17SHarald Welte } 362e4e6a17SHarald Welte 372e4e6a17SHarald Welte static int 382e4e6a17SHarald Welte match6(const struct sk_buff *skb, 392e4e6a17SHarald Welte const struct net_device *in, 402e4e6a17SHarald Welte const struct net_device *out, 412e4e6a17SHarald Welte const void *matchinfo, 422e4e6a17SHarald Welte int offset, 432e4e6a17SHarald Welte unsigned int protoff, 442e4e6a17SHarald Welte int *hotdrop) 452e4e6a17SHarald Welte { 462e4e6a17SHarald Welte const struct xt_length_info *info = matchinfo; 472e4e6a17SHarald Welte u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); 482e4e6a17SHarald Welte 492e4e6a17SHarald Welte return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 502e4e6a17SHarald Welte } 512e4e6a17SHarald Welte 522e4e6a17SHarald Welte static int 532e4e6a17SHarald Welte checkentry(const char *tablename, 542e4e6a17SHarald Welte const void *ip, 552e4e6a17SHarald Welte void *matchinfo, 562e4e6a17SHarald Welte unsigned int matchsize, 572e4e6a17SHarald Welte unsigned int hook_mask) 582e4e6a17SHarald Welte { 592e4e6a17SHarald Welte if (matchsize != XT_ALIGN(sizeof(struct xt_length_info))) 602e4e6a17SHarald Welte return 0; 612e4e6a17SHarald Welte 622e4e6a17SHarald Welte return 1; 632e4e6a17SHarald Welte } 642e4e6a17SHarald Welte 652e4e6a17SHarald Welte static struct xt_match length_match = { 662e4e6a17SHarald Welte .name = "length", 672e4e6a17SHarald Welte .match = &match, 682e4e6a17SHarald Welte .checkentry = &checkentry, 692e4e6a17SHarald Welte .me = THIS_MODULE, 702e4e6a17SHarald Welte }; 712e4e6a17SHarald Welte static struct xt_match length6_match = { 722e4e6a17SHarald Welte .name = "length", 732e4e6a17SHarald Welte .match = &match6, 742e4e6a17SHarald Welte .checkentry = &checkentry, 752e4e6a17SHarald Welte .me = THIS_MODULE, 762e4e6a17SHarald Welte }; 772e4e6a17SHarald Welte 782e4e6a17SHarald Welte static int __init init(void) 792e4e6a17SHarald Welte { 802e4e6a17SHarald Welte int ret; 812e4e6a17SHarald Welte ret = xt_register_match(AF_INET, &length_match); 822e4e6a17SHarald Welte if (ret) 832e4e6a17SHarald Welte return ret; 842e4e6a17SHarald Welte ret = xt_register_match(AF_INET6, &length6_match); 852e4e6a17SHarald Welte if (ret) 862e4e6a17SHarald Welte xt_unregister_match(AF_INET, &length_match); 872e4e6a17SHarald Welte 882e4e6a17SHarald Welte return ret; 892e4e6a17SHarald Welte } 902e4e6a17SHarald Welte 912e4e6a17SHarald Welte static void __exit fini(void) 922e4e6a17SHarald Welte { 932e4e6a17SHarald Welte xt_unregister_match(AF_INET, &length_match); 942e4e6a17SHarald Welte xt_unregister_match(AF_INET6, &length6_match); 952e4e6a17SHarald Welte } 962e4e6a17SHarald Welte 972e4e6a17SHarald Welte module_init(init); 982e4e6a17SHarald Welte module_exit(fini); 99