X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fnetfilter%2Fxt_conntrack.c;h=3dc2357b8de88dd163e62a18a90d17bee52db27e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=ffdebc95eb9520902944e9a9875d58589b1a90f4;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index ffdebc95e..3dc2357b8 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -20,6 +20,7 @@ #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); @@ -32,6 +33,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, @@ -44,7 +46,7 @@ match(const struct sk_buff *skb, ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); -#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) +#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &ip_conntrack_untracked) statebit = XT_CONNTRACK_STATE_UNTRACKED; @@ -53,63 +55,72 @@ match(const struct sk_buff *skb, else statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & XT_CONNTRACK_STATE) { + if (sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) + if (test_bit(IPS_SRC_NAT_BIT, &ct->status)) statebit |= XT_CONNTRACK_STATE_SNAT; - - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) + if (test_bit(IPS_DST_NAT_BIT, &ct->status)) statebit |= XT_CONNTRACK_STATE_DNAT; } - - if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, + XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & XT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) - return 0; - } - - if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) + if (ct == NULL) { + if (sinfo->flags & ~XT_CONNTRACK_STATE) return 0; + return 1; } - if(sinfo->flags & XT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) - return 0; - } - - if(sinfo->flags & XT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_PROTO && + FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, + XT_CONNTRACK_PROTO)) + return 0; + + if (sinfo->flags & XT_CONNTRACK_ORIGSRC && + FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip & + sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != + sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, + XT_CONNTRACK_ORIGSRC)) + return 0; - if(sinfo->flags & XT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_ORIGDST && + FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip & + sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, + XT_CONNTRACK_ORIGDST)) + return 0; - if(sinfo->flags & XT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_REPLSRC && + FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip & + sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != + sinfo->tuple[IP_CT_DIR_REPLY].src.ip, + XT_CONNTRACK_REPLSRC)) + return 0; - if(sinfo->flags & XT_CONNTRACK_EXPIRES) { - unsigned long expires; + if (sinfo->flags & XT_CONNTRACK_REPLDST && + FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip & + sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != + sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, + XT_CONNTRACK_REPLDST)) + return 0; - if(!ct) - return 0; + if (sinfo->flags & XT_CONNTRACK_STATUS && + FWINV((ct->status & sinfo->statusmask) == 0, + XT_CONNTRACK_STATUS)) + return 0; - expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; + if (sinfo->flags & XT_CONNTRACK_EXPIRES) { + unsigned long expires = timer_pending(&ct->timeout) ? + (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && + expires <= sinfo->expires_max), + XT_CONNTRACK_EXPIRES)) return 0; } - return 1; } @@ -118,6 +129,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, @@ -139,100 +151,116 @@ match(const struct sk_buff *skb, else statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & XT_CONNTRACK_STATE) { + if (sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) + if (test_bit(IPS_SRC_NAT_BIT, &ct->status)) statebit |= XT_CONNTRACK_STATE_SNAT; - - if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != - ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) + if (test_bit(IPS_DST_NAT_BIT, &ct->status)) statebit |= XT_CONNTRACK_STATE_DNAT; } - - if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, + XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & XT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) - return 0; - } - - if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) + if (ct == NULL) { + if (sinfo->flags & ~XT_CONNTRACK_STATE) return 0; + return 1; } - if(sinfo->flags & XT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) - return 0; - } - - if(sinfo->flags & XT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_PROTO && + FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, + XT_CONNTRACK_PROTO)) + return 0; + + if (sinfo->flags & XT_CONNTRACK_ORIGSRC && + FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip & + sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != + sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, + XT_CONNTRACK_ORIGSRC)) + return 0; - if(sinfo->flags & XT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_ORIGDST && + FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip & + sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, + XT_CONNTRACK_ORIGDST)) + return 0; - if(sinfo->flags & XT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) - return 0; - } + if (sinfo->flags & XT_CONNTRACK_REPLSRC && + FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip & + sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != + sinfo->tuple[IP_CT_DIR_REPLY].src.ip, + XT_CONNTRACK_REPLSRC)) + return 0; - if(sinfo->flags & XT_CONNTRACK_EXPIRES) { - unsigned long expires; + if (sinfo->flags & XT_CONNTRACK_REPLDST && + FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip & + sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != + sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, + XT_CONNTRACK_REPLDST)) + return 0; - if(!ct) - return 0; + if (sinfo->flags & XT_CONNTRACK_STATUS && + FWINV((ct->status & sinfo->statusmask) == 0, + XT_CONNTRACK_STATUS)) + return 0; - expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { + unsigned long expires = timer_pending(&ct->timeout) ? + (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && + expires <= sinfo->expires_max), + XT_CONNTRACK_EXPIRES)) return 0; } - return 1; } #endif /* CONFIG_NF_IP_CONNTRACK */ -static int check(const char *tablename, - const void *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) +static int +checkentry(const char *tablename, + const void *ip, + const struct xt_match *match, + void *matchinfo, + unsigned int hook_mask) { - if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) + if (nf_ct_l3proto_try_module_get(match->family) < 0) { + printk(KERN_WARNING "can't load conntrack support for " + "proto=%d\n", match->family); return 0; - + } return 1; } +static void destroy(const struct xt_match *match, void *matchinfo) +{ + nf_ct_l3proto_module_put(match->family); +} + static struct xt_match conntrack_match = { .name = "conntrack", - .match = &match, - .checkentry = &check, + .match = match, + .checkentry = checkentry, + .destroy = destroy, + .matchsize = sizeof(struct xt_conntrack_info), + .family = AF_INET, .me = THIS_MODULE, }; -static int __init init(void) +static int __init xt_conntrack_init(void) { - int ret; - need_conntrack(); - ret = xt_register_match(AF_INET, &conntrack_match); - - return ret; + return xt_register_match(&conntrack_match); } -static void __exit fini(void) +static void __exit xt_conntrack_fini(void) { - xt_unregister_match(AF_INET, &conntrack_match); + xt_unregister_match(&conntrack_match); } -module_init(init); -module_exit(fini); +module_init(xt_conntrack_init); +module_exit(xt_conntrack_fini);