e1701c68c1
Based upon a patch from Patrick McHardy. The fib_rules netlink attribute policy introduced in 2.6.19 broke userspace compatibilty. When specifying a rule with "from all" or "to all", iproute adds a zero byte long netlink attribute, but the policy requires all addresses to have a size equal to sizeof(struct in_addr)/sizeof(struct in6_addr), resulting in a validation error. Check attribute length of FRA_SRC/FRA_DST in the generic framework by letting the family specific rules implementation provide the length of an address. Report an error if address length is non zero but no address attribute is provided. Fix actual bug by checking address length for non-zero instead of relying on availability of attribute. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
109 lines
2.5 KiB
C
109 lines
2.5 KiB
C
#ifndef __NET_FIB_RULES_H
|
|
#define __NET_FIB_RULES_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/fib_rules.h>
|
|
#include <net/flow.h>
|
|
#include <net/netlink.h>
|
|
|
|
struct fib_rule
|
|
{
|
|
struct list_head list;
|
|
atomic_t refcnt;
|
|
int ifindex;
|
|
char ifname[IFNAMSIZ];
|
|
u32 mark;
|
|
u32 mark_mask;
|
|
u32 pref;
|
|
u32 flags;
|
|
u32 table;
|
|
u8 action;
|
|
struct rcu_head rcu;
|
|
};
|
|
|
|
struct fib_lookup_arg
|
|
{
|
|
void *lookup_ptr;
|
|
void *result;
|
|
struct fib_rule *rule;
|
|
};
|
|
|
|
struct fib_rules_ops
|
|
{
|
|
int family;
|
|
struct list_head list;
|
|
int rule_size;
|
|
int addr_size;
|
|
|
|
int (*action)(struct fib_rule *,
|
|
struct flowi *, int,
|
|
struct fib_lookup_arg *);
|
|
int (*match)(struct fib_rule *,
|
|
struct flowi *, int);
|
|
int (*configure)(struct fib_rule *,
|
|
struct sk_buff *,
|
|
struct nlmsghdr *,
|
|
struct fib_rule_hdr *,
|
|
struct nlattr **);
|
|
int (*compare)(struct fib_rule *,
|
|
struct fib_rule_hdr *,
|
|
struct nlattr **);
|
|
int (*fill)(struct fib_rule *, struct sk_buff *,
|
|
struct nlmsghdr *,
|
|
struct fib_rule_hdr *);
|
|
u32 (*default_pref)(void);
|
|
size_t (*nlmsg_payload)(struct fib_rule *);
|
|
|
|
int nlgroup;
|
|
struct nla_policy *policy;
|
|
struct list_head *rules_list;
|
|
struct module *owner;
|
|
};
|
|
|
|
#define FRA_GENERIC_POLICY \
|
|
[FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
|
|
[FRA_PRIORITY] = { .type = NLA_U32 }, \
|
|
[FRA_FWMARK] = { .type = NLA_U32 }, \
|
|
[FRA_FWMASK] = { .type = NLA_U32 }, \
|
|
[FRA_TABLE] = { .type = NLA_U32 }
|
|
|
|
static inline void fib_rule_get(struct fib_rule *rule)
|
|
{
|
|
atomic_inc(&rule->refcnt);
|
|
}
|
|
|
|
static inline void fib_rule_put_rcu(struct rcu_head *head)
|
|
{
|
|
struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
|
|
kfree(rule);
|
|
}
|
|
|
|
static inline void fib_rule_put(struct fib_rule *rule)
|
|
{
|
|
if (atomic_dec_and_test(&rule->refcnt))
|
|
call_rcu(&rule->rcu, fib_rule_put_rcu);
|
|
}
|
|
|
|
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
|
|
{
|
|
if (nla[FRA_TABLE])
|
|
return nla_get_u32(nla[FRA_TABLE]);
|
|
return frh->table;
|
|
}
|
|
|
|
extern int fib_rules_register(struct fib_rules_ops *);
|
|
extern int fib_rules_unregister(struct fib_rules_ops *);
|
|
|
|
extern int fib_rules_lookup(struct fib_rules_ops *,
|
|
struct flowi *, int flags,
|
|
struct fib_lookup_arg *);
|
|
|
|
extern int fib_nl_newrule(struct sk_buff *,
|
|
struct nlmsghdr *, void *);
|
|
extern int fib_nl_delrule(struct sk_buff *,
|
|
struct nlmsghdr *, void *);
|
|
extern int fib_rules_dump(struct sk_buff *,
|
|
struct netlink_callback *, int);
|
|
#endif
|