xref: /openbmc/linux/net/netfilter/xt_length.c (revision 2e4e6a17)
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