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