#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>
-#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
#include <net/raw.h>
-#include <net/route.h>
#include <linux/notifier.h>
#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
#include <net/checksum.h>
#include <net/netlink.h>
#define mroute_do_pim 0
#endif
-static struct mfc6_cache *mfc6_cache_array[MFC_LINES]; /* Forwarding cache */
+static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */
static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */
static atomic_t cache_resolve_queue_len; /* Size of unresolved */
static struct kmem_cache *mrt_cachep __read_mostly;
static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache);
-static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert);
+static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert);
static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
#ifdef CONFIG_IPV6_PIMSM_V2
const char *name = vif->dev ? vif->dev->name : "none";
seq_printf(seq,
- "%2Zd %-10s %8ld %7ld %8ld %7ld %05X\n",
+ "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
vif - vif6_table,
name, vif->bytes_in, vif->pkt_in,
vif->bytes_out, vif->pkt_out,
const struct mfc6_cache *mfc = v;
const struct ipmr_mfc_iter *it = seq->private;
- seq_printf(seq,
- NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld",
- NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin),
+ seq_printf(seq, "%pI6 %pI6 %-3d %8ld %8ld %8ld",
+ &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
mfc->mf6c_parent,
mfc->mfc_un.res.pkt,
mfc->mfc_un.res.bytes,
if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
(pim->flags & PIM_NULL_REGISTER) ||
(ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
- (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))))
+ csum_fold(skb_checksum(skb, 0, skb->len, 0))))
goto drop;
/* check if the inner packet is destined to mcast group */
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
dst_release(skb->dst);
- ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len;
- ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++;
+ reg_dev->stats.rx_bytes += skb->len;
+ reg_dev->stats.rx_packets++;
skb->dst = NULL;
nf_reset(skb);
netif_rx(skb);
static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
{
read_lock(&mrt_lock);
- ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len;
- ((struct net_device_stats *)netdev_priv(dev))->tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
return 0;
}
-static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
-{
- return (struct net_device_stats *)netdev_priv(dev);
-}
-
static void reg_vif_setup(struct net_device *dev)
{
dev->type = ARPHRD_PIMREG;
dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
dev->flags = IFF_NOARP;
dev->hard_start_xmit = reg_vif_xmit;
- dev->get_stats = reg_vif_get_stats;
dev->destructor = free_netdev;
}
static struct net_device *ip6mr_reg_vif(void)
{
struct net_device *dev;
- struct inet6_dev *in_dev;
-
- dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg",
- reg_vif_setup);
+ dev = alloc_netdev(0, "pim6reg", reg_vif_setup);
if (dev == NULL)
return NULL;
}
dev->iflink = 0;
- in_dev = ipv6_find_idev(dev);
- if (!in_dev)
- goto failure;
-
if (dev_open(dev))
goto failure;
+ dev_hold(dev);
return dev;
failure:
{
int vifi;
- cache->mfc_un.res.minvif = MAXVIFS;
+ cache->mfc_un.res.minvif = MAXMIFS;
cache->mfc_un.res.maxvif = 0;
- memset(cache->mfc_un.res.ttls, 255, MAXVIFS);
+ memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
for (vifi = 0; vifi < maxvif; vifi++) {
if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
int vifi = vifc->mif6c_mifi;
struct mif_device *v = &vif6_table[vifi];
struct net_device *dev;
+ int err;
/* Is vif busy ? */
if (MIF_EXISTS(vifi))
dev = ip6mr_reg_vif();
if (!dev)
return -ENOBUFS;
+ err = dev_set_allmulti(dev, 1);
+ if (err) {
+ unregister_netdevice(dev);
+ dev_put(dev);
+ return err;
+ }
break;
#endif
case 0:
dev = dev_get_by_index(&init_net, vifc->mif6c_pifi);
if (!dev)
return -EADDRNOTAVAIL;
- dev_put(dev);
+ err = dev_set_allmulti(dev, 1);
+ if (err) {
+ dev_put(dev);
+ return err;
+ }
break;
default:
return -EINVAL;
}
- dev_set_allmulti(dev, 1);
-
/*
* Fill in the VIF structures
*/
/* And finish update writing critical data */
write_lock_bh(&mrt_lock);
- dev_hold(dev);
v->dev = dev;
#ifdef CONFIG_IPV6_PIMSM_V2
if (v->flags & MIFF_REGISTER)
if (c == NULL)
return NULL;
memset(c, 0, sizeof(*c));
- c->mfc_un.res.minvif = MAXVIFS;
+ c->mfc_un.res.minvif = MAXMIFS;
return c;
}
struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
- nlh->nlmsg_len = skb->tail - (u8 *)nlh;
+ nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
} else {
nlh->nlmsg_type = NLMSG_ERROR;
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
* Called under mrt_lock.
*/
-static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
+static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
{
struct sk_buff *skb;
struct mrt6msg *msg;
msg->im6_mbz = 0;
msg->im6_msgtype = assert;
- msg->im6_mif = vifi;
+ msg->im6_mif = mifi;
msg->im6_pad = 0;
ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
*/
static int
-ip6mr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
+ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
{
int err;
struct mfc6_cache *c;
/*
* Reflect first query at pim6sd
*/
- if ((err = ip6mr_cache_report(skb, vifi, MRT6MSG_NOCACHE)) < 0) {
+ if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) {
/* If the report failed throw the cache entry
out - Brad Parker
*/
struct mif_device *v;
int ct;
- if (dev_net(dev) != &init_net)
+ if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
if (event != NETDEV_UNREGISTER)
* Setup for IP multicast routing
*/
-void __init ip6_mr_init(void)
+int __init ip6_mr_init(void)
{
+ int err;
+
mrt_cachep = kmem_cache_create("ip6_mrt_cache",
sizeof(struct mfc6_cache),
0, SLAB_HWCACHE_ALIGN,
NULL);
if (!mrt_cachep)
- panic("cannot allocate ip6_mrt_cache");
+ return -ENOMEM;
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
- register_netdevice_notifier(&ip6_mr_notifier);
+ err = register_netdevice_notifier(&ip6_mr_notifier);
+ if (err)
+ goto reg_notif_fail;
+#ifdef CONFIG_PROC_FS
+ err = -ENOMEM;
+ if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
+ goto proc_vif_fail;
+ if (!proc_net_fops_create(&init_net, "ip6_mr_cache",
+ 0, &ip6mr_mfc_fops))
+ goto proc_cache_fail;
+#endif
+ return 0;
#ifdef CONFIG_PROC_FS
- proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops);
- proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops);
+proc_cache_fail:
+ proc_net_remove(&init_net, "ip6_mr_vif");
+proc_vif_fail:
+ unregister_netdevice_notifier(&ip6_mr_notifier);
#endif
+reg_notif_fail:
+ del_timer(&ipmr_expire_timer);
+ kmem_cache_destroy(mrt_cachep);
+ return err;
}
+void ip6_mr_cleanup(void)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_remove(&init_net, "ip6_mr_cache");
+ proc_net_remove(&init_net, "ip6_mr_vif");
+#endif
+ unregister_netdevice_notifier(&ip6_mr_notifier);
+ del_timer(&ipmr_expire_timer);
+ kmem_cache_destroy(mrt_cachep);
+}
static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
{
int line;
struct mfc6_cache *uc, *c, **cp;
- unsigned char ttls[MAXVIFS];
+ unsigned char ttls[MAXMIFS];
int i;
- memset(ttls, 255, MAXVIFS);
- for (i = 0; i < MAXVIFS; i++) {
+ memset(ttls, 255, MAXMIFS);
+ for (i = 0; i < MAXMIFS; i++) {
if (IF_ISSET(i, &mfc->mf6cc_ifset))
ttls[i] = 1;
return -EINVAL;
if (copy_from_user(&vif, optval, sizeof(vif)))
return -EFAULT;
- if (vif.mif6c_mifi >= MAXVIFS)
+ if (vif.mif6c_mifi >= MAXMIFS)
return -ENFILE;
rtnl_lock();
ret = mif6_add(&vif, sk == mroute6_socket);
#ifdef CONFIG_IPV6_PIMSM_V2
case MRT6_PIM:
{
- int v, ret;
+ int v;
if (get_user(v, (int __user *)optval))
return -EFAULT;
v = !!v;
#endif
/*
- * Spurious command, or MRT_VERSION which you cannot
+ * Spurious command, or MRT6_VERSION which you cannot
* set.
*/
default:
static inline int ip6mr_forward2_finish(struct sk_buff *skb)
{
- /* XXX stats */
+ IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst),
+ IPSTATS_MIB_OUTFORWDATAGRAMS);
return dst_output(skb);
}
if (vif->flags & MIFF_REGISTER) {
vif->pkt_out++;
vif->bytes_out += skb->len;
- ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len;
- ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++;
+ vif->dev->stats.tx_bytes += skb->len;
+ vif->dev->stats.tx_packets++;
ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT);
kfree_skb(skb);
return 0;
int ct;
struct rtnexthop *nhp;
struct net_device *dev = vif6_table[c->mf6c_parent].dev;
- u8 *b = skb->tail;
+ u8 *b = skb_tail_pointer(skb);
struct rtattr *mp_head;
if (dev)
}
}
mp_head->rta_type = RTA_MULTIPATH;
- mp_head->rta_len = skb->tail - (u8 *)mp_head;
+ mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
rtm->rtm_type = RTN_MULTICAST;
return 1;