mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-13 20:33:15 +00:00
[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>
This commit is contained in:
parent
205d67c7d9
commit
c1d10adb4a
@ -64,6 +64,9 @@ enum ctattr_l4proto {
|
||||
CTA_PROTO_ICMP_ID,
|
||||
CTA_PROTO_ICMP_TYPE,
|
||||
CTA_PROTO_ICMP_CODE,
|
||||
CTA_PROTO_ICMPV6_ID,
|
||||
CTA_PROTO_ICMPV6_TYPE,
|
||||
CTA_PROTO_ICMPV6_CODE,
|
||||
__CTA_PROTO_MAX
|
||||
};
|
||||
#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
|
||||
|
@ -94,6 +94,9 @@ struct nf_conn
|
||||
/* Current number of expected connections */
|
||||
unsigned int expecting;
|
||||
|
||||
/* Unique ID that identifies this conntrack*/
|
||||
unsigned int id;
|
||||
|
||||
/* Helper. if any */
|
||||
struct nf_conntrack_helper *helper;
|
||||
|
||||
@ -140,6 +143,9 @@ struct nf_conntrack_expect
|
||||
/* Usage count. */
|
||||
atomic_t use;
|
||||
|
||||
/* Unique ID */
|
||||
unsigned int id;
|
||||
|
||||
/* Flags */
|
||||
unsigned int flags;
|
||||
|
||||
@ -190,6 +196,31 @@ static inline void nf_ct_put(struct nf_conn *ct)
|
||||
nf_conntrack_put(&ct->ct_general);
|
||||
}
|
||||
|
||||
extern struct nf_conntrack_tuple_hash *
|
||||
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conn *ignored_conntrack);
|
||||
|
||||
extern void nf_conntrack_hash_insert(struct nf_conn *ct);
|
||||
|
||||
extern struct nf_conntrack_expect *
|
||||
__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
|
||||
|
||||
extern struct nf_conntrack_expect *
|
||||
nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
|
||||
|
||||
extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
|
||||
|
||||
extern void nf_ct_remove_expectations(struct nf_conn *ct);
|
||||
|
||||
extern void nf_conntrack_flush(void);
|
||||
|
||||
extern struct nf_conntrack_helper *
|
||||
nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
|
||||
extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
|
||||
|
||||
extern struct nf_conntrack_helper *
|
||||
__nf_conntrack_helper_find_byname(const char *name);
|
||||
|
||||
/* call to create an explicit dependency on nf_conntrack. */
|
||||
extern void need_nf_conntrack(void);
|
||||
|
||||
|
@ -33,6 +33,8 @@ struct nf_conntrack_helper
|
||||
unsigned int protoff,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info conntrackinfo);
|
||||
|
||||
int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
|
||||
};
|
||||
|
||||
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
|
||||
struct nfattr;
|
||||
|
||||
struct nf_conntrack_l3proto
|
||||
{
|
||||
/* Next pointer. */
|
||||
@ -70,6 +72,12 @@ struct nf_conntrack_l3proto
|
||||
|
||||
u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
|
||||
|
||||
int (*tuple_to_nfattr)(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *t);
|
||||
|
||||
int (*nfattr_to_tuple)(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t);
|
||||
|
||||
/* Module (if any) which this is connected to. */
|
||||
struct module *me;
|
||||
};
|
||||
@ -81,11 +89,16 @@ extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
|
||||
extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
|
||||
|
||||
static inline struct nf_conntrack_l3proto *
|
||||
nf_ct_find_l3proto(u_int16_t l3proto)
|
||||
__nf_ct_l3proto_find(u_int16_t l3proto)
|
||||
{
|
||||
return nf_ct_l3protos[l3proto];
|
||||
}
|
||||
|
||||
extern struct nf_conntrack_l3proto *
|
||||
nf_ct_l3proto_find_get(u_int16_t l3proto);
|
||||
|
||||
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
|
||||
|
||||
/* Existing built-in protocols */
|
||||
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
|
||||
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
|
||||
struct seq_file;
|
||||
struct nfattr;
|
||||
|
||||
struct nf_conntrack_protocol
|
||||
{
|
||||
@ -66,6 +67,18 @@ struct nf_conntrack_protocol
|
||||
enum ip_conntrack_info *ctinfo,
|
||||
int pf, unsigned int hooknum);
|
||||
|
||||
/* convert protoinfo to nfnetink attributes */
|
||||
int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
|
||||
const struct nf_conn *ct);
|
||||
|
||||
/* convert nfnetlink attributes to protoinfo */
|
||||
int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
|
||||
|
||||
int (*tuple_to_nfattr)(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *t);
|
||||
int (*nfattr_to_tuple)(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t);
|
||||
|
||||
/* Module (if any) which this is connected to. */
|
||||
struct module *me;
|
||||
};
|
||||
@ -80,12 +93,23 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
|
||||
extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
|
||||
|
||||
extern struct nf_conntrack_protocol *
|
||||
nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
|
||||
__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
|
||||
|
||||
extern struct nf_conntrack_protocol *
|
||||
nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
|
||||
|
||||
extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
|
||||
|
||||
/* Protocol registration. */
|
||||
extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
|
||||
extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
|
||||
|
||||
/* Generic netlink helpers */
|
||||
extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *tuple);
|
||||
extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t);
|
||||
|
||||
/* Log invalid packets */
|
||||
extern unsigned int nf_ct_log_invalid;
|
||||
|
||||
|
@ -392,6 +392,48 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
static int ipv4_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t),
|
||||
&tuple->src.u3.ip);
|
||||
NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
|
||||
&tuple->dst.u3.ip);
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_ip[CTA_IP_MAX] = {
|
||||
[CTA_IP_V4_SRC-1] = sizeof(u_int32_t),
|
||||
[CTA_IP_V4_DST-1] = sizeof(u_int32_t),
|
||||
};
|
||||
|
||||
static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t)
|
||||
{
|
||||
if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
|
||||
return -EINVAL;
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
|
||||
return -EINVAL;
|
||||
|
||||
t->src.u3.ip =
|
||||
*(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
|
||||
t->dst.u3.ip =
|
||||
*(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct nf_sockopt_ops so_getorigdst = {
|
||||
.pf = PF_INET,
|
||||
.get_optmin = SO_ORIGINAL_DST,
|
||||
@ -408,6 +450,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
|
||||
.print_conntrack = ipv4_print_conntrack,
|
||||
.prepare = ipv4_prepare,
|
||||
.get_features = ipv4_get_features,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = ipv4_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = ipv4_nfattr_to_tuple,
|
||||
#endif
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conntrack_tuple *orig)
|
||||
{
|
||||
/* Add 1; spaces filled with 0. */
|
||||
static u_int8_t invmap[]
|
||||
= { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
|
||||
/* Add 1; spaces filled with 0. */
|
||||
static const u_int8_t invmap[] = {
|
||||
[ICMP_ECHO] = ICMP_ECHOREPLY + 1,
|
||||
[ICMP_ECHOREPLY] = ICMP_ECHO + 1,
|
||||
[ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
|
||||
[ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
|
||||
[ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
|
||||
[ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
|
||||
[ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
|
||||
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
|
||||
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
|
||||
};
|
||||
|
||||
static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conntrack_tuple *orig)
|
||||
{
|
||||
if (orig->dst.u.icmp.type >= sizeof(invmap)
|
||||
|| !invmap[orig->dst.u.icmp.type])
|
||||
return 0;
|
||||
@ -120,11 +121,12 @@ static int icmp_packet(struct nf_conn *ct,
|
||||
static int icmp_new(struct nf_conn *conntrack,
|
||||
const struct sk_buff *skb, unsigned int dataoff)
|
||||
{
|
||||
static u_int8_t valid_new[]
|
||||
= { [ICMP_ECHO] = 1,
|
||||
static const u_int8_t valid_new[] = {
|
||||
[ICMP_ECHO] = 1,
|
||||
[ICMP_TIMESTAMP] = 1,
|
||||
[ICMP_INFO_REQUEST] = 1,
|
||||
[ICMP_ADDRESS] = 1 };
|
||||
[ICMP_ADDRESS] = 1
|
||||
};
|
||||
|
||||
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
|
||||
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
|
||||
@ -168,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
|
||||
innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol);
|
||||
innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
|
||||
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
|
||||
/* Are they talking about one of our connections? */
|
||||
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
|
||||
@ -281,6 +283,60 @@ checksum_skipped:
|
||||
return icmp_error_message(skb, ctinfo, hooknum);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
static int icmp_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *t)
|
||||
{
|
||||
NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
|
||||
&t->src.u.icmp.id);
|
||||
NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
|
||||
&t->dst.u.icmp.type);
|
||||
NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
|
||||
&t->dst.u.icmp.code);
|
||||
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_proto[CTA_PROTO_MAX] = {
|
||||
[CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t),
|
||||
[CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t),
|
||||
[CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t)
|
||||
};
|
||||
|
||||
static int icmp_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
if (!tb[CTA_PROTO_ICMP_TYPE-1]
|
||||
|| !tb[CTA_PROTO_ICMP_CODE-1]
|
||||
|| !tb[CTA_PROTO_ICMP_ID-1])
|
||||
return -EINVAL;
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
|
||||
return -EINVAL;
|
||||
|
||||
tuple->dst.u.icmp.type =
|
||||
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
|
||||
tuple->dst.u.icmp.code =
|
||||
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
|
||||
tuple->src.u.icmp.id =
|
||||
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
|
||||
|
||||
if (tuple->dst.u.icmp.type >= sizeof(invmap)
|
||||
|| !invmap[tuple->dst.u.icmp.type])
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
|
||||
{
|
||||
.list = { NULL, NULL },
|
||||
@ -295,7 +351,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
|
||||
.new = icmp_new,
|
||||
.error = icmp_error,
|
||||
.destroy = NULL,
|
||||
.me = NULL
|
||||
.me = NULL,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = icmp_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = icmp_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
|
||||
|
@ -401,6 +401,48 @@ static ctl_table nf_ct_net_table[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
static int ipv6_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
NFA_PUT(skb, CTA_IP_V6_SRC, sizeof(u_int32_t) * 4,
|
||||
&tuple->src.u3.ip6);
|
||||
NFA_PUT(skb, CTA_IP_V6_DST, sizeof(u_int32_t) * 4,
|
||||
&tuple->dst.u3.ip6);
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_ip[CTA_IP_MAX] = {
|
||||
[CTA_IP_V6_SRC-1] = sizeof(u_int32_t)*4,
|
||||
[CTA_IP_V6_DST-1] = sizeof(u_int32_t)*4,
|
||||
};
|
||||
|
||||
static int ipv6_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t)
|
||||
{
|
||||
if (!tb[CTA_IP_V6_SRC-1] || !tb[CTA_IP_V6_DST-1])
|
||||
return -EINVAL;
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&t->src.u3.ip6, NFA_DATA(tb[CTA_IP_V6_SRC-1]),
|
||||
sizeof(u_int32_t) * 4);
|
||||
memcpy(&t->dst.u3.ip6, NFA_DATA(tb[CTA_IP_V6_DST-1]),
|
||||
sizeof(u_int32_t) * 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
|
||||
.l3proto = PF_INET6,
|
||||
.name = "ipv6",
|
||||
@ -409,6 +451,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
|
||||
.print_tuple = ipv6_print_tuple,
|
||||
.print_conntrack = ipv6_print_conntrack,
|
||||
.prepare = ipv6_prepare,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = ipv6_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = ipv6_nfattr_to_tuple,
|
||||
#endif
|
||||
.get_features = ipv6_get_features,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
@ -57,17 +57,17 @@ static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conntrack_tuple *orig)
|
||||
{
|
||||
/* Add 1; spaces filled with 0. */
|
||||
static u_int8_t invmap[] = {
|
||||
/* Add 1; spaces filled with 0. */
|
||||
static u_int8_t invmap[] = {
|
||||
[ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
|
||||
[ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
|
||||
[ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
|
||||
[ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1
|
||||
};
|
||||
};
|
||||
|
||||
static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conntrack_tuple *orig)
|
||||
{
|
||||
int type = orig->dst.u.icmp.type - 128;
|
||||
if (type < 0 || type >= sizeof(invmap) || !invmap[type])
|
||||
return 0;
|
||||
@ -185,7 +185,7 @@ icmpv6_error_message(struct sk_buff *skb,
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
|
||||
inproto = nf_ct_find_proto(PF_INET6, inprotonum);
|
||||
inproto = __nf_ct_proto_find(PF_INET6, inprotonum);
|
||||
|
||||
/* Are they talking about one of our connections? */
|
||||
if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
|
||||
@ -255,6 +255,60 @@ skipped:
|
||||
return icmpv6_error_message(skb, dataoff, ctinfo, hooknum);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
static int icmpv6_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *t)
|
||||
{
|
||||
NFA_PUT(skb, CTA_PROTO_ICMPV6_ID, sizeof(u_int16_t),
|
||||
&t->src.u.icmp.id);
|
||||
NFA_PUT(skb, CTA_PROTO_ICMPV6_TYPE, sizeof(u_int8_t),
|
||||
&t->dst.u.icmp.type);
|
||||
NFA_PUT(skb, CTA_PROTO_ICMPV6_CODE, sizeof(u_int8_t),
|
||||
&t->dst.u.icmp.code);
|
||||
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_proto[CTA_PROTO_MAX] = {
|
||||
[CTA_PROTO_ICMPV6_TYPE-1] = sizeof(u_int8_t),
|
||||
[CTA_PROTO_ICMPV6_CODE-1] = sizeof(u_int8_t),
|
||||
[CTA_PROTO_ICMPV6_ID-1] = sizeof(u_int16_t)
|
||||
};
|
||||
|
||||
static int icmpv6_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
if (!tb[CTA_PROTO_ICMPV6_TYPE-1]
|
||||
|| !tb[CTA_PROTO_ICMPV6_CODE-1]
|
||||
|| !tb[CTA_PROTO_ICMPV6_ID-1])
|
||||
return -EINVAL;
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
|
||||
return -EINVAL;
|
||||
|
||||
tuple->dst.u.icmp.type =
|
||||
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_TYPE-1]);
|
||||
tuple->dst.u.icmp.code =
|
||||
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]);
|
||||
tuple->src.u.icmp.id =
|
||||
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]);
|
||||
|
||||
if (tuple->dst.u.icmp.type < 128
|
||||
|| tuple->dst.u.icmp.type - 128 >= sizeof(invmap)
|
||||
|| !invmap[tuple->dst.u.icmp.type - 128])
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
|
||||
{
|
||||
.l3proto = PF_INET6,
|
||||
@ -267,6 +321,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
|
||||
.packet = icmpv6_packet,
|
||||
.new = icmpv6_new,
|
||||
.error = icmpv6_error,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = icmpv6_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = icmpv6_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6);
|
||||
|
@ -95,4 +95,11 @@ config NF_CONNTRACK_FTP
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NF_CT_NETLINK
|
||||
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
|
||||
depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
|
||||
depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
|
||||
help
|
||||
This option enables support for a netlink-based userspace interface
|
||||
|
||||
endmenu
|
||||
|
@ -13,3 +13,6 @@ obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
|
||||
|
||||
# SCTP protocol connection tracking
|
||||
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
|
||||
|
||||
# netlink interface for nf_conntrack
|
||||
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
|
||||
|
@ -82,6 +82,8 @@ unsigned int nf_ct_log_invalid;
|
||||
static LIST_HEAD(unconfirmed);
|
||||
static int nf_conntrack_vmalloc;
|
||||
|
||||
static unsigned int nf_conntrack_next_id = 1;
|
||||
static unsigned int nf_conntrack_expect_next_id = 1;
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
struct notifier_block *nf_conntrack_chain;
|
||||
struct notifier_block *nf_conntrack_expect_chain;
|
||||
@ -184,7 +186,7 @@ DECLARE_MUTEX(nf_ct_cache_mutex);
|
||||
|
||||
extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
|
||||
struct nf_conntrack_protocol *
|
||||
nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol)
|
||||
__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
|
||||
{
|
||||
if (unlikely(nf_ct_protos[l3proto] == NULL))
|
||||
return &nf_conntrack_generic_protocol;
|
||||
@ -192,6 +194,50 @@ nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol)
|
||||
return nf_ct_protos[l3proto][protocol];
|
||||
}
|
||||
|
||||
/* this is guaranteed to always return a valid protocol helper, since
|
||||
* it falls back to generic_protocol */
|
||||
struct nf_conntrack_protocol *
|
||||
nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
|
||||
{
|
||||
struct nf_conntrack_protocol *p;
|
||||
|
||||
preempt_disable();
|
||||
p = __nf_ct_proto_find(l3proto, protocol);
|
||||
if (p) {
|
||||
if (!try_module_get(p->me))
|
||||
p = &nf_conntrack_generic_protocol;
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void nf_ct_proto_put(struct nf_conntrack_protocol *p)
|
||||
{
|
||||
module_put(p->me);
|
||||
}
|
||||
|
||||
struct nf_conntrack_l3proto *
|
||||
nf_ct_l3proto_find_get(u_int16_t l3proto)
|
||||
{
|
||||
struct nf_conntrack_l3proto *p;
|
||||
|
||||
preempt_disable();
|
||||
p = __nf_ct_l3proto_find(l3proto);
|
||||
if (p) {
|
||||
if (!try_module_get(p->me))
|
||||
p = &nf_conntrack_generic_l3proto;
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
|
||||
{
|
||||
module_put(p->me);
|
||||
}
|
||||
|
||||
static int nf_conntrack_hash_rnd_initted;
|
||||
static unsigned int nf_conntrack_hash_rnd;
|
||||
|
||||
@ -384,7 +430,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
|
||||
}
|
||||
|
||||
/* nf_conntrack_expect helper functions */
|
||||
static void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
|
||||
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
|
||||
{
|
||||
ASSERT_WRITE_LOCK(&nf_conntrack_lock);
|
||||
NF_CT_ASSERT(!timer_pending(&exp->timeout));
|
||||
@ -404,6 +450,33 @@ static void expectation_timed_out(unsigned long ul_expect)
|
||||
nf_conntrack_expect_put(exp);
|
||||
}
|
||||
|
||||
struct nf_conntrack_expect *
|
||||
__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
struct nf_conntrack_expect *i;
|
||||
|
||||
list_for_each_entry(i, &nf_conntrack_expect_list, list) {
|
||||
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
|
||||
atomic_inc(&i->use);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Just find a expectation corresponding to a tuple. */
|
||||
struct nf_conntrack_expect *
|
||||
nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
struct nf_conntrack_expect *i;
|
||||
|
||||
read_lock_bh(&nf_conntrack_lock);
|
||||
i = __nf_conntrack_expect_find(tuple);
|
||||
read_unlock_bh(&nf_conntrack_lock);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* If an expectation for this connection is found, it gets delete from
|
||||
* global list then returned. */
|
||||
static struct nf_conntrack_expect *
|
||||
@ -432,7 +505,7 @@ find_expectation(const struct nf_conntrack_tuple *tuple)
|
||||
}
|
||||
|
||||
/* delete all expectations for this conntrack */
|
||||
static void remove_expectations(struct nf_conn *ct)
|
||||
void nf_ct_remove_expectations(struct nf_conn *ct)
|
||||
{
|
||||
struct nf_conntrack_expect *i, *tmp;
|
||||
|
||||
@ -462,7 +535,7 @@ clean_from_lists(struct nf_conn *ct)
|
||||
LIST_DELETE(&nf_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
|
||||
|
||||
/* Destroy all pending expectations */
|
||||
remove_expectations(ct);
|
||||
nf_ct_remove_expectations(ct);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -482,12 +555,11 @@ destroy_conntrack(struct nf_conntrack *nfct)
|
||||
/* To make sure we don't get any weird locking issues here:
|
||||
* destroy_conntrack() MUST NOT be called with a write lock
|
||||
* to nf_conntrack_lock!!! -HW */
|
||||
l3proto = nf_ct_find_l3proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
|
||||
l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
|
||||
if (l3proto && l3proto->destroy)
|
||||
l3proto->destroy(ct);
|
||||
|
||||
proto = nf_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
|
||||
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
|
||||
proto = __nf_ct_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
|
||||
if (proto && proto->destroy)
|
||||
proto->destroy(ct);
|
||||
|
||||
@ -499,7 +571,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
|
||||
* except TFTP can create an expectation on the first packet,
|
||||
* before connection is in the list, so we need to clean here,
|
||||
* too. */
|
||||
remove_expectations(ct);
|
||||
nf_ct_remove_expectations(ct);
|
||||
|
||||
/* We overload first tuple to link into unconfirmed list. */
|
||||
if (!nf_ct_is_confirmed(ct)) {
|
||||
@ -540,7 +612,7 @@ conntrack_tuple_cmp(const struct nf_conntrack_tuple_hash *i,
|
||||
&& nf_ct_tuple_equal(tuple, &i->tuple);
|
||||
}
|
||||
|
||||
static struct nf_conntrack_tuple_hash *
|
||||
struct nf_conntrack_tuple_hash *
|
||||
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_conn *ignored_conntrack)
|
||||
{
|
||||
@ -575,6 +647,29 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
|
||||
return h;
|
||||
}
|
||||
|
||||
static void __nf_conntrack_hash_insert(struct nf_conn *ct,
|
||||
unsigned int hash,
|
||||
unsigned int repl_hash)
|
||||
{
|
||||
ct->id = ++nf_conntrack_next_id;
|
||||
list_prepend(&nf_conntrack_hash[hash],
|
||||
&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
|
||||
list_prepend(&nf_conntrack_hash[repl_hash],
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].list);
|
||||
}
|
||||
|
||||
void nf_conntrack_hash_insert(struct nf_conn *ct)
|
||||
{
|
||||
unsigned int hash, repl_hash;
|
||||
|
||||
hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
|
||||
repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
|
||||
|
||||
write_lock_bh(&nf_conntrack_lock);
|
||||
__nf_conntrack_hash_insert(ct, hash, repl_hash);
|
||||
write_unlock_bh(&nf_conntrack_lock);
|
||||
}
|
||||
|
||||
/* Confirm a connection given skb; places it in hash table */
|
||||
int
|
||||
__nf_conntrack_confirm(struct sk_buff **pskb)
|
||||
@ -621,10 +716,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
|
||||
/* Remove from unconfirmed list */
|
||||
list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
|
||||
|
||||
list_prepend(&nf_conntrack_hash[hash],
|
||||
&ct->tuplehash[IP_CT_DIR_ORIGINAL]);
|
||||
list_prepend(&nf_conntrack_hash[repl_hash],
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY]);
|
||||
__nf_conntrack_hash_insert(ct, hash, repl_hash);
|
||||
/* Timer relative to confirmation time, not original
|
||||
setting time, otherwise we'd get timer wrap in
|
||||
weird delay cases. */
|
||||
@ -708,13 +800,41 @@ static inline int helper_cmp(const struct nf_conntrack_helper *i,
|
||||
}
|
||||
|
||||
static struct nf_conntrack_helper *
|
||||
nf_ct_find_helper(const struct nf_conntrack_tuple *tuple)
|
||||
__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
return LIST_FIND(&helpers, helper_cmp,
|
||||
struct nf_conntrack_helper *,
|
||||
tuple);
|
||||
}
|
||||
|
||||
struct nf_conntrack_helper *
|
||||
nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
struct nf_conntrack_helper *helper;
|
||||
|
||||
/* need nf_conntrack_lock to assure that helper exists until
|
||||
* try_module_get() is called */
|
||||
read_lock_bh(&nf_conntrack_lock);
|
||||
|
||||
helper = __nf_ct_helper_find(tuple);
|
||||
if (helper) {
|
||||
/* need to increase module usage count to assure helper will
|
||||
* not go away while the caller is e.g. busy putting a
|
||||
* conntrack in the hash that uses the helper */
|
||||
if (!try_module_get(helper->me))
|
||||
helper = NULL;
|
||||
}
|
||||
|
||||
read_unlock_bh(&nf_conntrack_lock);
|
||||
|
||||
return helper;
|
||||
}
|
||||
|
||||
void nf_ct_helper_put(struct nf_conntrack_helper *helper)
|
||||
{
|
||||
module_put(helper->me);
|
||||
}
|
||||
|
||||
static struct nf_conn *
|
||||
__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||
const struct nf_conntrack_tuple *repl,
|
||||
@ -744,7 +864,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||
/* find features needed by this conntrack. */
|
||||
features = l3proto->get_features(orig);
|
||||
read_lock_bh(&nf_conntrack_lock);
|
||||
if (nf_ct_find_helper(repl) != NULL)
|
||||
if (__nf_ct_helper_find(repl) != NULL)
|
||||
features |= NF_CT_F_HELP;
|
||||
read_unlock_bh(&nf_conntrack_lock);
|
||||
|
||||
@ -794,7 +914,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||
{
|
||||
struct nf_conntrack_l3proto *l3proto;
|
||||
|
||||
l3proto = nf_ct_find_l3proto(orig->src.l3num);
|
||||
l3proto = __nf_ct_l3proto_find(orig->src.l3num);
|
||||
return __nf_conntrack_alloc(orig, repl, l3proto);
|
||||
}
|
||||
|
||||
@ -853,7 +973,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
|
||||
nf_conntrack_get(&conntrack->master->ct_general);
|
||||
NF_CT_STAT_INC(expect_new);
|
||||
} else {
|
||||
conntrack->helper = nf_ct_find_helper(&repl_tuple);
|
||||
conntrack->helper = __nf_ct_helper_find(&repl_tuple);
|
||||
|
||||
NF_CT_STAT_INC(new);
|
||||
}
|
||||
@ -947,13 +1067,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
l3proto = nf_ct_find_l3proto((u_int16_t)pf);
|
||||
l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
|
||||
if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
|
||||
DEBUGP("not prepared to track yet or error occured\n");
|
||||
return -ret;
|
||||
}
|
||||
|
||||
proto = nf_ct_find_proto((u_int16_t)pf, protonum);
|
||||
proto = __nf_ct_proto_find((u_int16_t)pf, protonum);
|
||||
|
||||
/* It may be an special packet, error, unclean...
|
||||
* inverse of the return code tells to the netfilter
|
||||
@ -1002,8 +1122,8 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
|
||||
const struct nf_conntrack_tuple *orig)
|
||||
{
|
||||
return nf_ct_invert_tuple(inverse, orig,
|
||||
nf_ct_find_l3proto(orig->src.l3num),
|
||||
nf_ct_find_proto(orig->src.l3num,
|
||||
__nf_ct_l3proto_find(orig->src.l3num),
|
||||
__nf_ct_proto_find(orig->src.l3num,
|
||||
orig->dst.protonum));
|
||||
}
|
||||
|
||||
@ -1096,6 +1216,7 @@ static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
|
||||
exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
|
||||
add_timer(&exp->timeout);
|
||||
|
||||
exp->id = ++nf_conntrack_expect_next_id;
|
||||
atomic_inc(&exp->use);
|
||||
NF_CT_STAT_INC(expect_create);
|
||||
}
|
||||
@ -1176,7 +1297,7 @@ void nf_conntrack_alter_reply(struct nf_conn *conntrack,
|
||||
|
||||
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
|
||||
if (!conntrack->master && conntrack->expecting == 0)
|
||||
conntrack->helper = nf_ct_find_helper(newreply);
|
||||
conntrack->helper = __nf_ct_helper_find(newreply);
|
||||
write_unlock_bh(&nf_conntrack_lock);
|
||||
}
|
||||
|
||||
@ -1201,6 +1322,19 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nf_conntrack_helper *
|
||||
__nf_conntrack_helper_find_byname(const char *name)
|
||||
{
|
||||
struct nf_conntrack_helper *h;
|
||||
|
||||
list_for_each_entry(h, &helpers, list) {
|
||||
if (!strcmp(h->name, name))
|
||||
return h;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int unhelp(struct nf_conntrack_tuple_hash *i,
|
||||
const struct nf_conntrack_helper *me)
|
||||
{
|
||||
@ -1284,6 +1418,51 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
|
||||
nf_conntrack_event_cache(event, skb);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
|
||||
* in ip_conntrack_core, since we don't want the protocols to autoload
|
||||
* or depend on ctnetlink */
|
||||
int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
|
||||
&tuple->src.u.tcp.port);
|
||||
NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
|
||||
&tuple->dst.u.tcp.port);
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_proto[CTA_PROTO_MAX] = {
|
||||
[CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
|
||||
[CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t)
|
||||
};
|
||||
|
||||
int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
|
||||
struct nf_conntrack_tuple *t)
|
||||
{
|
||||
if (!tb[CTA_PROTO_SRC_PORT-1] || !tb[CTA_PROTO_DST_PORT-1])
|
||||
return -EINVAL;
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
|
||||
return -EINVAL;
|
||||
|
||||
t->src.u.tcp.port =
|
||||
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
|
||||
t->dst.u.tcp.port =
|
||||
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Used by ipt_REJECT and ip6t_REJECT. */
|
||||
void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
|
||||
{
|
||||
@ -1366,6 +1545,11 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
|
||||
get_order(sizeof(struct list_head) * size));
|
||||
}
|
||||
|
||||
void nf_conntrack_flush()
|
||||
{
|
||||
nf_ct_iterate_cleanup(kill_all, NULL);
|
||||
}
|
||||
|
||||
/* Mishearing the voices in his head, our hero wonders how he's
|
||||
supposed to kill the mall. */
|
||||
void nf_conntrack_cleanup(void)
|
||||
@ -1379,7 +1563,7 @@ void nf_conntrack_cleanup(void)
|
||||
|
||||
nf_ct_event_cache_flush();
|
||||
i_see_dead_people:
|
||||
nf_ct_iterate_cleanup(kill_all, NULL);
|
||||
nf_conntrack_flush();
|
||||
if (atomic_read(&nf_conntrack_count) != 0) {
|
||||
schedule();
|
||||
goto i_see_dead_people;
|
||||
|
1642
net/netfilter/nf_conntrack_netlink.c
Normal file
1642
net/netfilter/nf_conntrack_netlink.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1148,6 +1148,63 @@ static int tcp_new(struct nf_conn *conntrack,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
|
||||
const struct nf_conn *ct)
|
||||
{
|
||||
struct nfattr *nest_parms;
|
||||
|
||||
read_lock_bh(&tcp_lock);
|
||||
nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
|
||||
NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
|
||||
&ct->proto.tcp.state);
|
||||
read_unlock_bh(&tcp_lock);
|
||||
|
||||
NFA_NEST_END(skb, nest_parms);
|
||||
|
||||
return 0;
|
||||
|
||||
nfattr_failure:
|
||||
read_unlock_bh(&tcp_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
|
||||
[CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
|
||||
};
|
||||
|
||||
static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
|
||||
{
|
||||
struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
|
||||
struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
|
||||
|
||||
/* updates could not contain anything about the private
|
||||
* protocol info, in that case skip the parsing */
|
||||
if (!attr)
|
||||
return 0;
|
||||
|
||||
nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
|
||||
|
||||
if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
|
||||
return -EINVAL;
|
||||
|
||||
if (!tb[CTA_PROTOINFO_TCP_STATE-1])
|
||||
return -EINVAL;
|
||||
|
||||
write_lock_bh(&tcp_lock);
|
||||
ct->proto.tcp.state =
|
||||
*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
|
||||
write_unlock_bh(&tcp_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
|
||||
{
|
||||
.l3proto = PF_INET,
|
||||
@ -1160,6 +1217,13 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
|
||||
.packet = tcp_packet,
|
||||
.new = tcp_new,
|
||||
.error = tcp_error4,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.to_nfattr = tcp_to_nfattr,
|
||||
.from_nfattr = nfattr_to_tcp,
|
||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
|
||||
@ -1174,6 +1238,13 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
|
||||
.packet = tcp_packet,
|
||||
.new = tcp_new,
|
||||
.error = tcp_error6,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.to_nfattr = tcp_to_nfattr,
|
||||
.from_nfattr = nfattr_to_tcp,
|
||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(nf_conntrack_protocol_tcp4);
|
||||
|
@ -196,6 +196,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
|
||||
.packet = udp_packet,
|
||||
.new = udp_new,
|
||||
.error = udp_error4,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
|
||||
@ -210,6 +215,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
|
||||
.packet = udp_packet,
|
||||
.new = udp_new,
|
||||
.error = udp_error6,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
|
||||
.nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
|
||||
#endif
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
|
||||
|
@ -161,11 +161,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
|
||||
if (NF_CT_DIRECTION(hash))
|
||||
return 0;
|
||||
|
||||
l3proto = nf_ct_find_l3proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
|
||||
l3proto = __nf_ct_l3proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
|
||||
.tuple.src.l3num);
|
||||
|
||||
NF_CT_ASSERT(l3proto);
|
||||
proto = nf_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
|
||||
proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
|
||||
.tuple.src.l3num,
|
||||
conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
|
||||
.tuple.dst.protonum);
|
||||
@ -307,8 +307,8 @@ static int exp_seq_show(struct seq_file *s, void *v)
|
||||
expect->tuple.src.l3num,
|
||||
expect->tuple.dst.protonum);
|
||||
print_tuple(s, &expect->tuple,
|
||||
nf_ct_find_l3proto(expect->tuple.src.l3num),
|
||||
nf_ct_find_proto(expect->tuple.src.l3num,
|
||||
__nf_ct_l3proto_find(expect->tuple.src.l3num),
|
||||
__nf_ct_proto_find(expect->tuple.src.l3num,
|
||||
expect->tuple.dst.protonum));
|
||||
return seq_putc(s, '\n');
|
||||
}
|
||||
@ -847,7 +847,11 @@ EXPORT_SYMBOL(nf_conntrack_helper_unregister);
|
||||
EXPORT_SYMBOL(nf_ct_iterate_cleanup);
|
||||
EXPORT_SYMBOL(__nf_ct_refresh_acct);
|
||||
EXPORT_SYMBOL(nf_ct_protos);
|
||||
EXPORT_SYMBOL(nf_ct_find_proto);
|
||||
EXPORT_SYMBOL(__nf_ct_proto_find);
|
||||
EXPORT_SYMBOL(nf_ct_proto_find_get);
|
||||
EXPORT_SYMBOL(nf_ct_proto_put);
|
||||
EXPORT_SYMBOL(nf_ct_l3proto_find_get);
|
||||
EXPORT_SYMBOL(nf_ct_l3proto_put);
|
||||
EXPORT_SYMBOL(nf_ct_l3protos);
|
||||
EXPORT_SYMBOL(nf_conntrack_expect_alloc);
|
||||
EXPORT_SYMBOL(nf_conntrack_expect_put);
|
||||
@ -867,3 +871,21 @@ EXPORT_SYMBOL(nf_ct_get_tuple);
|
||||
EXPORT_SYMBOL(nf_ct_invert_tuple);
|
||||
EXPORT_SYMBOL(nf_conntrack_in);
|
||||
EXPORT_SYMBOL(__nf_conntrack_attach);
|
||||
EXPORT_SYMBOL(nf_conntrack_alloc);
|
||||
EXPORT_SYMBOL(nf_conntrack_free);
|
||||
EXPORT_SYMBOL(nf_conntrack_flush);
|
||||
EXPORT_SYMBOL(nf_ct_remove_expectations);
|
||||
EXPORT_SYMBOL(nf_ct_helper_find_get);
|
||||
EXPORT_SYMBOL(nf_ct_helper_put);
|
||||
EXPORT_SYMBOL(__nf_conntrack_helper_find_byname);
|
||||
EXPORT_SYMBOL(__nf_conntrack_find);
|
||||
EXPORT_SYMBOL(nf_ct_unlink_expect);
|
||||
EXPORT_SYMBOL(nf_conntrack_hash_insert);
|
||||
EXPORT_SYMBOL(__nf_conntrack_expect_find);
|
||||
EXPORT_SYMBOL(nf_conntrack_expect_find);
|
||||
EXPORT_SYMBOL(nf_conntrack_expect_list);
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || \
|
||||
defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr);
|
||||
EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user