Skip to content

Commit

Permalink
[NETFILTER]: nfnetlink: convert to generic netlink attribute functions
Browse files Browse the repository at this point in the history
Get rid of the duplicated rtnetlink macros and use the generic netlink
attribute functions. The old duplicated stuff is moved to a new header
file that exists just for userspace.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Oct 10, 2007
1 parent 7c8d4cb commit df6fb86
Show file tree
Hide file tree
Showing 17 changed files with 527 additions and 532 deletions.
1 change: 1 addition & 0 deletions include/linux/netfilter/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ unifdef-y += nf_conntrack_common.h
unifdef-y += nf_conntrack_ftp.h
unifdef-y += nf_conntrack_tcp.h
unifdef-y += nfnetlink.h
unifdef-y += nfnetlink_compat.h
unifdef-y += x_tables.h
unifdef-y += xt_physdev.h
78 changes: 6 additions & 72 deletions include/linux/netfilter/nfnetlink.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
#ifndef _NFNETLINK_H
#define _NFNETLINK_H
#include <linux/types.h>

#ifndef __KERNEL__
/* nfnetlink groups: Up to 32 maximum - backwards compatibility for userspace */
#define NF_NETLINK_CONNTRACK_NEW 0x00000001
#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002
#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004
#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008
#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010
#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020
#endif
#include <linux/netfilter/nfnetlink_compat.h>

enum nfnetlink_groups {
NFNLGRP_NONE,
Expand All @@ -31,48 +22,6 @@ enum nfnetlink_groups {
};
#define NFNLGRP_MAX (__NFNLGRP_MAX - 1)

/* Generic structure for encapsulation optional netfilter information.
* It is reminiscent of sockaddr, but with sa_family replaced
* with attribute type.
* ! This should someday be put somewhere generic as now rtnetlink and
* ! nfnetlink use the same attributes methods. - J. Schulist.
*/

struct nfattr
{
u_int16_t nfa_len;
u_int16_t nfa_type; /* we use 15 bits for the type, and the highest
* bit to indicate whether the payload is nested */
};

/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
* rtnetlink.h, it's time to put this in a generic file */

#define NFNL_NFA_NEST 0x8000
#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff)

#define NFA_ALIGNTO 4
#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
&& (nfa)->nfa_len <= (len))
#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
(struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len))
#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
#define NFA_NEST(skb, type) \
({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \
NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \
__start; })
#define NFA_NEST_END(skb, start) \
({ (start)->nfa_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
(skb)->len; })
#define NFA_NEST_CANCEL(skb, start) \
({ if (start) \
skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
-1; })

/* General form of address family dependent message.
*/
struct nfgenmsg {
Expand All @@ -83,10 +32,6 @@ struct nfgenmsg {

#define NFNETLINK_V0 0

#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \
+ NLMSG_ALIGN(sizeof(struct nfgenmsg))))
#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))

/* netfilter netlink message types are split in two pieces:
* 8 bit subsystem, 8bit operation.
*/
Expand All @@ -107,12 +52,13 @@ struct nfgenmsg {

#include <linux/netlink.h>
#include <linux/capability.h>
#include <net/netlink.h>

struct nfnl_callback
{
int (*call)(struct sock *nl, struct sk_buff *skb,
struct nlmsghdr *nlh, struct nfattr *cda[]);
u_int16_t attr_count; /* number of nfattr's */
struct nlmsghdr *nlh, struct nlattr *cda[]);
u_int16_t attr_count; /* number of nlattr's */
};

struct nfnetlink_subsystem
Expand All @@ -123,27 +69,15 @@ struct nfnetlink_subsystem
const struct nfnl_callback *cb; /* callback for individual types */
};

extern void __nfa_fill(struct sk_buff *skb, int attrtype,
int attrlen, const void *data);
#define NFA_PUT(skb, attrtype, attrlen, data) \
({ if (skb_tailroom(skb) < (int)NFA_SPACE(attrlen)) goto nfattr_failure; \
__nfa_fill(skb, attrtype, attrlen, data); })

extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n);
extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n);

extern void nfattr_parse(struct nfattr *tb[], int maxattr,
struct nfattr *nfa, int len);

#define nfattr_parse_nested(tb, max, nfa) \
nfattr_parse((tb), (max), NFA_DATA((nfa)), NFA_PAYLOAD((nfa)))

#define nfattr_bad_size(tb, max, cta_min) \
({ int __i, __res = 0; \
for (__i=0; __i<max; __i++) { \
for (__i=1; __i <= max; __i++) { \
if (!cta_min[__i]) \
continue; \
if (tb[__i] && NFA_PAYLOAD(tb[__i]) < cta_min[__i]){ \
if (tb[__i] && nla_len(tb[__i]) < cta_min[__i]){ \
__res = 1; \
break; \
} \
Expand Down
61 changes: 61 additions & 0 deletions include/linux/netfilter/nfnetlink_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef _NFNETLINK_COMPAT_H
#define _NFNETLINK_COMPAT_H
#ifndef __KERNEL
/* Old nfnetlink macros for userspace */

/* nfnetlink groups: Up to 32 maximum */
#define NF_NETLINK_CONNTRACK_NEW 0x00000001
#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002
#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004
#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008
#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010
#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020

/* Generic structure for encapsulation optional netfilter information.
* It is reminiscent of sockaddr, but with sa_family replaced
* with attribute type.
* ! This should someday be put somewhere generic as now rtnetlink and
* ! nfnetlink use the same attributes methods. - J. Schulist.
*/

struct nfattr
{
u_int16_t nfa_len;
u_int16_t nfa_type; /* we use 15 bits for the type, and the highest
* bit to indicate whether the payload is nested */
};

/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
* rtnetlink.h, it's time to put this in a generic file */

#define NFNL_NFA_NEST 0x8000
#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff)

#define NFA_ALIGNTO 4
#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
&& (nfa)->nfa_len <= (len))
#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
(struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len))
#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
#define NFA_NEST(skb, type) \
({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \
NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \
__start; })
#define NFA_NEST_END(skb, start) \
({ (start)->nfa_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
(skb)->len; })
#define NFA_NEST_CANCEL(skb, start) \
({ if (start) \
skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
-1; })

#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \
+ NLMSG_ALIGN(sizeof(struct nfgenmsg))))
#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))

#endif /* ! __KERNEL__ */
#endif /* _NFNETLINK_COMPAT_H */
5 changes: 2 additions & 3 deletions include/net/netfilter/nf_conntrack_l3proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@

#ifndef _NF_CONNTRACK_L3PROTO_H
#define _NF_CONNTRACK_L3PROTO_H
#include <linux/netlink.h>
#include <linux/seq_file.h>
#include <net/netfilter/nf_conntrack.h>

struct nfattr;

struct nf_conntrack_l3proto
{
/* L3 Protocol Family number. ex) PF_INET */
Expand Down Expand Up @@ -67,7 +66,7 @@ struct nf_conntrack_l3proto
int (*tuple_to_nfattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);

int (*nfattr_to_tuple)(struct nfattr *tb[],
int (*nfattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t);

#ifdef CONFIG_SYSCTL
Expand Down
10 changes: 5 additions & 5 deletions include/net/netfilter/nf_conntrack_l4proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

#ifndef _NF_CONNTRACK_L4PROTO_H
#define _NF_CONNTRACK_L4PROTO_H
#include <linux/netlink.h>
#include <net/netfilter/nf_conntrack.h>

struct seq_file;
struct nfattr;

struct nf_conntrack_l4proto
{
Expand Down Expand Up @@ -65,15 +65,15 @@ struct nf_conntrack_l4proto
int pf, unsigned int hooknum);

/* convert protoinfo to nfnetink attributes */
int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
int (*to_nfattr)(struct sk_buff *skb, struct nlattr *nla,
const struct nf_conn *ct);

/* convert nfnetlink attributes to protoinfo */
int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
int (*from_nfattr)(struct nlattr *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[],
int (*nfattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t);

#ifdef CONFIG_SYSCTL
Expand Down Expand Up @@ -113,7 +113,7 @@ extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *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[],
extern int nf_ct_port_nfattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t);

/* Log invalid packets */
Expand Down
4 changes: 2 additions & 2 deletions include/net/netfilter/nf_nat_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct nf_nat_protocol
int (*range_to_nfattr)(struct sk_buff *skb,
const struct nf_nat_range *range);

int (*nfattr_to_range)(struct nfattr *tb[],
int (*nfattr_to_range)(struct nlattr *tb[],
struct nf_nat_range *range);
};

Expand All @@ -64,7 +64,7 @@ extern struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);

extern int nf_nat_port_range_to_nfattr(struct sk_buff *skb,
const struct nf_nat_range *range);
extern int nf_nat_port_nfattr_to_range(struct nfattr *tb[],
extern int nf_nat_port_nfattr_to_range(struct nlattr *tb[],
struct nf_nat_range *range);

#endif /*_NF_NAT_PROTO_H*/
20 changes: 10 additions & 10 deletions net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,32 +363,32 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
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),
NLA_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),
NLA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
&tuple->dst.u3.ip);
return 0;

nfattr_failure:
nla_put_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 const size_t cta_min_ip[CTA_IP_MAX+1] = {
[CTA_IP_V4_SRC] = sizeof(u_int32_t),
[CTA_IP_V4_DST] = sizeof(u_int32_t),
};

static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
static int ipv4_nfattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t)
{
if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
if (!tb[CTA_IP_V4_SRC] || !tb[CTA_IP_V4_DST])
return -EINVAL;

if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
return -EINVAL;

t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
t->src.u3.ip = *(__be32 *)nla_data(tb[CTA_IP_V4_SRC]);
t->dst.u3.ip = *(__be32 *)nla_data(tb[CTA_IP_V4_DST]);

return 0;
}
Expand Down
30 changes: 15 additions & 15 deletions net/ipv4/netfilter/nf_conntrack_proto_icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,42 +235,42 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
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),
NLA_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),
NLA_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),
NLA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
&t->dst.u.icmp.code);

return 0;

nfattr_failure:
nla_put_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 const size_t cta_min_proto[CTA_PROTO_MAX+1] = {
[CTA_PROTO_ICMP_TYPE] = sizeof(u_int8_t),
[CTA_PROTO_ICMP_CODE] = sizeof(u_int8_t),
[CTA_PROTO_ICMP_ID] = sizeof(u_int16_t)
};

static int icmp_nfattr_to_tuple(struct nfattr *tb[],
static int icmp_nfattr_to_tuple(struct nlattr *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])
if (!tb[CTA_PROTO_ICMP_TYPE]
|| !tb[CTA_PROTO_ICMP_CODE]
|| !tb[CTA_PROTO_ICMP_ID])
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]);
*(u_int8_t *)nla_data(tb[CTA_PROTO_ICMP_TYPE]);
tuple->dst.u.icmp.code =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
*(u_int8_t *)nla_data(tb[CTA_PROTO_ICMP_CODE]);
tuple->src.u.icmp.id =
*(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
*(__be16 *)nla_data(tb[CTA_PROTO_ICMP_ID]);

if (tuple->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[tuple->dst.u.icmp.type])
Expand Down
Loading

0 comments on commit df6fb86

Please sign in to comment.