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 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 bool *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 46 static 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 63 static int __init xt_pkttype_init(void) 64 { 65 return xt_register_matches(xt_pkttype_match, 66 ARRAY_SIZE(xt_pkttype_match)); 67 } 68 69 static void __exit xt_pkttype_fini(void) 70 { 71 xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match)); 72 } 73 74 module_init(xt_pkttype_init); 75 module_exit(xt_pkttype_fini); 76