Skip to content

Commit

Permalink
[NETFILTER]: Add ctnetlink port for nf_conntrack
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pablo Neira Ayuso authored and David S. Miller committed Jan 5, 2006
1 parent 205d67c commit c1d10ad
Show file tree
Hide file tree
Showing 16 changed files with 2,289 additions and 63 deletions.
3 changes: 3 additions & 0 deletions include/linux/netfilter/nfnetlink_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 31 additions & 0 deletions include/net/netfilter/nf_conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -140,6 +143,9 @@ struct nf_conntrack_expect
/* Usage count. */
atomic_t use;

/* Unique ID */
unsigned int id;

/* Flags */
unsigned int flags;

Expand Down Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions include/net/netfilter/nf_conntrack_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
15 changes: 14 additions & 1 deletion include/net/netfilter/nf_conntrack_l3proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <linux/seq_file.h>
#include <net/netfilter/nf_conntrack.h>

struct nfattr;

struct nf_conntrack_l3proto
{
/* Next pointer. */
Expand Down Expand Up @@ -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;
};
Expand All @@ -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;
Expand Down
26 changes: 25 additions & 1 deletion include/net/netfilter/nf_conntrack_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <net/netfilter/nf_conntrack.h>

struct seq_file;
struct nfattr;

struct nf_conntrack_protocol
{
Expand Down Expand Up @@ -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;
};
Expand All @@ -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;

Expand Down
47 changes: 47 additions & 0 deletions net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
};

Expand Down
97 changes: 79 additions & 18 deletions net/ipv4/netfilter/nf_conntrack_proto_icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
return 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
};

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,
[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};

if (orig->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[orig->dst.u.icmp.type])
return 0;
Expand Down Expand Up @@ -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,
[ICMP_TIMESTAMP] = 1,
[ICMP_INFO_REQUEST] = 1,
[ICMP_ADDRESS] = 1 };
static const u_int8_t valid_new[] = {
[ICMP_ECHO] = 1,
[ICMP_TIMESTAMP] = 1,
[ICMP_INFO_REQUEST] = 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]) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -281,6 +283,60 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
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 },
Expand All @@ -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);
Loading

0 comments on commit c1d10ad

Please sign in to comment.