代码
先贴上代码,后续再添加解释
uname -r 3.10.0-514.el7.x86_64
用户态代码
/*xt_pktsize.h /usr/inlcude/linux/netfilter_ipv4/*/
1 #ifndef __IPT_PKTSIZE_H
2 #define __IPT_PKTSIZE_H
3
4 #define PKTSIZE_VERSION "0.1"
5
6 struct xt_pktsize_info {
7 u_int32_t min_pktsize,max_pktsize;
8 };
9
10 #endif
#include
#include
#include
#include
#include
#include
#include
#include
static void __parse_pkts(const char* s,struct xt_pktsize_info *info);
static void __print(struct xt_pktsize_info *info);
static struct option opts[] = {
{ "size", 1, NULL, '1' },
{0}
};
static void help(void)
{
printf(
"pktsize v%s options:\n"
" --size size[:size] Match packet size against value or range\n"
"\nExamples:\n"
" iptables -A FORWARD -m pktsize --size 65 -j DROP\n"
" iptables -A FORWARD -m pktsize --size 80:120 -j DROP\n"
, PKTSIZE_VERSION);
}
/* Parse CLI parameters to xt_entry_match struct. And xtables_match.name will be copied to xt_entry_match struct
* In kernel space, the same xt_entry_match will be used to find correspond kenel match mode which is xt_match
*/
static int parse(int c, char **argv, int invert, unsigned int *flags
, const void *entry
, struct xt_entry_match **match)
{
struct xt_pktsize_info *info = (struct xt_pktsize_info *)(*match)->data;
switch(c){
case '1':
if (*flags)
xtables_error(PARAMETER_PROBLEM,
"size: `--size' may only be "
"specified once");
__parse_pkts(argv[optind-1], info);
*flags = 1;
break;
default:
return 0;
}
return 1;
}
static void final_check(unsigned int flags)
{
if(!flags)
xtables_error(PARAMETER_PROBLEM,"\npktsize-parameter problem: for pktsize useage type: iptables -m pktsize --help\n");
}
static void print(const void *ip, const struct xt_entry_match *match, int numeric)
{
printf("size ");
__print((struct xt_pktsize_info*)match->data);
}
static void save(const void *ip, const struct xt_entry_match *match)
{
printf("--size ");
__print((struct xt_pktsize_info *)match->data);
}
static struct xtables_match pktsize=
{
.name = "pktsize",
.version= XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_pktsize_info)),
.userspacesize= XT_ALIGN(sizeof(struct xt_pktsize_info)),
.help = help,
.parse = parse,
.final_check= final_check,
.print = print,
.save = save,
.extra_opts = opts
};
void _init(void)
{
xtables_register_match(&pktsize);
}
static void __print(struct xt_pktsize_info *info)
{
if (info->max_pktsize == info->min_pktsize)
printf("%u ", info->min_pktsize);
else
printf("%u:%u ", info->min_pktsize, info->max_pktsize);
}
static void __parse_pkts(const char* s,struct xt_pktsize_info *info)
{
char* buff,*cp;
buff = strdup(s);
if(NULL == (cp=strchr(buff,':'))){
info->min_pktsize = info->max_pktsize = strtol(buff,NULL,0);
}else{
*cp = '\0';
cp++;
info->min_pktsize = strtol(buff,NULL,0);
info->max_pktsize = (cp[0]? strtol(cp,NULL,0):0xFFFF);
}
free(buff);
if (info->min_pktsize > info->max_pktsize)
xtables_error(PARAMETER_PROBLEM,
"pktsize min. range value `%u' greater than max. "
"range value `%u'", info->min_pktsize, info->max_pktsize);
}
内核态代码
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");
MODULE_DESCRIPTION("Netfilter Module");
static bool match(const struct sk_buff *skb,struct xt_action_param *param)
{
const struct xt_pktsize_info *info = param->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
int truesize = ntohs(iph->tot_len)-(iph->ihl*4);
if(truesize >= info->min_pktsize && truesize <= info->max_pktsize)
return 1;
else
return 0;
return 1;
}
static struct xt_match pktsize_match = {
.name = "pktsize",
.family = AF_INET,
.match = match,
.matchsize = sizeof(struct xt_pktsize_info),
.destroy= NULL,
.me = THIS_MODULE,
};
static int __init init(void)
{
return xt_register_match(&pktsize_match);
}
static void __exit fini(void)
{
xt_unregister_match(&pktsize_match);
}
module_init(init);
module_exit(fini);
使用
iptables -A INPUT -m pktsize --size 60:100 -j DROP
使用 ping -s 80 会发现不通了。