summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/linux/include/linux/netfilter_bridge/ebt_ip.h21
-rw-r--r--kernel/linux/net/bridge/netfilter/ebt_ip.c54
2 files changed, 71 insertions, 4 deletions
diff --git a/kernel/linux/include/linux/netfilter_bridge/ebt_ip.h b/kernel/linux/include/linux/netfilter_bridge/ebt_ip.h
index b2791e0..499089b 100644
--- a/kernel/linux/include/linux/netfilter_bridge/ebt_ip.h
+++ b/kernel/linux/include/linux/netfilter_bridge/ebt_ip.h
@@ -1,3 +1,17 @@
+/*
+ * ebt_ip
+ *
+ * Authors:
+ * Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *
+ * April, 2002
+ *
+ * Changes:
+ * added ip-sport and ip-dport
+ * Innominate Security Technologies AG <mhopf@innominate.com>
+ * September, 2002
+ */
+
#ifndef __LINUX_BRIDGE_EBT_IP_H
#define __LINUX_BRIDGE_EBT_IP_H
@@ -5,7 +19,10 @@
#define EBT_IP_DEST 0x02
#define EBT_IP_TOS 0x04
#define EBT_IP_PROTO 0x08
-#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO)
+#define EBT_IP_SPORT 0x10
+#define EBT_IP_DPORT 0x20
+#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
+ EBT_IP_SPORT | EBT_IP_DPORT )
#define EBT_IP_MATCH "ip"
// the same values are used for the invflags
@@ -19,6 +36,8 @@ struct ebt_ip_info
uint8_t protocol;
uint8_t bitmask;
uint8_t invflags;
+ uint16_t sport[2];
+ uint16_t dport[2];
};
#endif
diff --git a/kernel/linux/net/bridge/netfilter/ebt_ip.c b/kernel/linux/net/bridge/netfilter/ebt_ip.c
index 329ecd6..59c27bd 100644
--- a/kernel/linux/net/bridge/netfilter/ebt_ip.c
+++ b/kernel/linux/net/bridge/netfilter/ebt_ip.c
@@ -6,13 +6,28 @@
*
* April, 2002
*
+ * Changes:
+ * added ip-sport and ip-dport
+ * Innominate Security Technologies AG <mhopf@innominate.com>
+ * September, 2002
*/
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_ip.h>
#include <linux/ip.h>
+#include <linux/in.h>
#include <linux/module.h>
+struct tcpudphdr {
+ uint16_t src;
+ uint16_t dst;
+};
+
+union h_u {
+ unsigned char *raw;
+ struct tcpudphdr *tuh;
+};
+
static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *data,
unsigned int datalen)
@@ -22,9 +37,31 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
if (info->bitmask & EBT_IP_TOS &&
FWINV(info->tos != ((*skb).nh.iph)->tos, EBT_IP_TOS))
return EBT_NOMATCH;
- if (info->bitmask & EBT_IP_PROTO && FWINV(info->protocol !=
- ((*skb).nh.iph)->protocol, EBT_IP_PROTO))
- return EBT_NOMATCH;
+ if (info->bitmask & EBT_IP_PROTO) {
+ if (FWINV(info->protocol != ((*skb).nh.iph)->protocol,
+ EBT_IP_PROTO))
+ return EBT_NOMATCH;
+ if ( info->protocol == IPPROTO_TCP ||
+ info->protocol == IPPROTO_UDP )
+ {
+ union h_u h;
+ h.raw = skb->data + skb->nh.iph->ihl*4;
+ if (info->bitmask & EBT_IP_DPORT) {
+ uint16_t port = ntohs(h.tuh->dst);
+ if (FWINV(port < info->dport[0] ||
+ port > info->dport[1],
+ EBT_IP_DPORT))
+ return EBT_NOMATCH;
+ }
+ if (info->bitmask & EBT_IP_SPORT) {
+ uint16_t port = ntohs(h.tuh->src);
+ if (FWINV(port < info->sport[0] ||
+ port > info->sport[1],
+ EBT_IP_SPORT))
+ return EBT_NOMATCH;
+ }
+ }
+ }
if (info->bitmask & EBT_IP_SOURCE &&
FWINV((((*skb).nh.iph)->saddr & info->smsk) !=
info->saddr, EBT_IP_SOURCE))
@@ -48,6 +85,17 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
return -EINVAL;
if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
return -EINVAL;
+ if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
+ if (!info->bitmask & EBT_IPROTO)
+ return -EINVAL;
+ if (info->protocol != IPPROTO_TCP &&
+ info->protocol != IPPROTO_UDP)
+ return -EINVAL;
+ }
+ if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
+ return -EINVAL;
+ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
+ return -EINVAL;
return 0;
}