1 /* Kernel module to match connection tracking information.
2 * Superset of Rusty's minimalistic state match.
4 * (C) 2001 Marc Boucher (marc@mbsi.ca).
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/skbuff.h>
13 #include <linux/netfilter_ipv4/ip_conntrack.h>
14 #include <linux/netfilter_ipv4/ip_tables.h>
15 #include <linux/netfilter_ipv4/ipt_conntrack.h>
17 MODULE_LICENSE("GPL");
18 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
19 MODULE_DESCRIPTION("iptables connection tracking match module");
22 match(const struct sk_buff
*skb
,
23 const struct net_device
*in
,
24 const struct net_device
*out
,
25 const void *matchinfo
,
29 const struct ipt_conntrack_info
*sinfo
= matchinfo
;
30 struct ip_conntrack
*ct
;
31 enum ip_conntrack_info ctinfo
;
32 unsigned int statebit
;
34 ct
= ip_conntrack_get((struct sk_buff
*)skb
, &ctinfo
);
36 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
38 if (ct
== &ip_conntrack_untracked
)
39 statebit
= IPT_CONNTRACK_STATE_UNTRACKED
;
41 statebit
= IPT_CONNTRACK_STATE_BIT(ctinfo
);
43 statebit
= IPT_CONNTRACK_STATE_INVALID
;
45 if(sinfo
->flags
& IPT_CONNTRACK_STATE
) {
47 if(ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.src
.ip
!=
48 ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
.dst
.ip
)
49 statebit
|= IPT_CONNTRACK_STATE_SNAT
;
51 if(ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.ip
!=
52 ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
.src
.ip
)
53 statebit
|= IPT_CONNTRACK_STATE_DNAT
;
56 if (FWINV((statebit
& sinfo
->statemask
) == 0, IPT_CONNTRACK_STATE
))
60 if(sinfo
->flags
& IPT_CONNTRACK_PROTO
) {
61 if (!ct
|| FWINV(ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
.dst
.protonum
!= sinfo
->tuple
[IP_CT_DIR_ORIGINAL
].dst
.protonum
, IPT_CONNTRACK_PROTO
))
65 if(sinfo
->flags
& IPT_CONNTRACK_ORIGSRC
) {
66 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
, IPT_CONNTRACK_ORIGSRC
))
70 if(sinfo
->flags
& IPT_CONNTRACK_ORIGDST
) {
71 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
, IPT_CONNTRACK_ORIGDST
))
75 if(sinfo
->flags
& IPT_CONNTRACK_REPLSRC
) {
76 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
, IPT_CONNTRACK_REPLSRC
))
80 if(sinfo
->flags
& IPT_CONNTRACK_REPLDST
) {
81 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
, IPT_CONNTRACK_REPLDST
))
85 if(sinfo
->flags
& IPT_CONNTRACK_STATUS
) {
86 if (!ct
|| FWINV((ct
->status
& sinfo
->statusmask
) == 0, IPT_CONNTRACK_STATUS
))
90 if(sinfo
->flags
& IPT_CONNTRACK_EXPIRES
) {
91 unsigned long expires
;
96 expires
= timer_pending(&ct
->timeout
) ? (ct
->timeout
.expires
- jiffies
)/HZ
: 0;
98 if (FWINV(!(expires
>= sinfo
->expires_min
&& expires
<= sinfo
->expires_max
), IPT_CONNTRACK_EXPIRES
))
105 static int check(const char *tablename
,
106 const struct ipt_ip
*ip
,
108 unsigned int matchsize
,
109 unsigned int hook_mask
)
111 if (matchsize
!= IPT_ALIGN(sizeof(struct ipt_conntrack_info
)))
117 static struct ipt_match conntrack_match
= {
120 .checkentry
= &check
,
124 static int __init
init(void)
127 return ipt_register_match(&conntrack_match
);
130 static void __exit
fini(void)
132 ipt_unregister_match(&conntrack_match
);