Skip to content
This repository was archived by the owner on Oct 30, 2021. It is now read-only.

Commit c1d10ad

Browse files
ummakynesdavem330
authored andcommitted
[NETFILTER]: Add ctnetlink port for nf_conntrack
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 205d67c commit c1d10ad

16 files changed

+2289
-63
lines changed

include/linux/netfilter/nfnetlink_conntrack.h

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ enum ctattr_l4proto {
6464
CTA_PROTO_ICMP_ID,
6565
CTA_PROTO_ICMP_TYPE,
6666
CTA_PROTO_ICMP_CODE,
67+
CTA_PROTO_ICMPV6_ID,
68+
CTA_PROTO_ICMPV6_TYPE,
69+
CTA_PROTO_ICMPV6_CODE,
6770
__CTA_PROTO_MAX
6871
};
6972
#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)

include/net/netfilter/nf_conntrack.h

+31
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ struct nf_conn
9494
/* Current number of expected connections */
9595
unsigned int expecting;
9696

97+
/* Unique ID that identifies this conntrack*/
98+
unsigned int id;
99+
97100
/* Helper. if any */
98101
struct nf_conntrack_helper *helper;
99102

@@ -140,6 +143,9 @@ struct nf_conntrack_expect
140143
/* Usage count. */
141144
atomic_t use;
142145

146+
/* Unique ID */
147+
unsigned int id;
148+
143149
/* Flags */
144150
unsigned int flags;
145151

@@ -190,6 +196,31 @@ static inline void nf_ct_put(struct nf_conn *ct)
190196
nf_conntrack_put(&ct->ct_general);
191197
}
192198

199+
extern struct nf_conntrack_tuple_hash *
200+
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
201+
const struct nf_conn *ignored_conntrack);
202+
203+
extern void nf_conntrack_hash_insert(struct nf_conn *ct);
204+
205+
extern struct nf_conntrack_expect *
206+
__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
207+
208+
extern struct nf_conntrack_expect *
209+
nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
210+
211+
extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
212+
213+
extern void nf_ct_remove_expectations(struct nf_conn *ct);
214+
215+
extern void nf_conntrack_flush(void);
216+
217+
extern struct nf_conntrack_helper *
218+
nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
219+
extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
220+
221+
extern struct nf_conntrack_helper *
222+
__nf_conntrack_helper_find_byname(const char *name);
223+
193224
/* call to create an explicit dependency on nf_conntrack. */
194225
extern void need_nf_conntrack(void);
195226

include/net/netfilter/nf_conntrack_helper.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ struct nf_conntrack_helper
3333
unsigned int protoff,
3434
struct nf_conn *ct,
3535
enum ip_conntrack_info conntrackinfo);
36+
37+
int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
3638
};
3739

3840
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);

include/net/netfilter/nf_conntrack_l3proto.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <linux/seq_file.h>
1515
#include <net/netfilter/nf_conntrack.h>
1616

17+
struct nfattr;
18+
1719
struct nf_conntrack_l3proto
1820
{
1921
/* Next pointer. */
@@ -70,6 +72,12 @@ struct nf_conntrack_l3proto
7072

7173
u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
7274

75+
int (*tuple_to_nfattr)(struct sk_buff *skb,
76+
const struct nf_conntrack_tuple *t);
77+
78+
int (*nfattr_to_tuple)(struct nfattr *tb[],
79+
struct nf_conntrack_tuple *t);
80+
7381
/* Module (if any) which this is connected to. */
7482
struct module *me;
7583
};
@@ -81,11 +89,16 @@ extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
8189
extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
8290

8391
static inline struct nf_conntrack_l3proto *
84-
nf_ct_find_l3proto(u_int16_t l3proto)
92+
__nf_ct_l3proto_find(u_int16_t l3proto)
8593
{
8694
return nf_ct_l3protos[l3proto];
8795
}
8896

97+
extern struct nf_conntrack_l3proto *
98+
nf_ct_l3proto_find_get(u_int16_t l3proto);
99+
100+
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
101+
89102
/* Existing built-in protocols */
90103
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
91104
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;

include/net/netfilter/nf_conntrack_protocol.h

+25-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <net/netfilter/nf_conntrack.h>
1313

1414
struct seq_file;
15+
struct nfattr;
1516

1617
struct nf_conntrack_protocol
1718
{
@@ -66,6 +67,18 @@ struct nf_conntrack_protocol
6667
enum ip_conntrack_info *ctinfo,
6768
int pf, unsigned int hooknum);
6869

70+
/* convert protoinfo to nfnetink attributes */
71+
int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
72+
const struct nf_conn *ct);
73+
74+
/* convert nfnetlink attributes to protoinfo */
75+
int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
76+
77+
int (*tuple_to_nfattr)(struct sk_buff *skb,
78+
const struct nf_conntrack_tuple *t);
79+
int (*nfattr_to_tuple)(struct nfattr *tb[],
80+
struct nf_conntrack_tuple *t);
81+
6982
/* Module (if any) which this is connected to. */
7083
struct module *me;
7184
};
@@ -80,12 +93,23 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
8093
extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
8194

8295
extern struct nf_conntrack_protocol *
83-
nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
96+
__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
97+
98+
extern struct nf_conntrack_protocol *
99+
nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
100+
101+
extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
84102

85103
/* Protocol registration. */
86104
extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
87105
extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
88106

107+
/* Generic netlink helpers */
108+
extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
109+
const struct nf_conntrack_tuple *tuple);
110+
extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
111+
struct nf_conntrack_tuple *t);
112+
89113
/* Log invalid packets */
90114
extern unsigned int nf_ct_log_invalid;
91115

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c

+47
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,48 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
392392
return -ENOENT;
393393
}
394394

395+
#if defined(CONFIG_NF_CT_NETLINK) || \
396+
defined(CONFIG_NF_CT_NETLINK_MODULE)
397+
398+
#include <linux/netfilter/nfnetlink.h>
399+
#include <linux/netfilter/nfnetlink_conntrack.h>
400+
401+
static int ipv4_tuple_to_nfattr(struct sk_buff *skb,
402+
const struct nf_conntrack_tuple *tuple)
403+
{
404+
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t),
405+
&tuple->src.u3.ip);
406+
NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
407+
&tuple->dst.u3.ip);
408+
return 0;
409+
410+
nfattr_failure:
411+
return -1;
412+
}
413+
414+
static const size_t cta_min_ip[CTA_IP_MAX] = {
415+
[CTA_IP_V4_SRC-1] = sizeof(u_int32_t),
416+
[CTA_IP_V4_DST-1] = sizeof(u_int32_t),
417+
};
418+
419+
static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
420+
struct nf_conntrack_tuple *t)
421+
{
422+
if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
423+
return -EINVAL;
424+
425+
if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
426+
return -EINVAL;
427+
428+
t->src.u3.ip =
429+
*(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
430+
t->dst.u3.ip =
431+
*(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
432+
433+
return 0;
434+
}
435+
#endif
436+
395437
static struct nf_sockopt_ops so_getorigdst = {
396438
.pf = PF_INET,
397439
.get_optmin = SO_ORIGINAL_DST,
@@ -408,6 +450,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
408450
.print_conntrack = ipv4_print_conntrack,
409451
.prepare = ipv4_prepare,
410452
.get_features = ipv4_get_features,
453+
#if defined(CONFIG_NF_CT_NETLINK) || \
454+
defined(CONFIG_NF_CT_NETLINK_MODULE)
455+
.tuple_to_nfattr = ipv4_tuple_to_nfattr,
456+
.nfattr_to_tuple = ipv4_nfattr_to_tuple,
457+
#endif
411458
.me = THIS_MODULE,
412459
};
413460

net/ipv4/netfilter/nf_conntrack_proto_icmp.c

+79-18
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
5050
return 1;
5151
}
5252

53+
/* Add 1; spaces filled with 0. */
54+
static const u_int8_t invmap[] = {
55+
[ICMP_ECHO] = ICMP_ECHOREPLY + 1,
56+
[ICMP_ECHOREPLY] = ICMP_ECHO + 1,
57+
[ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
58+
[ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
59+
[ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
60+
[ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
61+
[ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
62+
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
63+
};
64+
5365
static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
5466
const struct nf_conntrack_tuple *orig)
5567
{
56-
/* Add 1; spaces filled with 0. */
57-
static u_int8_t invmap[]
58-
= { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
59-
[ICMP_ECHOREPLY] = ICMP_ECHO + 1,
60-
[ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
61-
[ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
62-
[ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
63-
[ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
64-
[ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
65-
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
66-
6768
if (orig->dst.u.icmp.type >= sizeof(invmap)
6869
|| !invmap[orig->dst.u.icmp.type])
6970
return 0;
@@ -120,11 +121,12 @@ static int icmp_packet(struct nf_conn *ct,
120121
static int icmp_new(struct nf_conn *conntrack,
121122
const struct sk_buff *skb, unsigned int dataoff)
122123
{
123-
static u_int8_t valid_new[]
124-
= { [ICMP_ECHO] = 1,
125-
[ICMP_TIMESTAMP] = 1,
126-
[ICMP_INFO_REQUEST] = 1,
127-
[ICMP_ADDRESS] = 1 };
124+
static const u_int8_t valid_new[] = {
125+
[ICMP_ECHO] = 1,
126+
[ICMP_TIMESTAMP] = 1,
127+
[ICMP_INFO_REQUEST] = 1,
128+
[ICMP_ADDRESS] = 1
129+
};
128130

129131
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
130132
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
@@ -168,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
168170
return -NF_ACCEPT;
169171
}
170172

171-
innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol);
173+
innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
172174
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
173175
/* Are they talking about one of our connections? */
174176
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -281,6 +283,60 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
281283
return icmp_error_message(skb, ctinfo, hooknum);
282284
}
283285

286+
#if defined(CONFIG_NF_CT_NETLINK) || \
287+
defined(CONFIG_NF_CT_NETLINK_MODULE)
288+
289+
#include <linux/netfilter/nfnetlink.h>
290+
#include <linux/netfilter/nfnetlink_conntrack.h>
291+
292+
static int icmp_tuple_to_nfattr(struct sk_buff *skb,
293+
const struct nf_conntrack_tuple *t)
294+
{
295+
NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
296+
&t->src.u.icmp.id);
297+
NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
298+
&t->dst.u.icmp.type);
299+
NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
300+
&t->dst.u.icmp.code);
301+
302+
return 0;
303+
304+
nfattr_failure:
305+
return -1;
306+
}
307+
308+
static const size_t cta_min_proto[CTA_PROTO_MAX] = {
309+
[CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t),
310+
[CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t),
311+
[CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t)
312+
};
313+
314+
static int icmp_nfattr_to_tuple(struct nfattr *tb[],
315+
struct nf_conntrack_tuple *tuple)
316+
{
317+
if (!tb[CTA_PROTO_ICMP_TYPE-1]
318+
|| !tb[CTA_PROTO_ICMP_CODE-1]
319+
|| !tb[CTA_PROTO_ICMP_ID-1])
320+
return -EINVAL;
321+
322+
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
323+
return -EINVAL;
324+
325+
tuple->dst.u.icmp.type =
326+
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
327+
tuple->dst.u.icmp.code =
328+
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
329+
tuple->src.u.icmp.id =
330+
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
331+
332+
if (tuple->dst.u.icmp.type >= sizeof(invmap)
333+
|| !invmap[tuple->dst.u.icmp.type])
334+
return -EINVAL;
335+
336+
return 0;
337+
}
338+
#endif
339+
284340
struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
285341
{
286342
.list = { NULL, NULL },
@@ -295,7 +351,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
295351
.new = icmp_new,
296352
.error = icmp_error,
297353
.destroy = NULL,
298-
.me = NULL
354+
.me = NULL,
355+
#if defined(CONFIG_NF_CT_NETLINK) || \
356+
defined(CONFIG_NF_CT_NETLINK_MODULE)
357+
.tuple_to_nfattr = icmp_tuple_to_nfattr,
358+
.nfattr_to_tuple = icmp_nfattr_to_tuple,
359+
#endif
299360
};
300361

301362
EXPORT_SYMBOL(nf_conntrack_protocol_icmp);

0 commit comments

Comments
 (0)