1 /* 2 * ebt_ip 3 * 4 * Authors: 5 * Bart De Schuymer <bdschuym@pandora.be> 6 * 7 * April, 2002 8 * 9 * Changes: 10 * added ip-sport and ip-dport 11 * Innominate Security Technologies AG <mhopf@innominate.com> 12 * September, 2002 13 */ 14 #include <linux/ip.h> 15 #include <net/ip.h> 16 #include <linux/in.h> 17 #include <linux/module.h> 18 #include <linux/netfilter/x_tables.h> 19 #include <linux/netfilter_bridge/ebtables.h> 20 #include <linux/netfilter_bridge/ebt_ip.h> 21 22 struct tcpudphdr { 23 __be16 src; 24 __be16 dst; 25 }; 26 27 static bool 28 ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) 29 { 30 const struct ebt_ip_info *info = par->matchinfo; 31 const struct iphdr *ih; 32 struct iphdr _iph; 33 const struct tcpudphdr *pptr; 34 struct tcpudphdr _ports; 35 36 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 37 if (ih == NULL) 38 return false; 39 if ((info->bitmask & EBT_IP_TOS) && 40 NF_INVF(info, EBT_IP_TOS, info->tos != ih->tos)) 41 return false; 42 if ((info->bitmask & EBT_IP_SOURCE) && 43 NF_INVF(info, EBT_IP_SOURCE, 44 (ih->saddr & info->smsk) != info->saddr)) 45 return false; 46 if ((info->bitmask & EBT_IP_DEST) && 47 NF_INVF(info, EBT_IP_DEST, 48 (ih->daddr & info->dmsk) != info->daddr)) 49 return false; 50 if (info->bitmask & EBT_IP_PROTO) { 51 if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) 52 return false; 53 if (!(info->bitmask & EBT_IP_DPORT) && 54 !(info->bitmask & EBT_IP_SPORT)) 55 return true; 56 if (ntohs(ih->frag_off) & IP_OFFSET) 57 return false; 58 pptr = skb_header_pointer(skb, ih->ihl*4, 59 sizeof(_ports), &_ports); 60 if (pptr == NULL) 61 return false; 62 if (info->bitmask & EBT_IP_DPORT) { 63 u32 dst = ntohs(pptr->dst); 64 if (NF_INVF(info, EBT_IP_DPORT, 65 dst < info->dport[0] || 66 dst > info->dport[1])) 67 return false; 68 } 69 if (info->bitmask & EBT_IP_SPORT) { 70 u32 src = ntohs(pptr->src); 71 if (NF_INVF(info, EBT_IP_SPORT, 72 src < info->sport[0] || 73 src > info->sport[1])) 74 return false; 75 } 76 } 77 return true; 78 } 79 80 static int ebt_ip_mt_check(const struct xt_mtchk_param *par) 81 { 82 const struct ebt_ip_info *info = par->matchinfo; 83 const struct ebt_entry *e = par->entryinfo; 84 85 if (e->ethproto != htons(ETH_P_IP) || 86 e->invflags & EBT_IPROTO) 87 return -EINVAL; 88 if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) 89 return -EINVAL; 90 if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { 91 if (info->invflags & EBT_IP_PROTO) 92 return -EINVAL; 93 if (info->protocol != IPPROTO_TCP && 94 info->protocol != IPPROTO_UDP && 95 info->protocol != IPPROTO_UDPLITE && 96 info->protocol != IPPROTO_SCTP && 97 info->protocol != IPPROTO_DCCP) 98 return -EINVAL; 99 } 100 if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) 101 return -EINVAL; 102 if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) 103 return -EINVAL; 104 return 0; 105 } 106 107 static struct xt_match ebt_ip_mt_reg __read_mostly = { 108 .name = "ip", 109 .revision = 0, 110 .family = NFPROTO_BRIDGE, 111 .match = ebt_ip_mt, 112 .checkentry = ebt_ip_mt_check, 113 .matchsize = sizeof(struct ebt_ip_info), 114 .me = THIS_MODULE, 115 }; 116 117 static int __init ebt_ip_init(void) 118 { 119 return xt_register_match(&ebt_ip_mt_reg); 120 } 121 122 static void __exit ebt_ip_fini(void) 123 { 124 xt_unregister_match(&ebt_ip_mt_reg); 125 } 126 127 module_init(ebt_ip_init); 128 module_exit(ebt_ip_fini); 129 MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match"); 130 MODULE_LICENSE("GPL"); 131