Commit bb611874 authored by David S. Miller's avatar David S. Miller
parents d328bc83 cb6a4e46
...@@ -15,14 +15,6 @@ ...@@ -15,14 +15,6 @@
/* try to find source address in routing lookups */ /* try to find source address in routing lookups */
#define FIB_RULE_FIND_SADDR 0x00010000 #define FIB_RULE_FIND_SADDR 0x00010000
/* fib_rules families. values up to 127 are reserved for real address
* families, values above 128 may be used arbitrarily.
*/
#define FIB_RULES_IPV4 AF_INET
#define FIB_RULES_IPV6 AF_INET6
#define FIB_RULES_DECNET AF_DECnet
#define FIB_RULES_IPMR 128
struct fib_rule_hdr { struct fib_rule_hdr {
__u8 family; __u8 family;
__u8 dst_len; __u8 dst_len;
......
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
#include <linux/if_addr.h> #include <linux/if_addr.h>
#include <linux/neighbour.h> #include <linux/neighbour.h>
/* rtnetlink families. Values up to 127 are reserved for real address
* families, values above 128 may be used arbitrarily.
*/
#define RTNL_FAMILY_IPMR 128
#define RTNL_FAMILY_MAX 128
/**** /****
* Routing/neighbour discovery messages. * Routing/neighbour discovery messages.
****/ ****/
......
...@@ -104,7 +104,7 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla) ...@@ -104,7 +104,7 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
return frh->table; return frh->table;
} }
extern struct fib_rules_ops *fib_rules_register(struct fib_rules_ops *, struct net *); extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *);
extern void fib_rules_unregister(struct fib_rules_ops *); extern void fib_rules_unregister(struct fib_rules_ops *);
extern void fib_rules_cleanup_ops(struct fib_rules_ops *); extern void fib_rules_cleanup_ops(struct fib_rules_ops *);
......
...@@ -122,7 +122,7 @@ static int __fib_rules_register(struct fib_rules_ops *ops) ...@@ -122,7 +122,7 @@ static int __fib_rules_register(struct fib_rules_ops *ops)
} }
struct fib_rules_ops * struct fib_rules_ops *
fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) fib_rules_register(const struct fib_rules_ops *tmpl, struct net *net)
{ {
struct fib_rules_ops *ops; struct fib_rules_ops *ops;
int err; int err;
......
...@@ -98,7 +98,7 @@ int lockdep_rtnl_is_held(void) ...@@ -98,7 +98,7 @@ int lockdep_rtnl_is_held(void)
EXPORT_SYMBOL(lockdep_rtnl_is_held); EXPORT_SYMBOL(lockdep_rtnl_is_held);
#endif /* #ifdef CONFIG_PROVE_LOCKING */ #endif /* #ifdef CONFIG_PROVE_LOCKING */
static struct rtnl_link *rtnl_msg_handlers[NPROTO]; static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1];
static inline int rtm_msgindex(int msgtype) static inline int rtm_msgindex(int msgtype)
{ {
...@@ -118,7 +118,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) ...@@ -118,7 +118,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
{ {
struct rtnl_link *tab; struct rtnl_link *tab;
if (protocol < NPROTO) if (protocol <= RTNL_FAMILY_MAX)
tab = rtnl_msg_handlers[protocol]; tab = rtnl_msg_handlers[protocol];
else else
tab = NULL; tab = NULL;
...@@ -133,7 +133,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) ...@@ -133,7 +133,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
{ {
struct rtnl_link *tab; struct rtnl_link *tab;
if (protocol < NPROTO) if (protocol <= RTNL_FAMILY_MAX)
tab = rtnl_msg_handlers[protocol]; tab = rtnl_msg_handlers[protocol];
else else
tab = NULL; tab = NULL;
...@@ -167,7 +167,7 @@ int __rtnl_register(int protocol, int msgtype, ...@@ -167,7 +167,7 @@ int __rtnl_register(int protocol, int msgtype,
struct rtnl_link *tab; struct rtnl_link *tab;
int msgindex; int msgindex;
BUG_ON(protocol < 0 || protocol >= NPROTO); BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
msgindex = rtm_msgindex(msgtype); msgindex = rtm_msgindex(msgtype);
tab = rtnl_msg_handlers[protocol]; tab = rtnl_msg_handlers[protocol];
...@@ -219,7 +219,7 @@ int rtnl_unregister(int protocol, int msgtype) ...@@ -219,7 +219,7 @@ int rtnl_unregister(int protocol, int msgtype)
{ {
int msgindex; int msgindex;
BUG_ON(protocol < 0 || protocol >= NPROTO); BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
msgindex = rtm_msgindex(msgtype); msgindex = rtm_msgindex(msgtype);
if (rtnl_msg_handlers[protocol] == NULL) if (rtnl_msg_handlers[protocol] == NULL)
...@@ -241,7 +241,7 @@ EXPORT_SYMBOL_GPL(rtnl_unregister); ...@@ -241,7 +241,7 @@ EXPORT_SYMBOL_GPL(rtnl_unregister);
*/ */
void rtnl_unregister_all(int protocol) void rtnl_unregister_all(int protocol)
{ {
BUG_ON(protocol < 0 || protocol >= NPROTO); BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
kfree(rtnl_msg_handlers[protocol]); kfree(rtnl_msg_handlers[protocol]);
rtnl_msg_handlers[protocol] = NULL; rtnl_msg_handlers[protocol] = NULL;
...@@ -1385,7 +1385,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1385,7 +1385,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
if (s_idx == 0) if (s_idx == 0)
s_idx = 1; s_idx = 1;
for (idx = 1; idx < NPROTO; idx++) { for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) {
int type = cb->nlh->nlmsg_type-RTM_BASE; int type = cb->nlh->nlmsg_type-RTM_BASE;
if (idx < s_idx || idx == PF_PACKET) if (idx < s_idx || idx == PF_PACKET)
continue; continue;
......
...@@ -216,8 +216,8 @@ static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops) ...@@ -216,8 +216,8 @@ static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
dn_rt_cache_flush(-1); dn_rt_cache_flush(-1);
} }
static struct fib_rules_ops dn_fib_rules_ops_template = { static const struct fib_rules_ops __net_initdata dn_fib_rules_ops_template = {
.family = FIB_RULES_DECNET, .family = AF_DECnet,
.rule_size = sizeof(struct dn_fib_rule), .rule_size = sizeof(struct dn_fib_rule),
.addr_size = sizeof(u16), .addr_size = sizeof(u16),
.action = dn_fib_rule_action, .action = dn_fib_rule_action,
......
...@@ -245,8 +245,8 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops) ...@@ -245,8 +245,8 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
rt_cache_flush(ops->fro_net, -1); rt_cache_flush(ops->fro_net, -1);
} }
static struct fib_rules_ops fib4_rules_ops_template = { static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = {
.family = FIB_RULES_IPV4, .family = AF_INET,
.rule_size = sizeof(struct fib4_rule), .rule_size = sizeof(struct fib4_rule),
.addr_size = sizeof(u32), .addr_size = sizeof(u32),
.action = fib4_rule_action, .action = fib4_rule_action,
......
...@@ -128,8 +128,8 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -128,8 +128,8 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
int local); int local);
static int ipmr_cache_report(struct mr_table *mrt, static int ipmr_cache_report(struct mr_table *mrt,
struct sk_buff *pkt, vifi_t vifi, int assert); struct sk_buff *pkt, vifi_t vifi, int assert);
static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm); struct mfc_cache *c, struct rtmsg *rtm);
static void ipmr_expire_process(unsigned long arg); static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
...@@ -216,8 +216,8 @@ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb, ...@@ -216,8 +216,8 @@ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
return 0; return 0;
} }
static struct fib_rules_ops ipmr_rules_ops_template = { static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = {
.family = FIB_RULES_IPMR, .family = RTNL_FAMILY_IPMR,
.rule_size = sizeof(struct ipmr_rule), .rule_size = sizeof(struct ipmr_rule),
.addr_size = sizeof(u32), .addr_size = sizeof(u32),
.action = ipmr_rule_action, .action = ipmr_rule_action,
...@@ -831,7 +831,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, ...@@ -831,7 +831,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
if (ip_hdr(skb)->version == 0) { if (ip_hdr(skb)->version == 0) {
struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
if (ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
nlh->nlmsg_len = (skb_tail_pointer(skb) - nlh->nlmsg_len = (skb_tail_pointer(skb) -
(u8 *)nlh); (u8 *)nlh);
} else { } else {
...@@ -1904,9 +1904,8 @@ static int pim_rcv(struct sk_buff * skb) ...@@ -1904,9 +1904,8 @@ static int pim_rcv(struct sk_buff * skb)
} }
#endif #endif
static int static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct mfc_cache *c, struct rtmsg *rtm)
struct rtmsg *rtm)
{ {
int ct; int ct;
struct rtnexthop *nhp; struct rtnexthop *nhp;
...@@ -1994,11 +1993,93 @@ int ipmr_get_route(struct net *net, ...@@ -1994,11 +1993,93 @@ int ipmr_get_route(struct net *net,
if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
cache->mfc_flags |= MFC_NOTIFY; cache->mfc_flags |= MFC_NOTIFY;
err = ipmr_fill_mroute(mrt, skb, cache, rtm); err = __ipmr_fill_mroute(mrt, skb, cache, rtm);
read_unlock(&mrt_lock); read_unlock(&mrt_lock);
return err; return err;
} }
static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
u32 pid, u32 seq, struct mfc_cache *c)
{
struct nlmsghdr *nlh;
struct rtmsg *rtm;
nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
if (nlh == NULL)
return -EMSGSIZE;
rtm = nlmsg_data(nlh);
rtm->rtm_family = RTNL_FAMILY_IPMR;
rtm->rtm_dst_len = 32;
rtm->rtm_src_len = 32;
rtm->rtm_tos = 0;
rtm->rtm_table = mrt->id;
NLA_PUT_U32(skb, RTA_TABLE, mrt->id);
rtm->rtm_type = RTN_MULTICAST;
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
rtm->rtm_protocol = RTPROT_UNSPEC;
rtm->rtm_flags = 0;
NLA_PUT_BE32(skb, RTA_SRC, c->mfc_origin);
NLA_PUT_BE32(skb, RTA_DST, c->mfc_mcastgrp);
if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0)
goto nla_put_failure;
return nlmsg_end(skb, nlh);
nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
}
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct mr_table *mrt;
struct mfc_cache *mfc;
unsigned int t = 0, s_t;
unsigned int h = 0, s_h;
unsigned int e = 0, s_e;
s_t = cb->args[0];
s_h = cb->args[1];
s_e = cb->args[2];
read_lock(&mrt_lock);
ipmr_for_each_table(mrt, net) {
if (t < s_t)
goto next_table;
if (t > s_t)
s_h = 0;
for (h = s_h; h < MFC_LINES; h++) {
list_for_each_entry(mfc, &mrt->mfc_cache_array[h], list) {
if (e < s_e)
goto next_entry;
if (ipmr_fill_mroute(mrt, skb,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
mfc) < 0)
goto done;
next_entry:
e++;
}
e = s_e = 0;
}
s_h = 0;
next_table:
t++;
}
done:
read_unlock(&mrt_lock);
cb->args[2] = e;
cb->args[1] = h;
cb->args[0] = t;
return skb->len;
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
/* /*
* The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
...@@ -2355,6 +2436,7 @@ int __init ip_mr_init(void) ...@@ -2355,6 +2436,7 @@ int __init ip_mr_init(void)
goto add_proto_fail; goto add_proto_fail;
} }
#endif #endif
rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute);
return 0; return 0;
#ifdef CONFIG_IP_PIMSM_V2 #ifdef CONFIG_IP_PIMSM_V2
......
...@@ -237,8 +237,8 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) ...@@ -237,8 +237,8 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+ nla_total_size(16); /* src */ + nla_total_size(16); /* src */
} }
static struct fib_rules_ops fib6_rules_ops_template = { static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = {
.family = FIB_RULES_IPV6, .family = AF_INET6,
.rule_size = sizeof(struct fib6_rule), .rule_size = sizeof(struct fib6_rule),
.addr_size = sizeof(struct in6_addr), .addr_size = sizeof(struct in6_addr),
.action = fib6_rule_action, .action = fib6_rule_action,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment