1/* (C) 1999-2001 Michal Ludvig <michal@logix.cz>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8#include <linux/module.h>
9#include <linux/skbuff.h>
10#include <linux/if_ether.h>
11#include <linux/if_packet.h>
12#include <linux/in.h>
13#include <linux/ip.h>
14
15#include <linux/netfilter/xt_pkttype.h>
16#include <linux/netfilter/x_tables.h>
17
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
20MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
21MODULE_ALIAS("ipt_pkttype");
22MODULE_ALIAS("ip6t_pkttype");
23
24static int match(const struct sk_buff *skb,
25      const struct net_device *in,
26      const struct net_device *out,
27      const struct xt_match *match,
28      const void *matchinfo,
29      int offset,
30      unsigned int protoff,
31      int *hotdrop)
32{
33	u_int8_t type;
34	const struct xt_pkttype_info *info = matchinfo;
35
36	if (skb->pkt_type == PACKET_LOOPBACK)
37		type = (MULTICAST(ip_hdr(skb)->daddr)
38			? PACKET_MULTICAST
39			: PACKET_BROADCAST);
40	else
41		type = skb->pkt_type;
42
43	return (type == info->pkttype) ^ info->invert;
44}
45
46static struct xt_match xt_pkttype_match[] = {
47	{
48		.name		= "pkttype",
49		.family		= AF_INET,
50		.match		= match,
51		.matchsize	= sizeof(struct xt_pkttype_info),
52		.me		= THIS_MODULE,
53	},
54	{
55		.name		= "pkttype",
56		.family		= AF_INET6,
57		.match		= match,
58		.matchsize	= sizeof(struct xt_pkttype_info),
59		.me		= THIS_MODULE,
60	},
61};
62
63static int __init xt_pkttype_init(void)
64{
65	return xt_register_matches(xt_pkttype_match,
66				   ARRAY_SIZE(xt_pkttype_match));
67}
68
69static void __exit xt_pkttype_fini(void)
70{
71	xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match));
72}
73
74module_init(xt_pkttype_init);
75module_exit(xt_pkttype_fini);
76