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 18 MODULE_LICENSE("GPL"); 19 MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); 20 MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); 21 MODULE_ALIAS("ipt_pkttype"); 22 MODULE_ALIAS("ip6t_pkttype"); 23 24 static bool 25 pkttype_mt(const struct sk_buff *skb, const struct net_device *in, 26 const struct net_device *out, const struct xt_match *match, 27 const void *matchinfo, int offset, unsigned int protoff, 28 bool *hotdrop) 29 { 30 u_int8_t type; 31 const struct xt_pkttype_info *info = matchinfo; 32 33 if (skb->pkt_type == PACKET_LOOPBACK) 34 type = MULTICAST(ip_hdr(skb)->daddr) 35 ? PACKET_MULTICAST 36 : PACKET_BROADCAST; 37 else 38 type = skb->pkt_type; 39 40 return (type == info->pkttype) ^ info->invert; 41 } 42 43 static struct xt_match pkttype_mt_reg[] __read_mostly = { 44 { 45 .name = "pkttype", 46 .family = AF_INET, 47 .match = pkttype_mt, 48 .matchsize = sizeof(struct xt_pkttype_info), 49 .me = THIS_MODULE, 50 }, 51 { 52 .name = "pkttype", 53 .family = AF_INET6, 54 .match = pkttype_mt, 55 .matchsize = sizeof(struct xt_pkttype_info), 56 .me = THIS_MODULE, 57 }, 58 }; 59 60 static int __init pkttype_mt_init(void) 61 { 62 return xt_register_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg)); 63 } 64 65 static void __exit pkttype_mt_exit(void) 66 { 67 xt_unregister_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg)); 68 } 69 70 module_init(pkttype_mt_init); 71 module_exit(pkttype_mt_exit); 72