#define FFprint(a...) printk(KERN_DEBUG a)
-static struct sock *fibnl;
-
#ifndef CONFIG_IP_MULTIPLE_TABLES
static int __net_init fib4_rules_init(struct net *net)
return len + nla_total_size(4);
}
-static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
+static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
struct fib_config *cfg)
{
__be32 addr;
int plen;
memset(cfg, 0, sizeof(*cfg));
- cfg->fc_nlinfo.nl_net = &init_net;
+ cfg->fc_nlinfo.nl_net = net;
if (rt->rt_dst.sa_family != AF_INET)
return -EAFNOSUPPORT;
colon = strchr(devname, ':');
if (colon)
*colon = 0;
- dev = __dev_get_by_name(&init_net, devname);
+ dev = __dev_get_by_name(net, devname);
if (!dev)
return -ENODEV;
cfg->fc_oif = dev->ifindex;
if (rt->rt_gateway.sa_family == AF_INET && addr) {
cfg->fc_gw = addr;
if (rt->rt_flags & RTF_GATEWAY &&
- inet_addr_type(&init_net, addr) == RTN_UNICAST)
+ inet_addr_type(net, addr) == RTN_UNICAST)
cfg->fc_scope = RT_SCOPE_UNIVERSE;
}
* Handle IP routing ioctl calls. These are used to manipulate the routing tables
*/
-int ip_rt_ioctl(unsigned int cmd, void __user *arg)
+int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
{
struct fib_config cfg;
struct rtentry rt;
return -EFAULT;
rtnl_lock();
- err = rtentry_to_fib_config(cmd, &rt, &cfg);
+ err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
if (err == 0) {
struct fib_table *tb;
if (cmd == SIOCDELRT) {
- tb = fib_get_table(&init_net, cfg.fc_table);
+ tb = fib_get_table(net, cfg.fc_table);
if (tb)
err = tb->tb_delete(tb, &cfg);
else
err = -ESRCH;
} else {
- tb = fib_new_table(&init_net, cfg.fc_table);
+ tb = fib_new_table(net, cfg.fc_table);
if (tb)
err = tb->tb_insert(tb, &cfg);
else
[RTA_FLOW] = { .type = NLA_U32 },
};
-static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
- struct fib_config *cfg)
+static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct fib_config *cfg)
{
struct nlattr *attr;
int err, remaining;
cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
cfg->fc_nlinfo.nlh = nlh;
- cfg->fc_nlinfo.nl_net = &init_net;
+ cfg->fc_nlinfo.nl_net = net;
if (cfg->fc_type > RTN_MAX) {
err = -EINVAL;
if (net != &init_net)
return -EINVAL;
- err = rtm_to_fib_config(skb, nlh, &cfg);
+ err = rtm_to_fib_config(net, skb, nlh, &cfg);
if (err < 0)
goto errout;
if (net != &init_net)
return -EINVAL;
- err = rtm_to_fib_config(skb, nlh, &cfg);
+ err = rtm_to_fib_config(net, skb, nlh, &cfg);
if (err < 0)
goto errout;
static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
{
+ struct net *net = ifa->ifa_dev->dev->nd_net;
struct fib_table *tb;
struct fib_config cfg = {
.fc_protocol = RTPROT_KERNEL,
.fc_oif = ifa->ifa_dev->dev->ifindex,
.fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
.fc_nlinfo = {
- .nl_net = &init_net,
+ .nl_net = net,
},
};
if (type == RTN_UNICAST)
- tb = fib_new_table(&init_net, RT_TABLE_MAIN);
+ tb = fib_new_table(net, RT_TABLE_MAIN);
else
- tb = fib_new_table(&init_net, RT_TABLE_LOCAL);
+ tb = fib_new_table(net, RT_TABLE_LOCAL);
if (tb == NULL)
return;
static void nl_fib_input(struct sk_buff *skb)
{
+ struct net *net;
struct fib_result_nl *frn;
struct nlmsghdr *nlh;
struct fib_table *tb;
u32 pid;
+ net = skb->sk->sk_net;
nlh = nlmsg_hdr(skb);
if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
nlh = nlmsg_hdr(skb);
frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
- tb = fib_get_table(&init_net, frn->tb_id_in);
+ tb = fib_get_table(net, frn->tb_id_in);
nl_fib_lookup(frn, tb);
pid = NETLINK_CB(skb).pid; /* pid of sending process */
NETLINK_CB(skb).pid = 0; /* from kernel */
NETLINK_CB(skb).dst_group = 0; /* unicast */
- netlink_unicast(fibnl, skb, pid, MSG_DONTWAIT);
+ netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT);
}
static int nl_fib_lookup_init(struct net *net)
{
- fibnl = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
- nl_fib_input, NULL, THIS_MODULE);
- if (fibnl == NULL)
+ struct sock *sk;
+ sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
+ nl_fib_input, NULL, THIS_MODULE);
+ if (sk == NULL)
return -EAFNOSUPPORT;
+ /* Don't hold an extra reference on the namespace */
+ put_net(sk->sk_net);
+ net->ipv4.fibnl = sk;
return 0;
}
static void nl_fib_lookup_exit(struct net *net)
{
- sock_put(fibnl);
+ /* At the last minute lie and say this is a socket for the
+ * initial network namespace. So the socket will be safe to free.
+ */
+ net->ipv4.fibnl->sk_net = get_net(&init_net);
+ sock_put(net->ipv4.fibnl);
}
static void fib_disable_ip(struct net_device *dev, int force)