ipmr.c 63.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *	IP multicast routing support for mrouted 3.6/3.8
 *
4
 *		(c) 1995 Alan Cox, <alan@lxorguk.ukuu.org.uk>
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *	  Linux Consultancy and Custom Driver Development
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 *	Fixes:
 *	Michael Chastain	:	Incorrect size of copying.
 *	Alan Cox		:	Added the cache manager code
 *	Alan Cox		:	Fixed the clone/copy bug and device race.
 *	Mike McLagan		:	Routing by source
 *	Malcolm Beattie		:	Buffer handling fixes.
 *	Alexey Kuznetsov	:	Double buffer free and other fixes.
 *	SVR Anand		:	Fixed several multicast bugs and problems.
 *	Alexey Kuznetsov	:	Status, optimisations and more.
 *	Brad Parker		:	Better behaviour on mrouted upcall
 *					overflow.
 *      Carlos Picoto           :       PIMv1 Support
 *	Pavlin Ivanov Radoslavov:	PIMv2 Registers must checksum only PIM header
25
 *					Relax this requirement to work with older peers.
L
Linus Torvalds 已提交
26 27 28 29 30
 *
 */

#include <asm/uaccess.h>
#include <linux/types.h>
31
#include <linux/capability.h>
L
Linus Torvalds 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/mroute.h>
#include <linux/init.h>
48
#include <linux/if_ether.h>
49
#include <linux/slab.h>
50
#include <net/net_namespace.h>
L
Linus Torvalds 已提交
51 52 53
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
54
#include <net/route.h>
L
Linus Torvalds 已提交
55 56 57 58 59 60 61
#include <net/sock.h>
#include <net/icmp.h>
#include <net/udp.h>
#include <net/raw.h>
#include <linux/notifier.h>
#include <linux/if_arp.h>
#include <linux/netfilter_ipv4.h>
62
#include <linux/compat.h>
63
#include <linux/export.h>
64
#include <net/ip_tunnels.h>
L
Linus Torvalds 已提交
65
#include <net/checksum.h>
66
#include <net/netlink.h>
67
#include <net/fib_rules.h>
68
#include <linux/netconf.h>
L
Linus Torvalds 已提交
69 70 71 72 73

#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
#define CONFIG_IP_PIMSM	1
#endif

74
struct mr_table {
75
	struct list_head	list;
76 77 78
#ifdef CONFIG_NET_NS
	struct net		*net;
#endif
79
	u32			id;
E
Eric Dumazet 已提交
80
	struct sock __rcu	*mroute_sk;
81 82 83 84 85 86
	struct timer_list	ipmr_expire_timer;
	struct list_head	mfc_unres_queue;
	struct list_head	mfc_cache_array[MFC_LINES];
	struct vif_device	vif_table[MAXVIFS];
	int			maxvif;
	atomic_t		cache_resolve_queue_len;
87 88
	bool			mroute_do_assert;
	bool			mroute_do_pim;
89 90 91 92 93
#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
	int			mroute_reg_vif_num;
#endif
};

94 95 96 97 98 99 100 101
struct ipmr_rule {
	struct fib_rule		common;
};

struct ipmr_result {
	struct mr_table		*mrt;
};

L
Linus Torvalds 已提交
102
/* Big lock, protecting vif table, mrt cache and mroute socket state.
E
Eric Dumazet 已提交
103
 * Note that the changes are semaphored via rtnl_lock.
L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111
 */

static DEFINE_RWLOCK(mrt_lock);

/*
 *	Multicast router control variables
 */

112
#define VIF_EXISTS(_mrt, _idx) ((_mrt)->vif_table[_idx].dev != NULL)
L
Linus Torvalds 已提交
113 114 115 116 117

/* Special spinlock for queue of unresolved entries */
static DEFINE_SPINLOCK(mfc_unres_lock);

/* We return to original Alan's scheme. Hash table of resolved
E
Eric Dumazet 已提交
118 119 120 121 122
 * entries is changed only in process context and protected
 * with weak lock mrt_lock. Queue of unresolved entries is protected
 * with strong spinlock mfc_unres_lock.
 *
 * In this case data path is free of exclusive locks at all.
L
Linus Torvalds 已提交
123 124
 */

125
static struct kmem_cache *mrt_cachep __read_mostly;
L
Linus Torvalds 已提交
126

127
static struct mr_table *ipmr_new_table(struct net *net, u32 id);
128 129
static void ipmr_free_table(struct mr_table *mrt);

130 131 132
static void ip_mr_forward(struct net *net, struct mr_table *mrt,
			  struct sk_buff *skb, struct mfc_cache *cache,
			  int local);
133
static int ipmr_cache_report(struct mr_table *mrt,
134
			     struct sk_buff *pkt, vifi_t vifi, int assert);
135 136
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
			      struct mfc_cache *c, struct rtmsg *rtm);
137 138
static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
				 int cmd);
139
static void mroute_clean_tables(struct mr_table *mrt);
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
static void ipmr_expire_process(unsigned long arg);

#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
#define ipmr_for_each_table(mrt, net) \
	list_for_each_entry_rcu(mrt, &net->ipv4.mr_tables, list)

static struct mr_table *ipmr_get_table(struct net *net, u32 id)
{
	struct mr_table *mrt;

	ipmr_for_each_table(mrt, net) {
		if (mrt->id == id)
			return mrt;
	}
	return NULL;
}

D
David S. Miller 已提交
157
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
158 159 160 161 162 163
			   struct mr_table **mrt)
{
	struct ipmr_result res;
	struct fib_lookup_arg arg = { .result = &res, };
	int err;

D
David S. Miller 已提交
164 165
	err = fib_rules_lookup(net->ipv4.mr_rules_ops,
			       flowi4_to_flowi(flp4), 0, &arg);
166 167 168 169 170 171 172 173 174 175 176
	if (err < 0)
		return err;
	*mrt = res.mrt;
	return 0;
}

static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
			    int flags, struct fib_lookup_arg *arg)
{
	struct ipmr_result *res = arg->result;
	struct mr_table *mrt;
L
Linus Torvalds 已提交
177

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
	switch (rule->action) {
	case FR_ACT_TO_TBL:
		break;
	case FR_ACT_UNREACHABLE:
		return -ENETUNREACH;
	case FR_ACT_PROHIBIT:
		return -EACCES;
	case FR_ACT_BLACKHOLE:
	default:
		return -EINVAL;
	}

	mrt = ipmr_get_table(rule->fr_net, rule->table);
	if (mrt == NULL)
		return -EAGAIN;
	res->mrt = mrt;
	return 0;
}

static int ipmr_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
{
	return 1;
}

static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = {
	FRA_GENERIC_POLICY,
};

static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
			       struct fib_rule_hdr *frh, struct nlattr **tb)
{
	return 0;
}

static int ipmr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
			     struct nlattr **tb)
{
	return 1;
}

static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
			  struct fib_rule_hdr *frh)
{
	frh->dst_len = 0;
	frh->src_len = 0;
	frh->tos     = 0;
	return 0;
}

227
static const struct fib_rules_ops __net_initconst ipmr_rules_ops_template = {
228
	.family		= RTNL_FAMILY_IPMR,
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
	.rule_size	= sizeof(struct ipmr_rule),
	.addr_size	= sizeof(u32),
	.action		= ipmr_rule_action,
	.match		= ipmr_rule_match,
	.configure	= ipmr_rule_configure,
	.compare	= ipmr_rule_compare,
	.default_pref	= fib_default_rule_pref,
	.fill		= ipmr_rule_fill,
	.nlgroup	= RTNLGRP_IPV4_RULE,
	.policy		= ipmr_rule_policy,
	.owner		= THIS_MODULE,
};

static int __net_init ipmr_rules_init(struct net *net)
{
	struct fib_rules_ops *ops;
	struct mr_table *mrt;
	int err;

	ops = fib_rules_register(&ipmr_rules_ops_template, net);
	if (IS_ERR(ops))
		return PTR_ERR(ops);

	INIT_LIST_HEAD(&net->ipv4.mr_tables);

	mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
	if (mrt == NULL) {
		err = -ENOMEM;
		goto err1;
	}

	err = fib_default_rule_add(ops, 0x7fff, RT_TABLE_DEFAULT, 0);
	if (err < 0)
		goto err2;

	net->ipv4.mr_rules_ops = ops;
	return 0;

err2:
	kfree(mrt);
err1:
	fib_rules_unregister(ops);
	return err;
}

static void __net_exit ipmr_rules_exit(struct net *net)
{
	struct mr_table *mrt, *next;

E
Eric Dumazet 已提交
278 279
	list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
		list_del(&mrt->list);
280
		ipmr_free_table(mrt);
E
Eric Dumazet 已提交
281
	}
282 283 284 285 286 287 288 289 290 291 292
	fib_rules_unregister(net->ipv4.mr_rules_ops);
}
#else
#define ipmr_for_each_table(mrt, net) \
	for (mrt = net->ipv4.mrt; mrt; mrt = NULL)

static struct mr_table *ipmr_get_table(struct net *net, u32 id)
{
	return net->ipv4.mrt;
}

D
David S. Miller 已提交
293
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
294 295 296 297 298 299 300 301 302 303 304 305 306 307
			   struct mr_table **mrt)
{
	*mrt = net->ipv4.mrt;
	return 0;
}

static int __net_init ipmr_rules_init(struct net *net)
{
	net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
	return net->ipv4.mrt ? 0 : -ENOMEM;
}

static void __net_exit ipmr_rules_exit(struct net *net)
{
308
	ipmr_free_table(net->ipv4.mrt);
309 310 311 312 313 314 315
}
#endif

static struct mr_table *ipmr_new_table(struct net *net, u32 id)
{
	struct mr_table *mrt;
	unsigned int i;
L
Linus Torvalds 已提交
316

317 318 319 320 321 322 323
	mrt = ipmr_get_table(net, id);
	if (mrt != NULL)
		return mrt;

	mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
	if (mrt == NULL)
		return NULL;
324
	write_pnet(&mrt->net, net);
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	mrt->id = id;

	/* Forwarding cache */
	for (i = 0; i < MFC_LINES; i++)
		INIT_LIST_HEAD(&mrt->mfc_cache_array[i]);

	INIT_LIST_HEAD(&mrt->mfc_unres_queue);

	setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process,
		    (unsigned long)mrt);

#ifdef CONFIG_IP_PIMSM
	mrt->mroute_reg_vif_num = -1;
#endif
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
	list_add_tail_rcu(&mrt->list, &net->ipv4.mr_tables);
#endif
	return mrt;
}
L
Linus Torvalds 已提交
344

345 346 347 348 349 350 351
static void ipmr_free_table(struct mr_table *mrt)
{
	del_timer_sync(&mrt->ipmr_expire_timer);
	mroute_clean_tables(mrt);
	kfree(mrt);
}

L
Linus Torvalds 已提交
352 353
/* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */

354 355
static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
{
356 357
	struct net *net = dev_net(dev);

358 359
	dev_close(dev);

360
	dev = __dev_get_by_name(net, "tunl0");
361
	if (dev) {
362
		const struct net_device_ops *ops = dev->netdev_ops;
363 364 365 366 367 368 369 370 371 372 373 374
		struct ifreq ifr;
		struct ip_tunnel_parm p;

		memset(&p, 0, sizeof(p));
		p.iph.daddr = v->vifc_rmt_addr.s_addr;
		p.iph.saddr = v->vifc_lcl_addr.s_addr;
		p.iph.version = 4;
		p.iph.ihl = 5;
		p.iph.protocol = IPPROTO_IPIP;
		sprintf(p.name, "dvmrp%d", v->vifc_vifi);
		ifr.ifr_ifru.ifru_data = (__force void __user *)&p;

375 376 377 378 379 380 381
		if (ops->ndo_do_ioctl) {
			mm_segment_t oldfs = get_fs();

			set_fs(KERNEL_DS);
			ops->ndo_do_ioctl(dev, &ifr, SIOCDELTUNNEL);
			set_fs(oldfs);
		}
382 383 384
	}
}

L
Linus Torvalds 已提交
385
static
386
struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
L
Linus Torvalds 已提交
387 388 389
{
	struct net_device  *dev;

390
	dev = __dev_get_by_name(net, "tunl0");
L
Linus Torvalds 已提交
391 392

	if (dev) {
393
		const struct net_device_ops *ops = dev->netdev_ops;
L
Linus Torvalds 已提交
394 395 396 397 398 399 400 401 402 403 404 405
		int err;
		struct ifreq ifr;
		struct ip_tunnel_parm p;
		struct in_device  *in_dev;

		memset(&p, 0, sizeof(p));
		p.iph.daddr = v->vifc_rmt_addr.s_addr;
		p.iph.saddr = v->vifc_lcl_addr.s_addr;
		p.iph.version = 4;
		p.iph.ihl = 5;
		p.iph.protocol = IPPROTO_IPIP;
		sprintf(p.name, "dvmrp%d", v->vifc_vifi);
S
Stephen Hemminger 已提交
406
		ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
L
Linus Torvalds 已提交
407

408 409 410 411 412 413
		if (ops->ndo_do_ioctl) {
			mm_segment_t oldfs = get_fs();

			set_fs(KERNEL_DS);
			err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL);
			set_fs(oldfs);
E
Eric Dumazet 已提交
414
		} else {
415
			err = -EOPNOTSUPP;
E
Eric Dumazet 已提交
416
		}
L
Linus Torvalds 已提交
417 418
		dev = NULL;

419 420
		if (err == 0 &&
		    (dev = __dev_get_by_name(net, p.name)) != NULL) {
L
Linus Torvalds 已提交
421 422
			dev->flags |= IFF_MULTICAST;

423
			in_dev = __in_dev_get_rtnl(dev);
424
			if (in_dev == NULL)
L
Linus Torvalds 已提交
425
				goto failure;
426 427

			ipv4_devconf_setall(in_dev);
428
			neigh_parms_data_state_setall(in_dev->arp_parms);
429
			IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
L
Linus Torvalds 已提交
430 431 432

			if (dev_open(dev))
				goto failure;
433
			dev_hold(dev);
L
Linus Torvalds 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
		}
	}
	return dev;

failure:
	/* allow the register to be completed before unregistering. */
	rtnl_unlock();
	rtnl_lock();

	unregister_netdevice(dev);
	return NULL;
}

#ifdef CONFIG_IP_PIMSM

449
static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
L
Linus Torvalds 已提交
450
{
451
	struct net *net = dev_net(dev);
452
	struct mr_table *mrt;
D
David S. Miller 已提交
453 454 455 456
	struct flowi4 fl4 = {
		.flowi4_oif	= dev->ifindex,
		.flowi4_iif	= skb->skb_iif,
		.flowi4_mark	= skb->mark,
457 458 459
	};
	int err;

D
David S. Miller 已提交
460
	err = ipmr_fib_lookup(net, &fl4, &mrt);
461 462
	if (err < 0) {
		kfree_skb(skb);
463
		return err;
464
	}
465

L
Linus Torvalds 已提交
466
	read_lock(&mrt_lock);
467 468
	dev->stats.tx_bytes += skb->len;
	dev->stats.tx_packets++;
469
	ipmr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, IGMPMSG_WHOLEPKT);
L
Linus Torvalds 已提交
470 471
	read_unlock(&mrt_lock);
	kfree_skb(skb);
472
	return NETDEV_TX_OK;
L
Linus Torvalds 已提交
473 474
}

475 476 477 478
static const struct net_device_ops reg_vif_netdev_ops = {
	.ndo_start_xmit	= reg_vif_xmit,
};

L
Linus Torvalds 已提交
479 480 481
static void reg_vif_setup(struct net_device *dev)
{
	dev->type		= ARPHRD_PIMREG;
482
	dev->mtu		= ETH_DATA_LEN - sizeof(struct iphdr) - 8;
L
Linus Torvalds 已提交
483
	dev->flags		= IFF_NOARP;
484
	dev->netdev_ops		= &reg_vif_netdev_ops,
L
Linus Torvalds 已提交
485
	dev->destructor		= free_netdev;
T
Tom Goff 已提交
486
	dev->features		|= NETIF_F_NETNS_LOCAL;
L
Linus Torvalds 已提交
487 488
}

489
static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
L
Linus Torvalds 已提交
490 491 492
{
	struct net_device *dev;
	struct in_device *in_dev;
493
	char name[IFNAMSIZ];
L
Linus Torvalds 已提交
494

495 496 497 498
	if (mrt->id == RT_TABLE_DEFAULT)
		sprintf(name, "pimreg");
	else
		sprintf(name, "pimreg%u", mrt->id);
L
Linus Torvalds 已提交
499

500
	dev = alloc_netdev(0, name, reg_vif_setup);
L
Linus Torvalds 已提交
501 502 503 504

	if (dev == NULL)
		return NULL;

T
Tom Goff 已提交
505 506
	dev_net_set(dev, net);

L
Linus Torvalds 已提交
507 508 509 510 511 512
	if (register_netdevice(dev)) {
		free_netdev(dev);
		return NULL;
	}
	dev->iflink = 0;

513
	rcu_read_lock();
E
Eric Dumazet 已提交
514 515
	in_dev = __in_dev_get_rcu(dev);
	if (!in_dev) {
516
		rcu_read_unlock();
L
Linus Torvalds 已提交
517
		goto failure;
518
	}
L
Linus Torvalds 已提交
519

520
	ipv4_devconf_setall(in_dev);
521
	neigh_parms_data_state_setall(in_dev->arp_parms);
522 523
	IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
	rcu_read_unlock();
L
Linus Torvalds 已提交
524 525 526 527

	if (dev_open(dev))
		goto failure;

528 529
	dev_hold(dev);

L
Linus Torvalds 已提交
530 531 532 533 534 535 536 537 538 539 540 541
	return dev;

failure:
	/* allow the register to be completed before unregistering. */
	rtnl_unlock();
	rtnl_lock();

	unregister_netdevice(dev);
	return NULL;
}
#endif

542 543
/**
 *	vif_delete - Delete a VIF entry
544
 *	@notify: Set to 1, if the caller is a notifier_call
L
Linus Torvalds 已提交
545
 */
546

547
static int vif_delete(struct mr_table *mrt, int vifi, int notify,
548
		      struct list_head *head)
L
Linus Torvalds 已提交
549 550 551 552 553
{
	struct vif_device *v;
	struct net_device *dev;
	struct in_device *in_dev;

554
	if (vifi < 0 || vifi >= mrt->maxvif)
L
Linus Torvalds 已提交
555 556
		return -EADDRNOTAVAIL;

557
	v = &mrt->vif_table[vifi];
L
Linus Torvalds 已提交
558 559 560 561 562 563 564 565 566 567 568

	write_lock_bh(&mrt_lock);
	dev = v->dev;
	v->dev = NULL;

	if (!dev) {
		write_unlock_bh(&mrt_lock);
		return -EADDRNOTAVAIL;
	}

#ifdef CONFIG_IP_PIMSM
569 570
	if (vifi == mrt->mroute_reg_vif_num)
		mrt->mroute_reg_vif_num = -1;
L
Linus Torvalds 已提交
571 572
#endif

E
Eric Dumazet 已提交
573
	if (vifi + 1 == mrt->maxvif) {
L
Linus Torvalds 已提交
574
		int tmp;
E
Eric Dumazet 已提交
575 576

		for (tmp = vifi - 1; tmp >= 0; tmp--) {
577
			if (VIF_EXISTS(mrt, tmp))
L
Linus Torvalds 已提交
578 579
				break;
		}
580
		mrt->maxvif = tmp+1;
L
Linus Torvalds 已提交
581 582 583 584 585 586
	}

	write_unlock_bh(&mrt_lock);

	dev_set_allmulti(dev, -1);

E
Eric Dumazet 已提交
587 588
	in_dev = __in_dev_get_rtnl(dev);
	if (in_dev) {
589
		IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
590 591 592
		inet_netconf_notify_devconf(dev_net(dev),
					    NETCONFA_MC_FORWARDING,
					    dev->ifindex, &in_dev->cnf);
L
Linus Torvalds 已提交
593 594 595
		ip_rt_multicast_event(in_dev);
	}

E
Eric Dumazet 已提交
596
	if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER) && !notify)
597
		unregister_netdevice_queue(dev, head);
L
Linus Torvalds 已提交
598 599 600 601 602

	dev_put(dev);
	return 0;
}

603
static void ipmr_cache_free_rcu(struct rcu_head *head)
604
{
605 606
	struct mfc_cache *c = container_of(head, struct mfc_cache, rcu);

607 608 609
	kmem_cache_free(mrt_cachep, c);
}

610 611 612 613 614
static inline void ipmr_cache_free(struct mfc_cache *c)
{
	call_rcu(&c->rcu, ipmr_cache_free_rcu);
}

L
Linus Torvalds 已提交
615
/* Destroy an unresolved cache entry, killing queued skbs
E
Eric Dumazet 已提交
616
 * and reporting error to netlink readers.
L
Linus Torvalds 已提交
617 618
 */

619
static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
L
Linus Torvalds 已提交
620
{
621
	struct net *net = read_pnet(&mrt->net);
L
Linus Torvalds 已提交
622
	struct sk_buff *skb;
623
	struct nlmsgerr *e;
L
Linus Torvalds 已提交
624

625
	atomic_dec(&mrt->cache_resolve_queue_len);
L
Linus Torvalds 已提交
626

J
Jianjun Kong 已提交
627
	while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) {
628
		if (ip_hdr(skb)->version == 0) {
L
Linus Torvalds 已提交
629 630
			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
			nlh->nlmsg_type = NLMSG_ERROR;
631
			nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
L
Linus Torvalds 已提交
632
			skb_trim(skb, nlh->nlmsg_len);
633
			e = nlmsg_data(nlh);
634 635
			e->error = -ETIMEDOUT;
			memset(&e->msg, 0, sizeof(e->msg));
636

637
			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
E
Eric Dumazet 已提交
638
		} else {
L
Linus Torvalds 已提交
639
			kfree_skb(skb);
E
Eric Dumazet 已提交
640
		}
L
Linus Torvalds 已提交
641 642
	}

643
	ipmr_cache_free(c);
L
Linus Torvalds 已提交
644 645 646
}


647
/* Timer process for the unresolved queue. */
L
Linus Torvalds 已提交
648

649
static void ipmr_expire_process(unsigned long arg)
L
Linus Torvalds 已提交
650
{
651
	struct mr_table *mrt = (struct mr_table *)arg;
L
Linus Torvalds 已提交
652 653
	unsigned long now;
	unsigned long expires;
654
	struct mfc_cache *c, *next;
L
Linus Torvalds 已提交
655 656

	if (!spin_trylock(&mfc_unres_lock)) {
657
		mod_timer(&mrt->ipmr_expire_timer, jiffies+HZ/10);
L
Linus Torvalds 已提交
658 659 660
		return;
	}

661
	if (list_empty(&mrt->mfc_unres_queue))
L
Linus Torvalds 已提交
662 663 664 665 666
		goto out;

	now = jiffies;
	expires = 10*HZ;

667
	list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
L
Linus Torvalds 已提交
668 669 670 671 672 673 674
		if (time_after(c->mfc_un.unres.expires, now)) {
			unsigned long interval = c->mfc_un.unres.expires - now;
			if (interval < expires)
				expires = interval;
			continue;
		}

675
		list_del(&c->list);
676
		mroute_netlink_event(mrt, c, RTM_DELROUTE);
677
		ipmr_destroy_unres(mrt, c);
L
Linus Torvalds 已提交
678 679
	}

680 681
	if (!list_empty(&mrt->mfc_unres_queue))
		mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
L
Linus Torvalds 已提交
682 683 684 685 686 687 688

out:
	spin_unlock(&mfc_unres_lock);
}

/* Fill oifs list. It is called under write locked mrt_lock. */

689
static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache,
690
				   unsigned char *ttls)
L
Linus Torvalds 已提交
691 692 693 694 695 696 697
{
	int vifi;

	cache->mfc_un.res.minvif = MAXVIFS;
	cache->mfc_un.res.maxvif = 0;
	memset(cache->mfc_un.res.ttls, 255, MAXVIFS);

698 699
	for (vifi = 0; vifi < mrt->maxvif; vifi++) {
		if (VIF_EXISTS(mrt, vifi) &&
700
		    ttls[vifi] && ttls[vifi] < 255) {
L
Linus Torvalds 已提交
701 702 703 704 705 706 707 708 709
			cache->mfc_un.res.ttls[vifi] = ttls[vifi];
			if (cache->mfc_un.res.minvif > vifi)
				cache->mfc_un.res.minvif = vifi;
			if (cache->mfc_un.res.maxvif <= vifi)
				cache->mfc_un.res.maxvif = vifi + 1;
		}
	}
}

710 711
static int vif_add(struct net *net, struct mr_table *mrt,
		   struct vifctl *vifc, int mrtsock)
L
Linus Torvalds 已提交
712 713
{
	int vifi = vifc->vifc_vifi;
714
	struct vif_device *v = &mrt->vif_table[vifi];
L
Linus Torvalds 已提交
715 716
	struct net_device *dev;
	struct in_device *in_dev;
717
	int err;
L
Linus Torvalds 已提交
718 719

	/* Is vif busy ? */
720
	if (VIF_EXISTS(mrt, vifi))
L
Linus Torvalds 已提交
721 722 723 724 725 726 727 728 729
		return -EADDRINUSE;

	switch (vifc->vifc_flags) {
#ifdef CONFIG_IP_PIMSM
	case VIFF_REGISTER:
		/*
		 * Special Purpose VIF in PIM
		 * All the packets will be sent to the daemon
		 */
730
		if (mrt->mroute_reg_vif_num >= 0)
L
Linus Torvalds 已提交
731
			return -EADDRINUSE;
732
		dev = ipmr_reg_vif(net, mrt);
L
Linus Torvalds 已提交
733 734
		if (!dev)
			return -ENOBUFS;
735 736 737
		err = dev_set_allmulti(dev, 1);
		if (err) {
			unregister_netdevice(dev);
738
			dev_put(dev);
739 740
			return err;
		}
L
Linus Torvalds 已提交
741 742
		break;
#endif
743
	case VIFF_TUNNEL:
744
		dev = ipmr_new_tunnel(net, vifc);
L
Linus Torvalds 已提交
745 746
		if (!dev)
			return -ENOBUFS;
747 748 749
		err = dev_set_allmulti(dev, 1);
		if (err) {
			ipmr_del_tunnel(dev, vifc);
750
			dev_put(dev);
751 752
			return err;
		}
L
Linus Torvalds 已提交
753
		break;
754 755

	case VIFF_USE_IFINDEX:
L
Linus Torvalds 已提交
756
	case 0:
757 758
		if (vifc->vifc_flags == VIFF_USE_IFINDEX) {
			dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex);
E
Eric Dumazet 已提交
759
			if (dev && __in_dev_get_rtnl(dev) == NULL) {
760 761 762
				dev_put(dev);
				return -EADDRNOTAVAIL;
			}
E
Eric Dumazet 已提交
763
		} else {
764
			dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr);
E
Eric Dumazet 已提交
765
		}
L
Linus Torvalds 已提交
766 767
		if (!dev)
			return -EADDRNOTAVAIL;
768
		err = dev_set_allmulti(dev, 1);
769 770
		if (err) {
			dev_put(dev);
771
			return err;
772
		}
L
Linus Torvalds 已提交
773 774 775 776 777
		break;
	default:
		return -EINVAL;
	}

E
Eric Dumazet 已提交
778 779
	in_dev = __in_dev_get_rtnl(dev);
	if (!in_dev) {
780
		dev_put(dev);
L
Linus Torvalds 已提交
781
		return -EADDRNOTAVAIL;
782
	}
783
	IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
784 785
	inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, dev->ifindex,
				    &in_dev->cnf);
L
Linus Torvalds 已提交
786 787
	ip_rt_multicast_event(in_dev);

E
Eric Dumazet 已提交
788 789
	/* Fill in the VIF structures */

J
Jianjun Kong 已提交
790 791 792 793
	v->rate_limit = vifc->vifc_rate_limit;
	v->local = vifc->vifc_lcl_addr.s_addr;
	v->remote = vifc->vifc_rmt_addr.s_addr;
	v->flags = vifc->vifc_flags;
L
Linus Torvalds 已提交
794 795
	if (!mrtsock)
		v->flags |= VIFF_STATIC;
J
Jianjun Kong 已提交
796
	v->threshold = vifc->vifc_threshold;
L
Linus Torvalds 已提交
797 798 799 800 801
	v->bytes_in = 0;
	v->bytes_out = 0;
	v->pkt_in = 0;
	v->pkt_out = 0;
	v->link = dev->ifindex;
E
Eric Dumazet 已提交
802
	if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER))
L
Linus Torvalds 已提交
803 804 805 806
		v->link = dev->iflink;

	/* And finish update writing critical data */
	write_lock_bh(&mrt_lock);
J
Jianjun Kong 已提交
807
	v->dev = dev;
L
Linus Torvalds 已提交
808
#ifdef CONFIG_IP_PIMSM
E
Eric Dumazet 已提交
809
	if (v->flags & VIFF_REGISTER)
810
		mrt->mroute_reg_vif_num = vifi;
L
Linus Torvalds 已提交
811
#endif
812 813
	if (vifi+1 > mrt->maxvif)
		mrt->maxvif = vifi+1;
L
Linus Torvalds 已提交
814 815 816 817
	write_unlock_bh(&mrt_lock);
	return 0;
}

818
/* called with rcu_read_lock() */
819
static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
820 821
					 __be32 origin,
					 __be32 mcastgrp)
L
Linus Torvalds 已提交
822
{
J
Jianjun Kong 已提交
823
	int line = MFC_HASH(mcastgrp, origin);
L
Linus Torvalds 已提交
824 825
	struct mfc_cache *c;

826
	list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list) {
827 828
		if (c->mfc_origin == origin && c->mfc_mcastgrp == mcastgrp)
			return c;
L
Linus Torvalds 已提交
829
	}
830
	return NULL;
L
Linus Torvalds 已提交
831 832
}

833 834 835 836
/* Look for a (*,*,oif) entry */
static struct mfc_cache *ipmr_cache_find_any_parent(struct mr_table *mrt,
						    int vifi)
{
837
	int line = MFC_HASH(htonl(INADDR_ANY), htonl(INADDR_ANY));
838 839 840
	struct mfc_cache *c;

	list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
841 842
		if (c->mfc_origin == htonl(INADDR_ANY) &&
		    c->mfc_mcastgrp == htonl(INADDR_ANY) &&
843 844 845 846 847 848 849 850 851 852
		    c->mfc_un.res.ttls[vifi] < 255)
			return c;

	return NULL;
}

/* Look for a (*,G) entry */
static struct mfc_cache *ipmr_cache_find_any(struct mr_table *mrt,
					     __be32 mcastgrp, int vifi)
{
853
	int line = MFC_HASH(mcastgrp, htonl(INADDR_ANY));
854 855
	struct mfc_cache *c, *proxy;

856
	if (mcastgrp == htonl(INADDR_ANY))
857 858 859
		goto skip;

	list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
860
		if (c->mfc_origin == htonl(INADDR_ANY) &&
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
		    c->mfc_mcastgrp == mcastgrp) {
			if (c->mfc_un.res.ttls[vifi] < 255)
				return c;

			/* It's ok if the vifi is part of the static tree */
			proxy = ipmr_cache_find_any_parent(mrt,
							   c->mfc_parent);
			if (proxy && proxy->mfc_un.res.ttls[vifi] < 255)
				return c;
		}

skip:
	return ipmr_cache_find_any_parent(mrt, vifi);
}

L
Linus Torvalds 已提交
876 877 878
/*
 *	Allocate a multicast cache entry
 */
879
static struct mfc_cache *ipmr_cache_alloc(void)
L
Linus Torvalds 已提交
880
{
J
Jianjun Kong 已提交
881
	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
882 883 884

	if (c)
		c->mfc_un.res.minvif = MAXVIFS;
L
Linus Torvalds 已提交
885 886 887
	return c;
}

888
static struct mfc_cache *ipmr_cache_alloc_unres(void)
L
Linus Torvalds 已提交
889
{
J
Jianjun Kong 已提交
890
	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
891 892 893 894 895

	if (c) {
		skb_queue_head_init(&c->mfc_un.unres.unresolved);
		c->mfc_un.unres.expires = jiffies + 10*HZ;
	}
L
Linus Torvalds 已提交
896 897 898 899 900 901
	return c;
}

/*
 *	A cache entry has gone into a resolved state from queued
 */
902

903 904
static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
			       struct mfc_cache *uc, struct mfc_cache *c)
L
Linus Torvalds 已提交
905 906
{
	struct sk_buff *skb;
907
	struct nlmsgerr *e;
L
Linus Torvalds 已提交
908

E
Eric Dumazet 已提交
909
	/* Play the pending entries through our router */
L
Linus Torvalds 已提交
910

J
Jianjun Kong 已提交
911
	while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
912
		if (ip_hdr(skb)->version == 0) {
L
Linus Torvalds 已提交
913 914
			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));

915
			if (__ipmr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) {
E
Eric Dumazet 已提交
916 917
				nlh->nlmsg_len = skb_tail_pointer(skb) -
						 (u8 *)nlh;
L
Linus Torvalds 已提交
918 919
			} else {
				nlh->nlmsg_type = NLMSG_ERROR;
920
				nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
L
Linus Torvalds 已提交
921
				skb_trim(skb, nlh->nlmsg_len);
922
				e = nlmsg_data(nlh);
923 924
				e->error = -EMSGSIZE;
				memset(&e->msg, 0, sizeof(e->msg));
L
Linus Torvalds 已提交
925
			}
926

927
			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
E
Eric Dumazet 已提交
928
		} else {
929
			ip_mr_forward(net, mrt, skb, c, 0);
E
Eric Dumazet 已提交
930
		}
L
Linus Torvalds 已提交
931 932 933 934 935 936 937 938 939
	}
}

/*
 *	Bounce a cache query up to mrouted. We could use netlink for this but mrouted
 *	expects the following bizarre scheme.
 *
 *	Called under mrt_lock.
 */
940

941
static int ipmr_cache_report(struct mr_table *mrt,
942
			     struct sk_buff *pkt, vifi_t vifi, int assert)
L
Linus Torvalds 已提交
943 944
{
	struct sk_buff *skb;
945
	const int ihl = ip_hdrlen(pkt);
L
Linus Torvalds 已提交
946 947
	struct igmphdr *igmp;
	struct igmpmsg *msg;
E
Eric Dumazet 已提交
948
	struct sock *mroute_sk;
L
Linus Torvalds 已提交
949 950 951 952 953 954 955 956 957
	int ret;

#ifdef CONFIG_IP_PIMSM
	if (assert == IGMPMSG_WHOLEPKT)
		skb = skb_realloc_headroom(pkt, sizeof(struct iphdr));
	else
#endif
		skb = alloc_skb(128, GFP_ATOMIC);

S
Stephen Hemminger 已提交
958
	if (!skb)
L
Linus Torvalds 已提交
959 960 961 962 963
		return -ENOBUFS;

#ifdef CONFIG_IP_PIMSM
	if (assert == IGMPMSG_WHOLEPKT) {
		/* Ugly, but we have no choice with this interface.
E
Eric Dumazet 已提交
964 965 966
		 * Duplicate old header, fix ihl, length etc.
		 * And all this only to mangle msg->im_msgtype and
		 * to set msg->im_mbz to "mbz" :-)
L
Linus Torvalds 已提交
967
		 */
968 969
		skb_push(skb, sizeof(struct iphdr));
		skb_reset_network_header(skb);
970
		skb_reset_transport_header(skb);
971
		msg = (struct igmpmsg *)skb_network_header(skb);
972
		memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr));
L
Linus Torvalds 已提交
973 974
		msg->im_msgtype = IGMPMSG_WHOLEPKT;
		msg->im_mbz = 0;
975
		msg->im_vif = mrt->mroute_reg_vif_num;
976 977 978
		ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
		ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
					     sizeof(struct iphdr));
979
	} else
L
Linus Torvalds 已提交
980
#endif
981 982
	{

E
Eric Dumazet 已提交
983
	/* Copy the IP header */
L
Linus Torvalds 已提交
984

985
	skb_set_network_header(skb, skb->len);
986
	skb_put(skb, ihl);
987
	skb_copy_to_linear_data(skb, pkt->data, ihl);
E
Eric Dumazet 已提交
988
	ip_hdr(skb)->protocol = 0;	/* Flag to the kernel this is a route add */
989
	msg = (struct igmpmsg *)skb_network_header(skb);
L
Linus Torvalds 已提交
990
	msg->im_vif = vifi;
E
Eric Dumazet 已提交
991
	skb_dst_set(skb, dst_clone(skb_dst(pkt)));
L
Linus Torvalds 已提交
992

E
Eric Dumazet 已提交
993
	/* Add our header */
L
Linus Torvalds 已提交
994

E
Eric Dumazet 已提交
995
	igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
L
Linus Torvalds 已提交
996 997
	igmp->type	=
	msg->im_msgtype = assert;
E
Eric Dumazet 已提交
998 999
	igmp->code	= 0;
	ip_hdr(skb)->tot_len = htons(skb->len);		/* Fix the length */
1000
	skb->transport_header = skb->network_header;
1001
	}
L
Linus Torvalds 已提交
1002

E
Eric Dumazet 已提交
1003 1004 1005 1006
	rcu_read_lock();
	mroute_sk = rcu_dereference(mrt->mroute_sk);
	if (mroute_sk == NULL) {
		rcu_read_unlock();
L
Linus Torvalds 已提交
1007 1008 1009 1010
		kfree_skb(skb);
		return -EINVAL;
	}

E
Eric Dumazet 已提交
1011 1012
	/* Deliver to mrouted */

E
Eric Dumazet 已提交
1013 1014
	ret = sock_queue_rcv_skb(mroute_sk, skb);
	rcu_read_unlock();
1015
	if (ret < 0) {
1016
		net_warn_ratelimited("mroute: pending queue full, dropping entries\n");
L
Linus Torvalds 已提交
1017 1018 1019 1020 1021 1022 1023 1024 1025
		kfree_skb(skb);
	}

	return ret;
}

/*
 *	Queue a packet for resolution. It gets locked cache entry!
 */
1026

L
Linus Torvalds 已提交
1027
static int
1028
ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
L
Linus Torvalds 已提交
1029
{
1030
	bool found = false;
L
Linus Torvalds 已提交
1031 1032
	int err;
	struct mfc_cache *c;
1033
	const struct iphdr *iph = ip_hdr(skb);
L
Linus Torvalds 已提交
1034 1035

	spin_lock_bh(&mfc_unres_lock);
1036
	list_for_each_entry(c, &mrt->mfc_unres_queue, list) {
1037
		if (c->mfc_mcastgrp == iph->daddr &&
1038 1039
		    c->mfc_origin == iph->saddr) {
			found = true;
L
Linus Torvalds 已提交
1040
			break;
1041
		}
L
Linus Torvalds 已提交
1042 1043
	}

1044
	if (!found) {
E
Eric Dumazet 已提交
1045
		/* Create a new entry if allowable */
L
Linus Torvalds 已提交
1046

1047
		if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
1048
		    (c = ipmr_cache_alloc_unres()) == NULL) {
L
Linus Torvalds 已提交
1049 1050 1051 1052 1053 1054
			spin_unlock_bh(&mfc_unres_lock);

			kfree_skb(skb);
			return -ENOBUFS;
		}

E
Eric Dumazet 已提交
1055 1056
		/* Fill in the new cache entry */

1057 1058 1059
		c->mfc_parent	= -1;
		c->mfc_origin	= iph->saddr;
		c->mfc_mcastgrp	= iph->daddr;
L
Linus Torvalds 已提交
1060

E
Eric Dumazet 已提交
1061 1062
		/* Reflect first query at mrouted. */

1063
		err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE);
1064
		if (err < 0) {
1065
			/* If the report failed throw the cache entry
L
Linus Torvalds 已提交
1066 1067 1068 1069
			   out - Brad Parker
			 */
			spin_unlock_bh(&mfc_unres_lock);

1070
			ipmr_cache_free(c);
L
Linus Torvalds 已提交
1071 1072 1073 1074
			kfree_skb(skb);
			return err;
		}

1075 1076
		atomic_inc(&mrt->cache_resolve_queue_len);
		list_add(&c->list, &mrt->mfc_unres_queue);
1077
		mroute_netlink_event(mrt, c, RTM_NEWROUTE);
L
Linus Torvalds 已提交
1078

1079 1080
		if (atomic_read(&mrt->cache_resolve_queue_len) == 1)
			mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
L
Linus Torvalds 已提交
1081 1082
	}

E
Eric Dumazet 已提交
1083 1084 1085
	/* See if we can append the packet */

	if (c->mfc_un.unres.unresolved.qlen > 3) {
L
Linus Torvalds 已提交
1086 1087 1088
		kfree_skb(skb);
		err = -ENOBUFS;
	} else {
J
Jianjun Kong 已提交
1089
		skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
L
Linus Torvalds 已提交
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
		err = 0;
	}

	spin_unlock_bh(&mfc_unres_lock);
	return err;
}

/*
 *	MFC cache manipulation by user space mroute daemon
 */

1101
static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent)
L
Linus Torvalds 已提交
1102 1103
{
	int line;
1104
	struct mfc_cache *c, *next;
L
Linus Torvalds 已提交
1105

J
Jianjun Kong 已提交
1106
	line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
L
Linus Torvalds 已提交
1107

1108
	list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) {
L
Linus Torvalds 已提交
1109
		if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1110 1111
		    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
		    (parent == -1 || parent == c->mfc_parent)) {
1112
			list_del_rcu(&c->list);
1113
			mroute_netlink_event(mrt, c, RTM_DELROUTE);
1114
			ipmr_cache_free(c);
L
Linus Torvalds 已提交
1115 1116 1117 1118 1119 1120
			return 0;
		}
	}
	return -ENOENT;
}

1121
static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1122
			struct mfcctl *mfc, int mrtsock, int parent)
L
Linus Torvalds 已提交
1123
{
1124
	bool found = false;
L
Linus Torvalds 已提交
1125
	int line;
1126
	struct mfc_cache *uc, *c;
L
Linus Torvalds 已提交
1127

1128 1129 1130
	if (mfc->mfcc_parent >= MAXVIFS)
		return -ENFILE;

J
Jianjun Kong 已提交
1131
	line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);
L
Linus Torvalds 已提交
1132

1133
	list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
L
Linus Torvalds 已提交
1134
		if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1135 1136
		    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
		    (parent == -1 || parent == c->mfc_parent)) {
1137
			found = true;
L
Linus Torvalds 已提交
1138
			break;
1139
		}
L
Linus Torvalds 已提交
1140 1141
	}

1142
	if (found) {
L
Linus Torvalds 已提交
1143 1144
		write_lock_bh(&mrt_lock);
		c->mfc_parent = mfc->mfcc_parent;
1145
		ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls);
L
Linus Torvalds 已提交
1146 1147 1148
		if (!mrtsock)
			c->mfc_flags |= MFC_STATIC;
		write_unlock_bh(&mrt_lock);
1149
		mroute_netlink_event(mrt, c, RTM_NEWROUTE);
L
Linus Torvalds 已提交
1150 1151 1152
		return 0;
	}

1153
	if (mfc->mfcc_mcastgrp.s_addr != htonl(INADDR_ANY) &&
1154
	    !ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
L
Linus Torvalds 已提交
1155 1156
		return -EINVAL;

1157
	c = ipmr_cache_alloc();
J
Jianjun Kong 已提交
1158
	if (c == NULL)
L
Linus Torvalds 已提交
1159 1160
		return -ENOMEM;

J
Jianjun Kong 已提交
1161 1162 1163
	c->mfc_origin = mfc->mfcc_origin.s_addr;
	c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr;
	c->mfc_parent = mfc->mfcc_parent;
1164
	ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls);
L
Linus Torvalds 已提交
1165 1166 1167
	if (!mrtsock)
		c->mfc_flags |= MFC_STATIC;

1168
	list_add_rcu(&c->list, &mrt->mfc_cache_array[line]);
L
Linus Torvalds 已提交
1169 1170 1171 1172 1173

	/*
	 *	Check to see if we resolved a queued list. If so we
	 *	need to send on the frames and tidy up.
	 */
1174
	found = false;
L
Linus Torvalds 已提交
1175
	spin_lock_bh(&mfc_unres_lock);
1176
	list_for_each_entry(uc, &mrt->mfc_unres_queue, list) {
1177
		if (uc->mfc_origin == c->mfc_origin &&
L
Linus Torvalds 已提交
1178
		    uc->mfc_mcastgrp == c->mfc_mcastgrp) {
1179
			list_del(&uc->list);
1180
			atomic_dec(&mrt->cache_resolve_queue_len);
1181
			found = true;
L
Linus Torvalds 已提交
1182 1183 1184
			break;
		}
	}
1185 1186
	if (list_empty(&mrt->mfc_unres_queue))
		del_timer(&mrt->ipmr_expire_timer);
L
Linus Torvalds 已提交
1187 1188
	spin_unlock_bh(&mfc_unres_lock);

1189
	if (found) {
1190
		ipmr_cache_resolve(net, mrt, uc, c);
1191
		ipmr_cache_free(uc);
L
Linus Torvalds 已提交
1192
	}
1193
	mroute_netlink_event(mrt, c, RTM_NEWROUTE);
L
Linus Torvalds 已提交
1194 1195 1196 1197 1198 1199
	return 0;
}

/*
 *	Close the multicast socket, and clear the vif tables etc
 */
1200

1201
static void mroute_clean_tables(struct mr_table *mrt)
L
Linus Torvalds 已提交
1202 1203
{
	int i;
1204
	LIST_HEAD(list);
1205
	struct mfc_cache *c, *next;
1206

E
Eric Dumazet 已提交
1207 1208
	/* Shut down all active vif entries */

1209
	for (i = 0; i < mrt->maxvif; i++) {
E
Eric Dumazet 已提交
1210
		if (!(mrt->vif_table[i].flags & VIFF_STATIC))
1211
			vif_delete(mrt, i, 0, &list);
L
Linus Torvalds 已提交
1212
	}
1213
	unregister_netdevice_many(&list);
L
Linus Torvalds 已提交
1214

E
Eric Dumazet 已提交
1215 1216
	/* Wipe the cache */

1217
	for (i = 0; i < MFC_LINES; i++) {
1218
		list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) {
1219
			if (c->mfc_flags & MFC_STATIC)
L
Linus Torvalds 已提交
1220
				continue;
1221
			list_del_rcu(&c->list);
1222
			mroute_netlink_event(mrt, c, RTM_DELROUTE);
1223
			ipmr_cache_free(c);
L
Linus Torvalds 已提交
1224 1225 1226
		}
	}

1227
	if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
L
Linus Torvalds 已提交
1228
		spin_lock_bh(&mfc_unres_lock);
1229
		list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
1230
			list_del(&c->list);
1231
			mroute_netlink_event(mrt, c, RTM_DELROUTE);
1232
			ipmr_destroy_unres(mrt, c);
L
Linus Torvalds 已提交
1233 1234 1235 1236 1237
		}
		spin_unlock_bh(&mfc_unres_lock);
	}
}

E
Eric Dumazet 已提交
1238 1239 1240
/* called from ip_ra_control(), before an RCU grace period,
 * we dont need to call synchronize_rcu() here
 */
L
Linus Torvalds 已提交
1241 1242
static void mrtsock_destruct(struct sock *sk)
{
1243
	struct net *net = sock_net(sk);
1244
	struct mr_table *mrt;
1245

L
Linus Torvalds 已提交
1246
	rtnl_lock();
1247
	ipmr_for_each_table(mrt, net) {
E
Eric Dumazet 已提交
1248
		if (sk == rtnl_dereference(mrt->mroute_sk)) {
1249
			IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
1250 1251 1252
			inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
						    NETCONFA_IFINDEX_ALL,
						    net->ipv4.devconf_all);
1253
			RCU_INIT_POINTER(mrt->mroute_sk, NULL);
1254 1255
			mroute_clean_tables(mrt);
		}
L
Linus Torvalds 已提交
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
	}
	rtnl_unlock();
}

/*
 *	Socket options and virtual interface manipulation. The whole
 *	virtual interface system is a complete heap, but unfortunately
 *	that's how BSD mrouted happens to think. Maybe one day with a proper
 *	MOSPF/PIM router set up we can clean this up.
 */
1266

1267
int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
L
Linus Torvalds 已提交
1268
{
1269
	int ret, parent = 0;
L
Linus Torvalds 已提交
1270 1271
	struct vifctl vif;
	struct mfcctl mfc;
1272
	struct net *net = sock_net(sk);
1273 1274
	struct mr_table *mrt;

1275 1276 1277 1278
	if (sk->sk_type != SOCK_RAW ||
	    inet_sk(sk)->inet_num != IPPROTO_IGMP)
		return -EOPNOTSUPP;

1279 1280 1281
	mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return -ENOENT;
1282

S
Stephen Hemminger 已提交
1283
	if (optname != MRT_INIT) {
1284
		if (sk != rcu_access_pointer(mrt->mroute_sk) &&
1285
		    !ns_capable(net->user_ns, CAP_NET_ADMIN))
L
Linus Torvalds 已提交
1286 1287 1288
			return -EACCES;
	}

S
Stephen Hemminger 已提交
1289 1290
	switch (optname) {
	case MRT_INIT:
J
Jianjun Kong 已提交
1291
		if (optlen != sizeof(int))
1292
			return -EINVAL;
L
Linus Torvalds 已提交
1293

S
Stephen Hemminger 已提交
1294
		rtnl_lock();
E
Eric Dumazet 已提交
1295
		if (rtnl_dereference(mrt->mroute_sk)) {
L
Linus Torvalds 已提交
1296
			rtnl_unlock();
S
Stephen Hemminger 已提交
1297 1298 1299 1300 1301
			return -EADDRINUSE;
		}

		ret = ip_ra_control(sk, 1, mrtsock_destruct);
		if (ret == 0) {
1302
			rcu_assign_pointer(mrt->mroute_sk, sk);
1303
			IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
1304 1305 1306
			inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
						    NETCONFA_IFINDEX_ALL,
						    net->ipv4.devconf_all);
S
Stephen Hemminger 已提交
1307 1308 1309 1310
		}
		rtnl_unlock();
		return ret;
	case MRT_DONE:
1311
		if (sk != rcu_access_pointer(mrt->mroute_sk))
S
Stephen Hemminger 已提交
1312 1313 1314 1315
			return -EACCES;
		return ip_ra_control(sk, 0, NULL);
	case MRT_ADD_VIF:
	case MRT_DEL_VIF:
J
Jianjun Kong 已提交
1316
		if (optlen != sizeof(vif))
S
Stephen Hemminger 已提交
1317
			return -EINVAL;
J
Jianjun Kong 已提交
1318
		if (copy_from_user(&vif, optval, sizeof(vif)))
S
Stephen Hemminger 已提交
1319 1320 1321 1322
			return -EFAULT;
		if (vif.vifc_vifi >= MAXVIFS)
			return -ENFILE;
		rtnl_lock();
J
Jianjun Kong 已提交
1323
		if (optname == MRT_ADD_VIF) {
E
Eric Dumazet 已提交
1324 1325
			ret = vif_add(net, mrt, &vif,
				      sk == rtnl_dereference(mrt->mroute_sk));
S
Stephen Hemminger 已提交
1326
		} else {
1327
			ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL);
S
Stephen Hemminger 已提交
1328 1329 1330
		}
		rtnl_unlock();
		return ret;
L
Linus Torvalds 已提交
1331 1332 1333 1334 1335

		/*
		 *	Manipulate the forwarding caches. These live
		 *	in a sort of kernel/user symbiosis.
		 */
S
Stephen Hemminger 已提交
1336 1337
	case MRT_ADD_MFC:
	case MRT_DEL_MFC:
1338 1339 1340
		parent = -1;
	case MRT_ADD_MFC_PROXY:
	case MRT_DEL_MFC_PROXY:
J
Jianjun Kong 已提交
1341
		if (optlen != sizeof(mfc))
S
Stephen Hemminger 已提交
1342
			return -EINVAL;
J
Jianjun Kong 已提交
1343
		if (copy_from_user(&mfc, optval, sizeof(mfc)))
S
Stephen Hemminger 已提交
1344
			return -EFAULT;
1345 1346
		if (parent == 0)
			parent = mfc.mfcc_parent;
S
Stephen Hemminger 已提交
1347
		rtnl_lock();
1348 1349
		if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY)
			ret = ipmr_mfc_delete(mrt, &mfc, parent);
S
Stephen Hemminger 已提交
1350
		else
E
Eric Dumazet 已提交
1351
			ret = ipmr_mfc_add(net, mrt, &mfc,
1352 1353
					   sk == rtnl_dereference(mrt->mroute_sk),
					   parent);
S
Stephen Hemminger 已提交
1354 1355
		rtnl_unlock();
		return ret;
L
Linus Torvalds 已提交
1356 1357 1358
		/*
		 *	Control PIM assert.
		 */
S
Stephen Hemminger 已提交
1359 1360 1361
	case MRT_ASSERT:
	{
		int v;
1362 1363
		if (optlen != sizeof(v))
			return -EINVAL;
E
Eric Dumazet 已提交
1364
		if (get_user(v, (int __user *)optval))
S
Stephen Hemminger 已提交
1365
			return -EFAULT;
1366
		mrt->mroute_do_assert = v;
S
Stephen Hemminger 已提交
1367 1368
		return 0;
	}
L
Linus Torvalds 已提交
1369
#ifdef CONFIG_IP_PIMSM
S
Stephen Hemminger 已提交
1370 1371
	case MRT_PIM:
	{
S
Stephen Hemminger 已提交
1372 1373
		int v;

1374 1375
		if (optlen != sizeof(v))
			return -EINVAL;
E
Eric Dumazet 已提交
1376
		if (get_user(v, (int __user *)optval))
S
Stephen Hemminger 已提交
1377
			return -EFAULT;
1378
		v = !!v;
S
Stephen Hemminger 已提交
1379

S
Stephen Hemminger 已提交
1380 1381
		rtnl_lock();
		ret = 0;
1382 1383 1384
		if (v != mrt->mroute_do_pim) {
			mrt->mroute_do_pim = v;
			mrt->mroute_do_assert = v;
L
Linus Torvalds 已提交
1385
		}
S
Stephen Hemminger 已提交
1386 1387 1388
		rtnl_unlock();
		return ret;
	}
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
#endif
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
	case MRT_TABLE:
	{
		u32 v;

		if (optlen != sizeof(u32))
			return -EINVAL;
		if (get_user(v, (u32 __user *)optval))
			return -EFAULT;

1400 1401 1402 1403
		/* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
		if (v != RT_TABLE_DEFAULT && v >= 1000000000)
			return -EINVAL;

1404 1405
		rtnl_lock();
		ret = 0;
E
Eric Dumazet 已提交
1406 1407 1408 1409 1410
		if (sk == rtnl_dereference(mrt->mroute_sk)) {
			ret = -EBUSY;
		} else {
			if (!ipmr_new_table(net, v))
				ret = -ENOMEM;
1411 1412
			else
				raw_sk(sk)->ipmr_table = v;
E
Eric Dumazet 已提交
1413
		}
1414 1415 1416
		rtnl_unlock();
		return ret;
	}
L
Linus Torvalds 已提交
1417
#endif
S
Stephen Hemminger 已提交
1418 1419 1420 1421 1422 1423
	/*
	 *	Spurious command, or MRT_VERSION which you cannot
	 *	set.
	 */
	default:
		return -ENOPROTOOPT;
L
Linus Torvalds 已提交
1424 1425 1426 1427 1428 1429
	}
}

/*
 *	Getsock opt support for the multicast routing system.
 */
1430

J
Jianjun Kong 已提交
1431
int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen)
L
Linus Torvalds 已提交
1432 1433 1434
{
	int olr;
	int val;
1435
	struct net *net = sock_net(sk);
1436 1437
	struct mr_table *mrt;

1438 1439 1440 1441
	if (sk->sk_type != SOCK_RAW ||
	    inet_sk(sk)->inet_num != IPPROTO_IGMP)
		return -EOPNOTSUPP;

1442 1443 1444
	mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return -ENOENT;
L
Linus Torvalds 已提交
1445

J
Jianjun Kong 已提交
1446
	if (optname != MRT_VERSION &&
L
Linus Torvalds 已提交
1447
#ifdef CONFIG_IP_PIMSM
E
Eric Dumazet 已提交
1448
	   optname != MRT_PIM &&
L
Linus Torvalds 已提交
1449
#endif
E
Eric Dumazet 已提交
1450
	   optname != MRT_ASSERT)
L
Linus Torvalds 已提交
1451 1452 1453 1454 1455 1456 1457 1458
		return -ENOPROTOOPT;

	if (get_user(olr, optlen))
		return -EFAULT;

	olr = min_t(unsigned int, olr, sizeof(int));
	if (olr < 0)
		return -EINVAL;
1459

J
Jianjun Kong 已提交
1460
	if (put_user(olr, optlen))
L
Linus Torvalds 已提交
1461
		return -EFAULT;
J
Jianjun Kong 已提交
1462 1463
	if (optname == MRT_VERSION)
		val = 0x0305;
L
Linus Torvalds 已提交
1464
#ifdef CONFIG_IP_PIMSM
J
Jianjun Kong 已提交
1465
	else if (optname == MRT_PIM)
1466
		val = mrt->mroute_do_pim;
L
Linus Torvalds 已提交
1467 1468
#endif
	else
1469
		val = mrt->mroute_do_assert;
J
Jianjun Kong 已提交
1470
	if (copy_to_user(optval, &val, olr))
L
Linus Torvalds 已提交
1471 1472 1473 1474 1475 1476 1477
		return -EFAULT;
	return 0;
}

/*
 *	The IP multicast ioctl support routines.
 */
1478

L
Linus Torvalds 已提交
1479 1480 1481 1482 1483 1484
int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
{
	struct sioc_sg_req sr;
	struct sioc_vif_req vr;
	struct vif_device *vif;
	struct mfc_cache *c;
1485
	struct net *net = sock_net(sk);
1486 1487 1488 1489 1490
	struct mr_table *mrt;

	mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return -ENOENT;
1491

S
Stephen Hemminger 已提交
1492 1493
	switch (cmd) {
	case SIOCGETVIFCNT:
J
Jianjun Kong 已提交
1494
		if (copy_from_user(&vr, arg, sizeof(vr)))
S
Stephen Hemminger 已提交
1495
			return -EFAULT;
1496
		if (vr.vifi >= mrt->maxvif)
S
Stephen Hemminger 已提交
1497 1498
			return -EINVAL;
		read_lock(&mrt_lock);
1499 1500
		vif = &mrt->vif_table[vr.vifi];
		if (VIF_EXISTS(mrt, vr.vifi)) {
J
Jianjun Kong 已提交
1501 1502 1503 1504
			vr.icount = vif->pkt_in;
			vr.ocount = vif->pkt_out;
			vr.ibytes = vif->bytes_in;
			vr.obytes = vif->bytes_out;
L
Linus Torvalds 已提交
1505 1506
			read_unlock(&mrt_lock);

J
Jianjun Kong 已提交
1507
			if (copy_to_user(arg, &vr, sizeof(vr)))
S
Stephen Hemminger 已提交
1508 1509 1510 1511 1512 1513
				return -EFAULT;
			return 0;
		}
		read_unlock(&mrt_lock);
		return -EADDRNOTAVAIL;
	case SIOCGETSGCNT:
J
Jianjun Kong 已提交
1514
		if (copy_from_user(&sr, arg, sizeof(sr)))
S
Stephen Hemminger 已提交
1515 1516
			return -EFAULT;

1517
		rcu_read_lock();
1518
		c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
S
Stephen Hemminger 已提交
1519 1520 1521 1522
		if (c) {
			sr.pktcnt = c->mfc_un.res.pkt;
			sr.bytecnt = c->mfc_un.res.bytes;
			sr.wrong_if = c->mfc_un.res.wrong_if;
1523
			rcu_read_unlock();
S
Stephen Hemminger 已提交
1524

J
Jianjun Kong 已提交
1525
			if (copy_to_user(arg, &sr, sizeof(sr)))
S
Stephen Hemminger 已提交
1526 1527 1528
				return -EFAULT;
			return 0;
		}
1529
		rcu_read_unlock();
S
Stephen Hemminger 已提交
1530 1531 1532
		return -EADDRNOTAVAIL;
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
1533 1534 1535
	}
}

1536 1537 1538 1539 1540 1541 1542 1543 1544
#ifdef CONFIG_COMPAT
struct compat_sioc_sg_req {
	struct in_addr src;
	struct in_addr grp;
	compat_ulong_t pktcnt;
	compat_ulong_t bytecnt;
	compat_ulong_t wrong_if;
};

1545 1546 1547 1548 1549 1550 1551 1552
struct compat_sioc_vif_req {
	vifi_t	vifi;		/* Which iface */
	compat_ulong_t icount;
	compat_ulong_t ocount;
	compat_ulong_t ibytes;
	compat_ulong_t obytes;
};

1553 1554
int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
{
1555
	struct compat_sioc_sg_req sr;
1556 1557
	struct compat_sioc_vif_req vr;
	struct vif_device *vif;
1558 1559 1560 1561 1562 1563 1564 1565 1566
	struct mfc_cache *c;
	struct net *net = sock_net(sk);
	struct mr_table *mrt;

	mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return -ENOENT;

	switch (cmd) {
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
	case SIOCGETVIFCNT:
		if (copy_from_user(&vr, arg, sizeof(vr)))
			return -EFAULT;
		if (vr.vifi >= mrt->maxvif)
			return -EINVAL;
		read_lock(&mrt_lock);
		vif = &mrt->vif_table[vr.vifi];
		if (VIF_EXISTS(mrt, vr.vifi)) {
			vr.icount = vif->pkt_in;
			vr.ocount = vif->pkt_out;
			vr.ibytes = vif->bytes_in;
			vr.obytes = vif->bytes_out;
			read_unlock(&mrt_lock);

			if (copy_to_user(arg, &vr, sizeof(vr)))
				return -EFAULT;
			return 0;
		}
		read_unlock(&mrt_lock);
		return -EADDRNOTAVAIL;
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
	case SIOCGETSGCNT:
		if (copy_from_user(&sr, arg, sizeof(sr)))
			return -EFAULT;

		rcu_read_lock();
		c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
		if (c) {
			sr.pktcnt = c->mfc_un.res.pkt;
			sr.bytecnt = c->mfc_un.res.bytes;
			sr.wrong_if = c->mfc_un.res.wrong_if;
			rcu_read_unlock();

			if (copy_to_user(arg, &sr, sizeof(sr)))
				return -EFAULT;
			return 0;
		}
		rcu_read_unlock();
		return -EADDRNOTAVAIL;
	default:
		return -ENOIOCTLCMD;
	}
}
#endif

L
Linus Torvalds 已提交
1611 1612 1613

static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
{
1614
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1615
	struct net *net = dev_net(dev);
1616
	struct mr_table *mrt;
L
Linus Torvalds 已提交
1617 1618
	struct vif_device *v;
	int ct;
1619

L
Linus Torvalds 已提交
1620 1621
	if (event != NETDEV_UNREGISTER)
		return NOTIFY_DONE;
1622 1623 1624 1625 1626

	ipmr_for_each_table(mrt, net) {
		v = &mrt->vif_table[0];
		for (ct = 0; ct < mrt->maxvif; ct++, v++) {
			if (v->dev == dev)
1627
				vif_delete(mrt, ct, 1, NULL);
1628
		}
L
Linus Torvalds 已提交
1629 1630 1631 1632 1633
	}
	return NOTIFY_DONE;
}


J
Jianjun Kong 已提交
1634
static struct notifier_block ip_mr_notifier = {
L
Linus Torvalds 已提交
1635 1636 1637 1638
	.notifier_call = ipmr_device_event,
};

/*
E
Eric Dumazet 已提交
1639
 *	Encapsulate a packet by attaching a valid IPIP header to it.
L
Linus Torvalds 已提交
1640 1641 1642
 *	This avoids tunnel drivers and other mess and gives us the speed so
 *	important for multicast video.
 */
1643

A
Al Viro 已提交
1644
static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
L
Linus Torvalds 已提交
1645
{
1646
	struct iphdr *iph;
1647
	const struct iphdr *old_iph = ip_hdr(skb);
1648 1649

	skb_push(skb, sizeof(struct iphdr));
1650
	skb->transport_header = skb->network_header;
1651
	skb_reset_network_header(skb);
1652
	iph = ip_hdr(skb);
L
Linus Torvalds 已提交
1653

E
Eric Dumazet 已提交
1654
	iph->version	=	4;
1655 1656
	iph->tos	=	old_iph->tos;
	iph->ttl	=	old_iph->ttl;
L
Linus Torvalds 已提交
1657 1658 1659 1660 1661 1662
	iph->frag_off	=	0;
	iph->daddr	=	daddr;
	iph->saddr	=	saddr;
	iph->protocol	=	IPPROTO_IPIP;
	iph->ihl	=	5;
	iph->tot_len	=	htons(skb->len);
1663
	ip_select_ident(skb, skb_dst(skb), NULL);
L
Linus Torvalds 已提交
1664 1665 1666 1667 1668 1669 1670 1671
	ip_send_check(iph);

	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
	nf_reset(skb);
}

static inline int ipmr_forward_finish(struct sk_buff *skb)
{
E
Eric Dumazet 已提交
1672
	struct ip_options *opt = &(IPCB(skb)->opt);
L
Linus Torvalds 已提交
1673

E
Eric Dumazet 已提交
1674
	IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
1675
	IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len);
L
Linus Torvalds 已提交
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686

	if (unlikely(opt->optlen))
		ip_forward_options(skb);

	return dst_output(skb);
}

/*
 *	Processing handlers for ipmr_forward
 */

1687 1688
static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
			    struct sk_buff *skb, struct mfc_cache *c, int vifi)
L
Linus Torvalds 已提交
1689
{
1690
	const struct iphdr *iph = ip_hdr(skb);
1691
	struct vif_device *vif = &mrt->vif_table[vifi];
L
Linus Torvalds 已提交
1692 1693
	struct net_device *dev;
	struct rtable *rt;
1694
	struct flowi4 fl4;
L
Linus Torvalds 已提交
1695 1696 1697 1698 1699 1700 1701 1702
	int    encap = 0;

	if (vif->dev == NULL)
		goto out_free;

#ifdef CONFIG_IP_PIMSM
	if (vif->flags & VIFF_REGISTER) {
		vif->pkt_out++;
J
Jianjun Kong 已提交
1703
		vif->bytes_out += skb->len;
1704 1705
		vif->dev->stats.tx_bytes += skb->len;
		vif->dev->stats.tx_packets++;
1706
		ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT);
1707
		goto out_free;
L
Linus Torvalds 已提交
1708 1709 1710
	}
#endif

E
Eric Dumazet 已提交
1711
	if (vif->flags & VIFF_TUNNEL) {
1712
		rt = ip_route_output_ports(net, &fl4, NULL,
1713 1714 1715 1716
					   vif->remote, vif->local,
					   0, 0,
					   IPPROTO_IPIP,
					   RT_TOS(iph->tos), vif->link);
1717
		if (IS_ERR(rt))
L
Linus Torvalds 已提交
1718 1719 1720
			goto out_free;
		encap = sizeof(struct iphdr);
	} else {
1721
		rt = ip_route_output_ports(net, &fl4, NULL, iph->daddr, 0,
1722 1723 1724
					   0, 0,
					   IPPROTO_IPIP,
					   RT_TOS(iph->tos), vif->link);
1725
		if (IS_ERR(rt))
L
Linus Torvalds 已提交
1726 1727 1728
			goto out_free;
	}

1729
	dev = rt->dst.dev;
L
Linus Torvalds 已提交
1730

1731
	if (skb->len+encap > dst_mtu(&rt->dst) && (ntohs(iph->frag_off) & IP_DF)) {
L
Linus Torvalds 已提交
1732
		/* Do not fragment multicasts. Alas, IPv4 does not
E
Eric Dumazet 已提交
1733 1734
		 * allow to send ICMP, so that packets will disappear
		 * to blackhole.
L
Linus Torvalds 已提交
1735 1736
		 */

1737
		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
L
Linus Torvalds 已提交
1738 1739 1740 1741
		ip_rt_put(rt);
		goto out_free;
	}

1742
	encap += LL_RESERVED_SPACE(dev) + rt->dst.header_len;
L
Linus Torvalds 已提交
1743 1744

	if (skb_cow(skb, encap)) {
1745
		ip_rt_put(rt);
L
Linus Torvalds 已提交
1746 1747 1748 1749
		goto out_free;
	}

	vif->pkt_out++;
J
Jianjun Kong 已提交
1750
	vif->bytes_out += skb->len;
L
Linus Torvalds 已提交
1751

E
Eric Dumazet 已提交
1752
	skb_dst_drop(skb);
1753
	skb_dst_set(skb, &rt->dst);
1754
	ip_decrease_ttl(ip_hdr(skb));
L
Linus Torvalds 已提交
1755 1756

	/* FIXME: forward and output firewalls used to be called here.
E
Eric Dumazet 已提交
1757 1758
	 * What do we do with netfilter? -- RR
	 */
L
Linus Torvalds 已提交
1759 1760 1761
	if (vif->flags & VIFF_TUNNEL) {
		ip_encap(skb, vif->local, vif->remote);
		/* FIXME: extra output firewall step used to be here. --RR */
1762 1763
		vif->dev->stats.tx_packets++;
		vif->dev->stats.tx_bytes += skb->len;
L
Linus Torvalds 已提交
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
	}

	IPCB(skb)->flags |= IPSKB_FORWARDED;

	/*
	 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
	 * not only before forwarding, but after forwarding on all output
	 * interfaces. It is clear, if mrouter runs a multicasting
	 * program, it should receive packets not depending to what interface
	 * program is joined.
	 * If we will not make it, the program will have to join on all
	 * interfaces. On the other hand, multihoming host (or router, but
	 * not mrouter) cannot join to more than one interface - it will
	 * result in receiving multiple packets.
	 */
1779
	NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, dev,
L
Linus Torvalds 已提交
1780 1781 1782 1783 1784 1785 1786
		ipmr_forward_finish);
	return;

out_free:
	kfree_skb(skb);
}

1787
static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev)
L
Linus Torvalds 已提交
1788 1789
{
	int ct;
1790 1791 1792

	for (ct = mrt->maxvif-1; ct >= 0; ct--) {
		if (mrt->vif_table[ct].dev == dev)
L
Linus Torvalds 已提交
1793 1794 1795 1796 1797 1798 1799
			break;
	}
	return ct;
}

/* "local" means that we should preserve one skb (for local delivery) */

1800 1801 1802
static void ip_mr_forward(struct net *net, struct mr_table *mrt,
			  struct sk_buff *skb, struct mfc_cache *cache,
			  int local)
L
Linus Torvalds 已提交
1803 1804 1805
{
	int psend = -1;
	int vif, ct;
1806
	int true_vifi = ipmr_find_vif(mrt, skb->dev);
L
Linus Torvalds 已提交
1807 1808 1809 1810 1811

	vif = cache->mfc_parent;
	cache->mfc_un.res.pkt++;
	cache->mfc_un.res.bytes += skb->len;

1812
	if (cache->mfc_origin == htonl(INADDR_ANY) && true_vifi >= 0) {
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
		struct mfc_cache *cache_proxy;

		/* For an (*,G) entry, we only check that the incomming
		 * interface is part of the static tree.
		 */
		cache_proxy = ipmr_cache_find_any_parent(mrt, vif);
		if (cache_proxy &&
		    cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
			goto forward;
	}

L
Linus Torvalds 已提交
1824 1825 1826
	/*
	 * Wrong interface: drop packet and (maybe) send PIM assert.
	 */
1827
	if (mrt->vif_table[vif].dev != skb->dev) {
1828
		if (rt_is_output_route(skb_rtable(skb))) {
L
Linus Torvalds 已提交
1829
			/* It is our own packet, looped back.
E
Eric Dumazet 已提交
1830 1831 1832 1833 1834 1835 1836 1837 1838
			 * Very complicated situation...
			 *
			 * The best workaround until routing daemons will be
			 * fixed is not to redistribute packet, if it was
			 * send through wrong interface. It means, that
			 * multicast applications WILL NOT work for
			 * (S,G), which have default multicast route pointing
			 * to wrong oif. In any case, it is not a good
			 * idea to use multicasting applications on router.
L
Linus Torvalds 已提交
1839 1840 1841 1842 1843 1844
			 */
			goto dont_forward;
		}

		cache->mfc_un.res.wrong_if++;

1845
		if (true_vifi >= 0 && mrt->mroute_do_assert &&
L
Linus Torvalds 已提交
1846
		    /* pimsm uses asserts, when switching from RPT to SPT,
E
Eric Dumazet 已提交
1847 1848 1849
		     * so that we cannot check that packet arrived on an oif.
		     * It is bad, but otherwise we would need to move pretty
		     * large chunk of pimd to kernel. Ough... --ANK
L
Linus Torvalds 已提交
1850
		     */
1851
		    (mrt->mroute_do_pim ||
1852
		     cache->mfc_un.res.ttls[true_vifi] < 255) &&
1853
		    time_after(jiffies,
L
Linus Torvalds 已提交
1854 1855
			       cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
			cache->mfc_un.res.last_assert = jiffies;
1856
			ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF);
L
Linus Torvalds 已提交
1857 1858 1859 1860
		}
		goto dont_forward;
	}

1861
forward:
1862 1863
	mrt->vif_table[vif].pkt_in++;
	mrt->vif_table[vif].bytes_in += skb->len;
L
Linus Torvalds 已提交
1864 1865 1866 1867

	/*
	 *	Forward the frame
	 */
1868 1869
	if (cache->mfc_origin == htonl(INADDR_ANY) &&
	    cache->mfc_mcastgrp == htonl(INADDR_ANY)) {
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882
		if (true_vifi >= 0 &&
		    true_vifi != cache->mfc_parent &&
		    ip_hdr(skb)->ttl >
				cache->mfc_un.res.ttls[cache->mfc_parent]) {
			/* It's an (*,*) entry and the packet is not coming from
			 * the upstream: forward the packet to the upstream
			 * only.
			 */
			psend = cache->mfc_parent;
			goto last_forward;
		}
		goto dont_forward;
	}
E
Eric Dumazet 已提交
1883 1884
	for (ct = cache->mfc_un.res.maxvif - 1;
	     ct >= cache->mfc_un.res.minvif; ct--) {
1885
		/* For (*,G) entry, don't forward to the incoming interface */
1886 1887
		if ((cache->mfc_origin != htonl(INADDR_ANY) ||
		     ct != true_vifi) &&
1888
		    ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
L
Linus Torvalds 已提交
1889 1890
			if (psend != -1) {
				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
E
Eric Dumazet 已提交
1891

L
Linus Torvalds 已提交
1892
				if (skb2)
1893 1894
					ipmr_queue_xmit(net, mrt, skb2, cache,
							psend);
L
Linus Torvalds 已提交
1895
			}
J
Jianjun Kong 已提交
1896
			psend = ct;
L
Linus Torvalds 已提交
1897 1898
		}
	}
1899
last_forward:
L
Linus Torvalds 已提交
1900 1901 1902
	if (psend != -1) {
		if (local) {
			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
E
Eric Dumazet 已提交
1903

L
Linus Torvalds 已提交
1904
			if (skb2)
1905
				ipmr_queue_xmit(net, mrt, skb2, cache, psend);
L
Linus Torvalds 已提交
1906
		} else {
1907
			ipmr_queue_xmit(net, mrt, skb, cache, psend);
1908
			return;
L
Linus Torvalds 已提交
1909 1910 1911 1912 1913 1914 1915 1916
		}
	}

dont_forward:
	if (!local)
		kfree_skb(skb);
}

1917
static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb)
1918
{
1919 1920
	struct rtable *rt = skb_rtable(skb);
	struct iphdr *iph = ip_hdr(skb);
D
David S. Miller 已提交
1921
	struct flowi4 fl4 = {
1922 1923
		.daddr = iph->daddr,
		.saddr = iph->saddr,
1924
		.flowi4_tos = RT_TOS(iph->tos),
D
David S. Miller 已提交
1925 1926 1927
		.flowi4_oif = (rt_is_output_route(rt) ?
			       skb->dev->ifindex : 0),
		.flowi4_iif = (rt_is_output_route(rt) ?
1928
			       LOOPBACK_IFINDEX :
D
David S. Miller 已提交
1929
			       skb->dev->ifindex),
1930
		.flowi4_mark = skb->mark,
1931 1932 1933 1934
	};
	struct mr_table *mrt;
	int err;

D
David S. Miller 已提交
1935
	err = ipmr_fib_lookup(net, &fl4, &mrt);
1936 1937 1938 1939
	if (err)
		return ERR_PTR(err);
	return mrt;
}
L
Linus Torvalds 已提交
1940 1941 1942

/*
 *	Multicast packets for forwarding arrive here
E
Eric Dumazet 已提交
1943
 *	Called with rcu_read_lock();
L
Linus Torvalds 已提交
1944 1945 1946 1947 1948
 */

int ip_mr_input(struct sk_buff *skb)
{
	struct mfc_cache *cache;
1949
	struct net *net = dev_net(skb->dev);
E
Eric Dumazet 已提交
1950
	int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
1951
	struct mr_table *mrt;
L
Linus Torvalds 已提交
1952 1953

	/* Packet is looped back after forward, it should not be
E
Eric Dumazet 已提交
1954
	 * forwarded second time, but still can be delivered locally.
L
Linus Torvalds 已提交
1955
	 */
E
Eric Dumazet 已提交
1956
	if (IPCB(skb)->flags & IPSKB_FORWARDED)
L
Linus Torvalds 已提交
1957 1958
		goto dont_forward;

1959
	mrt = ipmr_rt_fib_lookup(net, skb);
1960 1961 1962
	if (IS_ERR(mrt)) {
		kfree_skb(skb);
		return PTR_ERR(mrt);
1963
	}
L
Linus Torvalds 已提交
1964
	if (!local) {
E
Eric Dumazet 已提交
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
		if (IPCB(skb)->opt.router_alert) {
			if (ip_call_ra_chain(skb))
				return 0;
		} else if (ip_hdr(skb)->protocol == IPPROTO_IGMP) {
			/* IGMPv1 (and broken IGMPv2 implementations sort of
			 * Cisco IOS <= 11.2(8)) do not put router alert
			 * option to IGMP packets destined to routable
			 * groups. It is very bad, because it means
			 * that we can forward NO IGMP messages.
			 */
			struct sock *mroute_sk;

			mroute_sk = rcu_dereference(mrt->mroute_sk);
			if (mroute_sk) {
				nf_reset(skb);
				raw_rcv(mroute_sk, skb);
				return 0;
			}
L
Linus Torvalds 已提交
1983 1984 1985
		    }
	}

1986
	/* already under rcu_read_lock() */
1987
	cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
1988 1989 1990 1991 1992 1993 1994
	if (cache == NULL) {
		int vif = ipmr_find_vif(mrt, skb->dev);

		if (vif >= 0)
			cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
						    vif);
	}
L
Linus Torvalds 已提交
1995 1996 1997 1998

	/*
	 *	No usable cache entry
	 */
J
Jianjun Kong 已提交
1999
	if (cache == NULL) {
L
Linus Torvalds 已提交
2000 2001 2002 2003 2004
		int vif;

		if (local) {
			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
			ip_local_deliver(skb);
2005
			if (skb2 == NULL)
L
Linus Torvalds 已提交
2006 2007 2008 2009
				return -ENOBUFS;
			skb = skb2;
		}

2010
		read_lock(&mrt_lock);
2011
		vif = ipmr_find_vif(mrt, skb->dev);
L
Linus Torvalds 已提交
2012
		if (vif >= 0) {
2013
			int err2 = ipmr_cache_unresolved(mrt, vif, skb);
L
Linus Torvalds 已提交
2014 2015
			read_unlock(&mrt_lock);

2016
			return err2;
L
Linus Torvalds 已提交
2017 2018 2019 2020 2021 2022
		}
		read_unlock(&mrt_lock);
		kfree_skb(skb);
		return -ENODEV;
	}

2023
	read_lock(&mrt_lock);
2024
	ip_mr_forward(net, mrt, skb, cache, local);
L
Linus Torvalds 已提交
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
	read_unlock(&mrt_lock);

	if (local)
		return ip_local_deliver(skb);

	return 0;

dont_forward:
	if (local)
		return ip_local_deliver(skb);
	kfree_skb(skb);
	return 0;
}

I
Ilpo Järvinen 已提交
2039
#ifdef CONFIG_IP_PIMSM
2040
/* called with rcu_read_lock() */
2041 2042
static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
		     unsigned int pimlen)
L
Linus Torvalds 已提交
2043
{
I
Ilpo Järvinen 已提交
2044 2045
	struct net_device *reg_dev = NULL;
	struct iphdr *encap;
L
Linus Torvalds 已提交
2046

I
Ilpo Järvinen 已提交
2047
	encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
L
Linus Torvalds 已提交
2048
	/*
E
Eric Dumazet 已提交
2049 2050 2051 2052
	 * Check that:
	 * a. packet is really sent to a multicast group
	 * b. packet is not a NULL-REGISTER
	 * c. packet is not truncated
L
Linus Torvalds 已提交
2053
	 */
2054
	if (!ipv4_is_multicast(encap->daddr) ||
L
Linus Torvalds 已提交
2055
	    encap->tot_len == 0 ||
I
Ilpo Järvinen 已提交
2056 2057
	    ntohs(encap->tot_len) + pimlen > skb->len)
		return 1;
L
Linus Torvalds 已提交
2058 2059

	read_lock(&mrt_lock);
2060 2061
	if (mrt->mroute_reg_vif_num >= 0)
		reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev;
L
Linus Torvalds 已提交
2062 2063
	read_unlock(&mrt_lock);

2064
	if (reg_dev == NULL)
I
Ilpo Järvinen 已提交
2065
		return 1;
L
Linus Torvalds 已提交
2066

2067
	skb->mac_header = skb->network_header;
2068
	skb_pull(skb, (u8 *)encap - skb->data);
2069
	skb_reset_network_header(skb);
L
Linus Torvalds 已提交
2070
	skb->protocol = htons(ETH_P_IP);
2071
	skb->ip_summed = CHECKSUM_NONE;
2072

2073
	skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
2074

L
Linus Torvalds 已提交
2075
	netif_rx(skb);
I
Ilpo Järvinen 已提交
2076

2077
	return NET_RX_SUCCESS;
I
Ilpo Järvinen 已提交
2078 2079 2080 2081 2082 2083 2084 2085
}
#endif

#ifdef CONFIG_IP_PIMSM_V1
/*
 * Handle IGMP messages of PIMv1
 */

E
Eric Dumazet 已提交
2086
int pim_rcv_v1(struct sk_buff *skb)
I
Ilpo Järvinen 已提交
2087 2088
{
	struct igmphdr *pim;
2089
	struct net *net = dev_net(skb->dev);
2090
	struct mr_table *mrt;
I
Ilpo Järvinen 已提交
2091 2092 2093 2094 2095 2096

	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
		goto drop;

	pim = igmp_hdr(skb);

2097
	mrt = ipmr_rt_fib_lookup(net, skb);
2098 2099
	if (IS_ERR(mrt))
		goto drop;
2100
	if (!mrt->mroute_do_pim ||
I
Ilpo Järvinen 已提交
2101 2102 2103
	    pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
		goto drop;

2104
	if (__pim_rcv(mrt, skb, sizeof(*pim))) {
I
Ilpo Järvinen 已提交
2105 2106 2107
drop:
		kfree_skb(skb);
	}
L
Linus Torvalds 已提交
2108 2109 2110 2111 2112
	return 0;
}
#endif

#ifdef CONFIG_IP_PIMSM_V2
E
Eric Dumazet 已提交
2113
static int pim_rcv(struct sk_buff *skb)
L
Linus Torvalds 已提交
2114 2115
{
	struct pimreghdr *pim;
2116 2117
	struct net *net = dev_net(skb->dev);
	struct mr_table *mrt;
L
Linus Torvalds 已提交
2118

I
Ilpo Järvinen 已提交
2119
	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr)))
L
Linus Torvalds 已提交
2120 2121
		goto drop;

2122
	pim = (struct pimreghdr *)skb_transport_header(skb);
E
Eric Dumazet 已提交
2123 2124
	if (pim->type != ((PIM_VERSION << 4) | (PIM_REGISTER)) ||
	    (pim->flags & PIM_NULL_REGISTER) ||
2125
	    (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
2126
	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
L
Linus Torvalds 已提交
2127 2128
		goto drop;

2129
	mrt = ipmr_rt_fib_lookup(net, skb);
2130 2131
	if (IS_ERR(mrt))
		goto drop;
2132
	if (__pim_rcv(mrt, skb, sizeof(*pim))) {
I
Ilpo Järvinen 已提交
2133 2134 2135
drop:
		kfree_skb(skb);
	}
L
Linus Torvalds 已提交
2136 2137 2138 2139
	return 0;
}
#endif

2140 2141
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
			      struct mfc_cache *c, struct rtmsg *rtm)
L
Linus Torvalds 已提交
2142 2143 2144
{
	int ct;
	struct rtnexthop *nhp;
T
Thomas Graf 已提交
2145
	struct nlattr *mp_attr;
2146
	struct rta_mfc_stats mfcs;
L
Linus Torvalds 已提交
2147

2148
	/* If cache is unresolved, don't try to parse IIF and OIF */
2149
	if (c->mfc_parent >= MAXVIFS)
2150 2151
		return -ENOENT;

T
Thomas Graf 已提交
2152 2153 2154
	if (VIF_EXISTS(mrt, c->mfc_parent) &&
	    nla_put_u32(skb, RTA_IIF, mrt->vif_table[c->mfc_parent].dev->ifindex) < 0)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2155

T
Thomas Graf 已提交
2156 2157
	if (!(mp_attr = nla_nest_start(skb, RTA_MULTIPATH)))
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2158 2159

	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
2160
		if (VIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
T
Thomas Graf 已提交
2161 2162 2163 2164 2165
			if (!(nhp = nla_reserve_nohdr(skb, sizeof(*nhp)))) {
				nla_nest_cancel(skb, mp_attr);
				return -EMSGSIZE;
			}

L
Linus Torvalds 已提交
2166 2167
			nhp->rtnh_flags = 0;
			nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
2168
			nhp->rtnh_ifindex = mrt->vif_table[ct].dev->ifindex;
L
Linus Torvalds 已提交
2169 2170 2171
			nhp->rtnh_len = sizeof(*nhp);
		}
	}
T
Thomas Graf 已提交
2172 2173 2174

	nla_nest_end(skb, mp_attr);

2175 2176 2177 2178 2179 2180
	mfcs.mfcs_packets = c->mfc_un.res.pkt;
	mfcs.mfcs_bytes = c->mfc_un.res.bytes;
	mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
	if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0)
		return -EMSGSIZE;

L
Linus Torvalds 已提交
2181 2182 2183 2184
	rtm->rtm_type = RTN_MULTICAST;
	return 1;
}

2185 2186 2187
int ipmr_get_route(struct net *net, struct sk_buff *skb,
		   __be32 saddr, __be32 daddr,
		   struct rtmsg *rtm, int nowait)
L
Linus Torvalds 已提交
2188 2189
{
	struct mfc_cache *cache;
2190 2191
	struct mr_table *mrt;
	int err;
L
Linus Torvalds 已提交
2192

2193 2194 2195 2196
	mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return -ENOENT;

2197
	rcu_read_lock();
2198
	cache = ipmr_cache_find(mrt, saddr, daddr);
2199 2200
	if (cache == NULL && skb->dev) {
		int vif = ipmr_find_vif(mrt, skb->dev);
L
Linus Torvalds 已提交
2201

2202 2203 2204
		if (vif >= 0)
			cache = ipmr_cache_find_any(mrt, daddr, vif);
	}
J
Jianjun Kong 已提交
2205
	if (cache == NULL) {
2206
		struct sk_buff *skb2;
2207
		struct iphdr *iph;
L
Linus Torvalds 已提交
2208
		struct net_device *dev;
E
Eric Dumazet 已提交
2209
		int vif = -1;
L
Linus Torvalds 已提交
2210 2211

		if (nowait) {
2212
			rcu_read_unlock();
L
Linus Torvalds 已提交
2213 2214 2215 2216
			return -EAGAIN;
		}

		dev = skb->dev;
2217
		read_lock(&mrt_lock);
E
Eric Dumazet 已提交
2218 2219 2220
		if (dev)
			vif = ipmr_find_vif(mrt, dev);
		if (vif < 0) {
L
Linus Torvalds 已提交
2221
			read_unlock(&mrt_lock);
2222
			rcu_read_unlock();
L
Linus Torvalds 已提交
2223 2224
			return -ENODEV;
		}
2225 2226 2227
		skb2 = skb_clone(skb, GFP_ATOMIC);
		if (!skb2) {
			read_unlock(&mrt_lock);
2228
			rcu_read_unlock();
2229 2230 2231
			return -ENOMEM;
		}

2232 2233
		skb_push(skb2, sizeof(struct iphdr));
		skb_reset_network_header(skb2);
2234 2235
		iph = ip_hdr(skb2);
		iph->ihl = sizeof(struct iphdr) >> 2;
2236 2237
		iph->saddr = saddr;
		iph->daddr = daddr;
2238
		iph->version = 0;
2239
		err = ipmr_cache_unresolved(mrt, vif, skb2);
L
Linus Torvalds 已提交
2240
		read_unlock(&mrt_lock);
2241
		rcu_read_unlock();
L
Linus Torvalds 已提交
2242 2243 2244
		return err;
	}

2245 2246
	read_lock(&mrt_lock);
	if (!nowait && (rtm->rtm_flags & RTM_F_NOTIFY))
L
Linus Torvalds 已提交
2247
		cache->mfc_flags |= MFC_NOTIFY;
2248
	err = __ipmr_fill_mroute(mrt, skb, cache, rtm);
L
Linus Torvalds 已提交
2249
	read_unlock(&mrt_lock);
2250
	rcu_read_unlock();
L
Linus Torvalds 已提交
2251 2252 2253
	return err;
}

2254
static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2255
			    u32 portid, u32 seq, struct mfc_cache *c, int cmd)
2256 2257 2258
{
	struct nlmsghdr *nlh;
	struct rtmsg *rtm;
2259
	int err;
2260

2261
	nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
2262 2263 2264 2265 2266 2267 2268 2269 2270
	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;
D
David S. Miller 已提交
2271 2272
	if (nla_put_u32(skb, RTA_TABLE, mrt->id))
		goto nla_put_failure;
2273 2274
	rtm->rtm_type     = RTN_MULTICAST;
	rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
2275 2276 2277 2278
	if (c->mfc_flags & MFC_STATIC)
		rtm->rtm_protocol = RTPROT_STATIC;
	else
		rtm->rtm_protocol = RTPROT_MROUTED;
2279 2280
	rtm->rtm_flags    = 0;

D
David S. Miller 已提交
2281 2282 2283
	if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) ||
	    nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp))
		goto nla_put_failure;
2284 2285 2286
	err = __ipmr_fill_mroute(mrt, skb, c, rtm);
	/* do not break the dump if cache is unresolved */
	if (err < 0 && err != -ENOENT)
2287 2288 2289 2290 2291 2292 2293 2294 2295
		goto nla_put_failure;

	return nlmsg_end(skb, nlh);

nla_put_failure:
	nlmsg_cancel(skb, nlh);
	return -EMSGSIZE;
}

2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
static size_t mroute_msgsize(bool unresolved, int maxvif)
{
	size_t len =
		NLMSG_ALIGN(sizeof(struct rtmsg))
		+ nla_total_size(4)	/* RTA_TABLE */
		+ nla_total_size(4)	/* RTA_SRC */
		+ nla_total_size(4)	/* RTA_DST */
		;

	if (!unresolved)
		len = len
		      + nla_total_size(4)	/* RTA_IIF */
		      + nla_total_size(0)	/* RTA_MULTIPATH */
		      + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
						/* RTA_MFC_STATS */
		      + nla_total_size(sizeof(struct rta_mfc_stats))
		;

	return len;
}

static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
				 int cmd)
{
	struct net *net = read_pnet(&mrt->net);
	struct sk_buff *skb;
	int err = -ENOBUFS;

	skb = nlmsg_new(mroute_msgsize(mfc->mfc_parent >= MAXVIFS, mrt->maxvif),
			GFP_ATOMIC);
	if (skb == NULL)
		goto errout;

	err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
	if (err < 0)
		goto errout;

	rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MROUTE, NULL, GFP_ATOMIC);
	return;

errout:
	kfree_skb(skb);
	if (err < 0)
		rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE, err);
}

2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
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];

2355
	rcu_read_lock();
2356 2357 2358 2359 2360 2361
	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++) {
2362
			list_for_each_entry_rcu(mfc, &mrt->mfc_cache_array[h], list) {
2363 2364 2365
				if (e < s_e)
					goto next_entry;
				if (ipmr_fill_mroute(mrt, skb,
2366
						     NETLINK_CB(cb->skb).portid,
2367
						     cb->nlh->nlmsg_seq,
2368
						     mfc, RTM_NEWROUTE) < 0)
2369 2370 2371 2372 2373 2374
					goto done;
next_entry:
				e++;
			}
			e = s_e = 0;
		}
2375 2376 2377 2378 2379 2380 2381
		spin_lock_bh(&mfc_unres_lock);
		list_for_each_entry(mfc, &mrt->mfc_unres_queue, list) {
			if (e < s_e)
				goto next_entry2;
			if (ipmr_fill_mroute(mrt, skb,
					     NETLINK_CB(cb->skb).portid,
					     cb->nlh->nlmsg_seq,
2382
					     mfc, RTM_NEWROUTE) < 0) {
2383 2384 2385 2386 2387 2388 2389 2390
				spin_unlock_bh(&mfc_unres_lock);
				goto done;
			}
next_entry2:
			e++;
		}
		spin_unlock_bh(&mfc_unres_lock);
		e = s_e = 0;
2391 2392 2393 2394 2395
		s_h = 0;
next_table:
		t++;
	}
done:
2396
	rcu_read_unlock();
2397 2398 2399 2400 2401 2402 2403 2404

	cb->args[2] = e;
	cb->args[1] = h;
	cb->args[0] = t;

	return skb->len;
}

2405
#ifdef CONFIG_PROC_FS
L
Linus Torvalds 已提交
2406
/*
E
Eric Dumazet 已提交
2407 2408
 *	The /proc interfaces to multicast routing :
 *	/proc/net/ip_mr_cache & /proc/net/ip_mr_vif
L
Linus Torvalds 已提交
2409 2410
 */
struct ipmr_vif_iter {
2411
	struct seq_net_private p;
2412
	struct mr_table *mrt;
L
Linus Torvalds 已提交
2413 2414 2415
	int ct;
};

2416 2417
static struct vif_device *ipmr_vif_seq_idx(struct net *net,
					   struct ipmr_vif_iter *iter,
L
Linus Torvalds 已提交
2418 2419
					   loff_t pos)
{
2420
	struct mr_table *mrt = iter->mrt;
2421 2422 2423

	for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) {
		if (!VIF_EXISTS(mrt, iter->ct))
L
Linus Torvalds 已提交
2424
			continue;
2425
		if (pos-- == 0)
2426
			return &mrt->vif_table[iter->ct];
L
Linus Torvalds 已提交
2427 2428 2429 2430 2431
	}
	return NULL;
}

static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
S
Stephen Hemminger 已提交
2432
	__acquires(mrt_lock)
L
Linus Torvalds 已提交
2433
{
2434
	struct ipmr_vif_iter *iter = seq->private;
2435
	struct net *net = seq_file_net(seq);
2436 2437 2438 2439 2440 2441 2442
	struct mr_table *mrt;

	mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return ERR_PTR(-ENOENT);

	iter->mrt = mrt;
2443

L
Linus Torvalds 已提交
2444
	read_lock(&mrt_lock);
2445
	return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1)
L
Linus Torvalds 已提交
2446 2447 2448 2449 2450 2451
		: SEQ_START_TOKEN;
}

static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct ipmr_vif_iter *iter = seq->private;
2452
	struct net *net = seq_file_net(seq);
2453
	struct mr_table *mrt = iter->mrt;
L
Linus Torvalds 已提交
2454 2455 2456

	++*pos;
	if (v == SEQ_START_TOKEN)
2457
		return ipmr_vif_seq_idx(net, iter, 0);
2458

2459 2460
	while (++iter->ct < mrt->maxvif) {
		if (!VIF_EXISTS(mrt, iter->ct))
L
Linus Torvalds 已提交
2461
			continue;
2462
		return &mrt->vif_table[iter->ct];
L
Linus Torvalds 已提交
2463 2464 2465 2466 2467
	}
	return NULL;
}

static void ipmr_vif_seq_stop(struct seq_file *seq, void *v)
S
Stephen Hemminger 已提交
2468
	__releases(mrt_lock)
L
Linus Torvalds 已提交
2469 2470 2471 2472 2473 2474
{
	read_unlock(&mrt_lock);
}

static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
{
2475 2476
	struct ipmr_vif_iter *iter = seq->private;
	struct mr_table *mrt = iter->mrt;
2477

L
Linus Torvalds 已提交
2478
	if (v == SEQ_START_TOKEN) {
2479
		seq_puts(seq,
L
Linus Torvalds 已提交
2480 2481 2482 2483 2484 2485 2486
			 "Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote\n");
	} else {
		const struct vif_device *vif = v;
		const char *name =  vif->dev ? vif->dev->name : "none";

		seq_printf(seq,
			   "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X %08X %08X\n",
2487
			   vif - mrt->vif_table,
2488
			   name, vif->bytes_in, vif->pkt_in,
L
Linus Torvalds 已提交
2489 2490 2491 2492 2493 2494
			   vif->bytes_out, vif->pkt_out,
			   vif->flags, vif->local, vif->remote);
	}
	return 0;
}

2495
static const struct seq_operations ipmr_vif_seq_ops = {
L
Linus Torvalds 已提交
2496 2497 2498 2499 2500 2501 2502 2503
	.start = ipmr_vif_seq_start,
	.next  = ipmr_vif_seq_next,
	.stop  = ipmr_vif_seq_stop,
	.show  = ipmr_vif_seq_show,
};

static int ipmr_vif_open(struct inode *inode, struct file *file)
{
2504 2505
	return seq_open_net(inode, file, &ipmr_vif_seq_ops,
			    sizeof(struct ipmr_vif_iter));
L
Linus Torvalds 已提交
2506 2507
}

2508
static const struct file_operations ipmr_vif_fops = {
L
Linus Torvalds 已提交
2509 2510 2511 2512
	.owner	 = THIS_MODULE,
	.open    = ipmr_vif_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
2513
	.release = seq_release_net,
L
Linus Torvalds 已提交
2514 2515 2516
};

struct ipmr_mfc_iter {
2517
	struct seq_net_private p;
2518
	struct mr_table *mrt;
2519
	struct list_head *cache;
L
Linus Torvalds 已提交
2520 2521 2522 2523
	int ct;
};


2524 2525
static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net,
					  struct ipmr_mfc_iter *it, loff_t pos)
L
Linus Torvalds 已提交
2526
{
2527
	struct mr_table *mrt = it->mrt;
L
Linus Torvalds 已提交
2528 2529
	struct mfc_cache *mfc;

2530
	rcu_read_lock();
2531
	for (it->ct = 0; it->ct < MFC_LINES; it->ct++) {
2532
		it->cache = &mrt->mfc_cache_array[it->ct];
2533
		list_for_each_entry_rcu(mfc, it->cache, list)
2534
			if (pos-- == 0)
L
Linus Torvalds 已提交
2535
				return mfc;
2536
	}
2537
	rcu_read_unlock();
L
Linus Torvalds 已提交
2538 2539

	spin_lock_bh(&mfc_unres_lock);
2540
	it->cache = &mrt->mfc_unres_queue;
2541
	list_for_each_entry(mfc, it->cache, list)
2542
		if (pos-- == 0)
L
Linus Torvalds 已提交
2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553
			return mfc;
	spin_unlock_bh(&mfc_unres_lock);

	it->cache = NULL;
	return NULL;
}


static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct ipmr_mfc_iter *it = seq->private;
2554
	struct net *net = seq_file_net(seq);
2555
	struct mr_table *mrt;
2556

2557 2558 2559
	mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
	if (mrt == NULL)
		return ERR_PTR(-ENOENT);
2560

2561
	it->mrt = mrt;
L
Linus Torvalds 已提交
2562 2563
	it->cache = NULL;
	it->ct = 0;
2564
	return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
L
Linus Torvalds 已提交
2565 2566 2567 2568 2569 2570 2571
		: SEQ_START_TOKEN;
}

static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct mfc_cache *mfc = v;
	struct ipmr_mfc_iter *it = seq->private;
2572
	struct net *net = seq_file_net(seq);
2573
	struct mr_table *mrt = it->mrt;
L
Linus Torvalds 已提交
2574 2575 2576 2577

	++*pos;

	if (v == SEQ_START_TOKEN)
2578
		return ipmr_mfc_seq_idx(net, seq->private, 0);
L
Linus Torvalds 已提交
2579

2580 2581
	if (mfc->list.next != it->cache)
		return list_entry(mfc->list.next, struct mfc_cache, list);
2582

2583
	if (it->cache == &mrt->mfc_unres_queue)
L
Linus Torvalds 已提交
2584 2585
		goto end_of_list;

2586
	BUG_ON(it->cache != &mrt->mfc_cache_array[it->ct]);
L
Linus Torvalds 已提交
2587 2588

	while (++it->ct < MFC_LINES) {
2589
		it->cache = &mrt->mfc_cache_array[it->ct];
2590 2591 2592
		if (list_empty(it->cache))
			continue;
		return list_first_entry(it->cache, struct mfc_cache, list);
L
Linus Torvalds 已提交
2593 2594 2595
	}

	/* exhausted cache_array, show unresolved */
2596
	rcu_read_unlock();
2597
	it->cache = &mrt->mfc_unres_queue;
L
Linus Torvalds 已提交
2598
	it->ct = 0;
2599

L
Linus Torvalds 已提交
2600
	spin_lock_bh(&mfc_unres_lock);
2601 2602
	if (!list_empty(it->cache))
		return list_first_entry(it->cache, struct mfc_cache, list);
L
Linus Torvalds 已提交
2603

E
Eric Dumazet 已提交
2604
end_of_list:
L
Linus Torvalds 已提交
2605 2606 2607 2608 2609 2610 2611 2612 2613
	spin_unlock_bh(&mfc_unres_lock);
	it->cache = NULL;

	return NULL;
}

static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
{
	struct ipmr_mfc_iter *it = seq->private;
2614
	struct mr_table *mrt = it->mrt;
L
Linus Torvalds 已提交
2615

2616
	if (it->cache == &mrt->mfc_unres_queue)
L
Linus Torvalds 已提交
2617
		spin_unlock_bh(&mfc_unres_lock);
2618
	else if (it->cache == &mrt->mfc_cache_array[it->ct])
2619
		rcu_read_unlock();
L
Linus Torvalds 已提交
2620 2621 2622 2623 2624 2625 2626
}

static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
{
	int n;

	if (v == SEQ_START_TOKEN) {
2627
		seq_puts(seq,
L
Linus Torvalds 已提交
2628 2629 2630 2631
		 "Group    Origin   Iif     Pkts    Bytes    Wrong Oifs\n");
	} else {
		const struct mfc_cache *mfc = v;
		const struct ipmr_mfc_iter *it = seq->private;
2632
		const struct mr_table *mrt = it->mrt;
2633

2634 2635 2636
		seq_printf(seq, "%08X %08X %-3hd",
			   (__force u32) mfc->mfc_mcastgrp,
			   (__force u32) mfc->mfc_origin,
2637
			   mfc->mfc_parent);
L
Linus Torvalds 已提交
2638

2639
		if (it->cache != &mrt->mfc_unres_queue) {
2640 2641 2642 2643
			seq_printf(seq, " %8lu %8lu %8lu",
				   mfc->mfc_un.res.pkt,
				   mfc->mfc_un.res.bytes,
				   mfc->mfc_un.res.wrong_if);
S
Stephen Hemminger 已提交
2644
			for (n = mfc->mfc_un.res.minvif;
E
Eric Dumazet 已提交
2645
			     n < mfc->mfc_un.res.maxvif; n++) {
2646
				if (VIF_EXISTS(mrt, n) &&
2647 2648
				    mfc->mfc_un.res.ttls[n] < 255)
					seq_printf(seq,
2649
					   " %2d:%-3d",
L
Linus Torvalds 已提交
2650 2651
					   n, mfc->mfc_un.res.ttls[n]);
			}
2652 2653 2654 2655 2656
		} else {
			/* unresolved mfc_caches don't contain
			 * pkt, bytes and wrong_if values
			 */
			seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
L
Linus Torvalds 已提交
2657 2658 2659 2660 2661 2662
		}
		seq_putc(seq, '\n');
	}
	return 0;
}

2663
static const struct seq_operations ipmr_mfc_seq_ops = {
L
Linus Torvalds 已提交
2664 2665 2666 2667 2668 2669 2670 2671
	.start = ipmr_mfc_seq_start,
	.next  = ipmr_mfc_seq_next,
	.stop  = ipmr_mfc_seq_stop,
	.show  = ipmr_mfc_seq_show,
};

static int ipmr_mfc_open(struct inode *inode, struct file *file)
{
2672 2673
	return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
			    sizeof(struct ipmr_mfc_iter));
L
Linus Torvalds 已提交
2674 2675
}

2676
static const struct file_operations ipmr_mfc_fops = {
L
Linus Torvalds 已提交
2677 2678 2679 2680
	.owner	 = THIS_MODULE,
	.open    = ipmr_mfc_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
2681
	.release = seq_release_net,
L
Linus Torvalds 已提交
2682
};
2683
#endif
L
Linus Torvalds 已提交
2684 2685

#ifdef CONFIG_IP_PIMSM_V2
2686
static const struct net_protocol pim_protocol = {
L
Linus Torvalds 已提交
2687
	.handler	=	pim_rcv,
T
Tom Goff 已提交
2688
	.netns_ok	=	1,
L
Linus Torvalds 已提交
2689 2690 2691 2692 2693 2694 2695
};
#endif


/*
 *	Setup for IP multicast routing
 */
2696 2697
static int __net_init ipmr_net_init(struct net *net)
{
2698
	int err;
2699

2700 2701
	err = ipmr_rules_init(net);
	if (err < 0)
2702
		goto fail;
2703 2704 2705

#ifdef CONFIG_PROC_FS
	err = -ENOMEM;
2706
	if (!proc_create("ip_mr_vif", 0, net->proc_net, &ipmr_vif_fops))
2707
		goto proc_vif_fail;
2708
	if (!proc_create("ip_mr_cache", 0, net->proc_net, &ipmr_mfc_fops))
2709 2710
		goto proc_cache_fail;
#endif
2711 2712
	return 0;

2713 2714
#ifdef CONFIG_PROC_FS
proc_cache_fail:
2715
	remove_proc_entry("ip_mr_vif", net->proc_net);
2716
proc_vif_fail:
2717
	ipmr_rules_exit(net);
2718
#endif
2719 2720 2721 2722 2723 2724
fail:
	return err;
}

static void __net_exit ipmr_net_exit(struct net *net)
{
2725
#ifdef CONFIG_PROC_FS
2726 2727
	remove_proc_entry("ip_mr_cache", net->proc_net);
	remove_proc_entry("ip_mr_vif", net->proc_net);
2728
#endif
2729
	ipmr_rules_exit(net);
2730 2731 2732 2733 2734 2735
}

static struct pernet_operations ipmr_net_ops = {
	.init = ipmr_net_init,
	.exit = ipmr_net_exit,
};
2736

W
Wang Chen 已提交
2737
int __init ip_mr_init(void)
L
Linus Torvalds 已提交
2738
{
W
Wang Chen 已提交
2739 2740
	int err;

L
Linus Torvalds 已提交
2741 2742
	mrt_cachep = kmem_cache_create("ip_mrt_cache",
				       sizeof(struct mfc_cache),
2743
				       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC,
2744
				       NULL);
W
Wang Chen 已提交
2745 2746 2747
	if (!mrt_cachep)
		return -ENOMEM;

2748 2749 2750 2751
	err = register_pernet_subsys(&ipmr_net_ops);
	if (err)
		goto reg_pernet_fail;

W
Wang Chen 已提交
2752 2753 2754
	err = register_netdevice_notifier(&ip_mr_notifier);
	if (err)
		goto reg_notif_fail;
T
Tom Goff 已提交
2755 2756
#ifdef CONFIG_IP_PIMSM_V2
	if (inet_add_protocol(&pim_protocol, IPPROTO_PIM) < 0) {
J
Joe Perches 已提交
2757
		pr_err("%s: can't add PIM protocol\n", __func__);
T
Tom Goff 已提交
2758 2759 2760 2761
		err = -EAGAIN;
		goto add_proto_fail;
	}
#endif
2762 2763
	rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE,
		      NULL, ipmr_rtm_dumproute, NULL);
W
Wang Chen 已提交
2764
	return 0;
2765

T
Tom Goff 已提交
2766 2767 2768 2769
#ifdef CONFIG_IP_PIMSM_V2
add_proto_fail:
	unregister_netdevice_notifier(&ip_mr_notifier);
#endif
B
Benjamin Thery 已提交
2770
reg_notif_fail:
2771 2772
	unregister_pernet_subsys(&ipmr_net_ops);
reg_pernet_fail:
B
Benjamin Thery 已提交
2773
	kmem_cache_destroy(mrt_cachep);
W
Wang Chen 已提交
2774
	return err;
L
Linus Torvalds 已提交
2775
}