aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter.h2
-rw-r--r--include/net/netfilter/nfnetlink_queue.h8
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_queue.h1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c95
-rw-r--r--net/netfilter/nfnetlink_queue_core.c9
-rw-r--r--net/netfilter/nfnetlink_queue_ct.c15
6 files changed, 114 insertions, 16 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 655d5d198d49..e2cf786be22f 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -325,6 +325,8 @@ struct nfq_ct_hook {
325 size_t (*build_size)(const struct nf_conn *ct); 325 size_t (*build_size)(const struct nf_conn *ct);
326 int (*build)(struct sk_buff *skb, struct nf_conn *ct); 326 int (*build)(struct sk_buff *skb, struct nf_conn *ct);
327 int (*parse)(const struct nlattr *attr, struct nf_conn *ct); 327 int (*parse)(const struct nlattr *attr, struct nf_conn *ct);
328 int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct,
329 u32 portid, u32 report);
328}; 330};
329extern struct nfq_ct_hook __rcu *nfq_ct_hook; 331extern struct nfq_ct_hook __rcu *nfq_ct_hook;
330 332
diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index 86267a529514..aff88ba91391 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -15,6 +15,8 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
15 enum ip_conntrack_info ctinfo); 15 enum ip_conntrack_info ctinfo);
16void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, 16void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
17 enum ip_conntrack_info ctinfo, int diff); 17 enum ip_conntrack_info ctinfo, int diff);
18int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
19 u32 portid, u32 report);
18#else 20#else
19inline struct nf_conn * 21inline struct nf_conn *
20nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo) 22nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
@@ -39,5 +41,11 @@ inline void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
39 enum ip_conntrack_info ctinfo, int diff) 41 enum ip_conntrack_info ctinfo, int diff)
40{ 42{
41} 43}
44
45inline int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
46 u32 portid, u32 report)
47{
48 return 0;
49}
42#endif /* NF_CONNTRACK */ 50#endif /* NF_CONNTRACK */
43#endif 51#endif
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h
index 3a9b92147339..0132bad79de7 100644
--- a/include/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/include/uapi/linux/netfilter/nfnetlink_queue.h
@@ -46,6 +46,7 @@ enum nfqnl_attr_type {
46 NFQA_CT_INFO, /* enum ip_conntrack_info */ 46 NFQA_CT_INFO, /* enum ip_conntrack_info */
47 NFQA_CAP_LEN, /* __u32 length of captured packet */ 47 NFQA_CAP_LEN, /* __u32 length of captured packet */
48 NFQA_SKB_INFO, /* __u32 skb meta information */ 48 NFQA_SKB_INFO, /* __u32 skb meta information */
49 NFQA_EXP, /* nf_conntrack_netlink.h */
49 50
50 __NFQA_MAX 51 __NFQA_MAX
51}; 52};
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9aaa68bbbcdb..fa61fea63234 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1987,6 +1987,27 @@ out:
1987 return err == -EAGAIN ? -ENOBUFS : err; 1987 return err == -EAGAIN ? -ENOBUFS : err;
1988} 1988}
1989 1989
1990static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
1991 [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
1992 [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
1993 [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
1994 [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
1995 [CTA_EXPECT_ID] = { .type = NLA_U32 },
1996 [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
1997 .len = NF_CT_HELPER_NAME_LEN - 1 },
1998 [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
1999 [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
2000 [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
2001 [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
2002 [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
2003};
2004
2005static struct nf_conntrack_expect *
2006ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
2007 struct nf_conntrack_helper *helper,
2008 struct nf_conntrack_tuple *tuple,
2009 struct nf_conntrack_tuple *mask);
2010
1990#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT 2011#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
1991static size_t 2012static size_t
1992ctnetlink_nfqueue_build_size(const struct nf_conn *ct) 2013ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
@@ -2127,10 +2148,69 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)
2127 return ret; 2148 return ret;
2128} 2149}
2129 2150
2151static int ctnetlink_nfqueue_exp_parse(const struct nlattr * const *cda,
2152 const struct nf_conn *ct,
2153 struct nf_conntrack_tuple *tuple,
2154 struct nf_conntrack_tuple *mask)
2155{
2156 int err;
2157
2158 err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
2159 nf_ct_l3num(ct));
2160 if (err < 0)
2161 return err;
2162
2163 return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
2164 nf_ct_l3num(ct));
2165}
2166
2167static int
2168ctnetlink_nfqueue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
2169 u32 portid, u32 report)
2170{
2171 struct nlattr *cda[CTA_EXPECT_MAX+1];
2172 struct nf_conntrack_tuple tuple, mask;
2173 struct nf_conntrack_helper *helper;
2174 struct nf_conntrack_expect *exp;
2175 int err;
2176
2177 err = nla_parse_nested(cda, CTA_EXPECT_MAX, attr, exp_nla_policy);
2178 if (err < 0)
2179 return err;
2180
2181 err = ctnetlink_nfqueue_exp_parse((const struct nlattr * const *)cda,
2182 ct, &tuple, &mask);
2183 if (err < 0)
2184 return err;
2185
2186 if (cda[CTA_EXPECT_HELP_NAME]) {
2187 const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
2188
2189 helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
2190 nf_ct_protonum(ct));
2191 if (helper == NULL)
2192 return -EOPNOTSUPP;
2193 }
2194
2195 exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
2196 helper, &tuple, &mask);
2197 if (IS_ERR(exp))
2198 return PTR_ERR(exp);
2199
2200 err = nf_ct_expect_related_report(exp, portid, report);
2201 if (err < 0) {
2202 nf_ct_expect_put(exp);
2203 return err;
2204 }
2205
2206 return 0;
2207}
2208
2130static struct nfq_ct_hook ctnetlink_nfqueue_hook = { 2209static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
2131 .build_size = ctnetlink_nfqueue_build_size, 2210 .build_size = ctnetlink_nfqueue_build_size,
2132 .build = ctnetlink_nfqueue_build, 2211 .build = ctnetlink_nfqueue_build,
2133 .parse = ctnetlink_nfqueue_parse, 2212 .parse = ctnetlink_nfqueue_parse,
2213 .attach_expect = ctnetlink_nfqueue_attach_expect,
2134}; 2214};
2135#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */ 2215#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
2136 2216
@@ -2498,21 +2578,6 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
2498 return err; 2578 return err;
2499} 2579}
2500 2580
2501static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
2502 [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
2503 [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
2504 [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
2505 [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
2506 [CTA_EXPECT_ID] = { .type = NLA_U32 },
2507 [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
2508 .len = NF_CT_HELPER_NAME_LEN - 1 },
2509 [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
2510 [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
2511 [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
2512 [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
2513 [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
2514};
2515
2516static int 2581static int
2517ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 2582ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
2518 const struct nlmsghdr *nlh, 2583 const struct nlmsghdr *nlh,
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index ec9de12aa488..e8c9f3bb779c 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -859,6 +859,7 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
859 [NFQA_MARK] = { .type = NLA_U32 }, 859 [NFQA_MARK] = { .type = NLA_U32 },
860 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC }, 860 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
861 [NFQA_CT] = { .type = NLA_UNSPEC }, 861 [NFQA_CT] = { .type = NLA_UNSPEC },
862 [NFQA_EXP] = { .type = NLA_UNSPEC },
862}; 863};
863 864
864static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { 865static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
@@ -987,8 +988,14 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
987 if (entry == NULL) 988 if (entry == NULL)
988 return -ENOENT; 989 return -ENOENT;
989 990
990 if (nfqa[NFQA_CT]) 991 if (nfqa[NFQA_CT]) {
991 ct = nfqnl_ct_parse(entry->skb, nfqa[NFQA_CT], &ctinfo); 992 ct = nfqnl_ct_parse(entry->skb, nfqa[NFQA_CT], &ctinfo);
993 if (ct && nfqa[NFQA_EXP]) {
994 nfqnl_attach_expect(ct, nfqa[NFQA_EXP],
995 NETLINK_CB(skb).portid,
996 nlmsg_report(nlh));
997 }
998 }
992 999
993 if (nfqa[NFQA_PAYLOAD]) { 1000 if (nfqa[NFQA_PAYLOAD]) {
994 u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]); 1001 u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]);
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index ab61d66bc0b9..be893039966d 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -96,3 +96,18 @@ void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
96 if ((ct->status & IPS_NAT_MASK) && diff) 96 if ((ct->status & IPS_NAT_MASK) && diff)
97 nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff); 97 nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff);
98} 98}
99
100int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
101 u32 portid, u32 report)
102{
103 struct nfq_ct_hook *nfq_ct;
104
105 if (nf_ct_is_untracked(ct))
106 return 0;
107
108 nfq_ct = rcu_dereference(nfq_ct_hook);
109 if (nfq_ct == NULL)
110 return -EOPNOTSUPP;
111
112 return nfq_ct->attach_expect(attr, ct, portid, report);
113}