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 15#include <linux/netfilter_bridge/ebtables.h> 16#include <linux/netfilter_bridge/ebt_ip.h> 17#include <linux/ip.h> 18#include <net/ip.h> 19#include <linux/in.h> 20#include <linux/module.h> 21 22struct tcpudphdr { 23 __be16 src; 24 __be16 dst; 25}; 26 27static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, 28 const struct net_device *out, const void *data, 29 unsigned int datalen) 30{ 31 struct ebt_ip_info *info = (struct ebt_ip_info *)data; 32 struct iphdr _iph, *ih; 33 struct tcpudphdr _ports, *pptr; 34 35 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 36 if (ih == NULL) 37 return EBT_NOMATCH; 38 if (info->bitmask & EBT_IP_TOS && 39 FWINV(info->tos != ih->tos, EBT_IP_TOS)) 40 return EBT_NOMATCH; 41 if (info->bitmask & EBT_IP_SOURCE && 42 FWINV((ih->saddr & info->smsk) != 43 info->saddr, EBT_IP_SOURCE)) 44 return EBT_NOMATCH; 45 if ((info->bitmask & EBT_IP_DEST) && 46 FWINV((ih->daddr & info->dmsk) != 47 info->daddr, EBT_IP_DEST)) 48 return EBT_NOMATCH; 49 if (info->bitmask & EBT_IP_PROTO) { 50 if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) 51 return EBT_NOMATCH; 52 if (!(info->bitmask & EBT_IP_DPORT) && 53 !(info->bitmask & EBT_IP_SPORT)) 54 return EBT_MATCH; 55 if (ntohs(ih->frag_off) & IP_OFFSET) 56 return EBT_NOMATCH; 57 pptr = skb_header_pointer(skb, ih->ihl*4, 58 sizeof(_ports), &_ports); 59 if (pptr == NULL) 60 return EBT_NOMATCH; 61 if (info->bitmask & EBT_IP_DPORT) { 62 u32 dst = ntohs(pptr->dst); 63 if (FWINV(dst < info->dport[0] || 64 dst > info->dport[1], 65 EBT_IP_DPORT)) 66 return EBT_NOMATCH; 67 } 68 if (info->bitmask & EBT_IP_SPORT) { 69 u32 src = ntohs(pptr->src); 70 if (FWINV(src < info->sport[0] || 71 src > info->sport[1], 72 EBT_IP_SPORT)) 73 return EBT_NOMATCH; 74 } 75 } 76 return EBT_MATCH; 77} 78 79static int ebt_ip_check(const char *tablename, unsigned int hookmask, 80 const struct ebt_entry *e, void *data, unsigned int datalen) 81{ 82 struct ebt_ip_info *info = (struct ebt_ip_info *)data; 83 84 if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info))) 85 return -EINVAL; 86 if (e->ethproto != htons(ETH_P_IP) || 87 e->invflags & EBT_IPROTO) 88 return -EINVAL; 89 if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) 90 return -EINVAL; 91 if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { 92 if (info->invflags & EBT_IP_PROTO) 93 return -EINVAL; 94 if (info->protocol != IPPROTO_TCP && 95 info->protocol != IPPROTO_UDP && 96 info->protocol != IPPROTO_UDPLITE && 97 info->protocol != IPPROTO_SCTP && 98 info->protocol != IPPROTO_DCCP) 99 return -EINVAL; 100 } 101 if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) 102 return -EINVAL; 103 if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) 104 return -EINVAL; 105 return 0; 106} 107 108static struct ebt_match filter_ip = 109{ 110 .name = EBT_IP_MATCH, 111 .match = ebt_filter_ip, 112 .check = ebt_ip_check, 113 .me = THIS_MODULE, 114}; 115 116static int __init ebt_ip_init(void) 117{ 118 return ebt_register_match(&filter_ip); 119} 120 121static void __exit ebt_ip_fini(void) 122{ 123 ebt_unregister_match(&filter_ip); 124} 125 126module_init(ebt_ip_init); 127module_exit(ebt_ip_fini); 128MODULE_LICENSE("GPL"); 129