#include <linux/pim.h>
#include <net/addrconf.h>
#include <linux/netfilter_ipv6.h>
+#include <net/ip6_checksum.h>
/* Big lock, protecting vif table, mrt cache and mroute socket state.
Note that the changes are semaphored via rtnl_lock.
static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
static void mroute_clean_tables(struct net *net);
-#ifdef CONFIG_IPV6_PIMSM_V2
-static struct inet6_protocol pim6_protocol;
-#endif
-
static struct timer_list ipmr_expire_timer;
return 0;
}
-static struct seq_operations ip6mr_vif_seq_ops = {
+static const struct seq_operations ip6mr_vif_seq_ops = {
.start = ip6mr_vif_seq_start,
.next = ip6mr_vif_seq_next,
.stop = ip6mr_vif_seq_stop,
sizeof(struct ipmr_vif_iter));
}
-static struct file_operations ip6mr_vif_fops = {
+static const struct file_operations ip6mr_vif_fops = {
.owner = THIS_MODULE,
.open = ip6mr_vif_open,
.read = seq_read,
return 0;
}
-static struct seq_operations ipmr_mfc_seq_ops = {
+static const struct seq_operations ipmr_mfc_seq_ops = {
.start = ipmr_mfc_seq_start,
.next = ipmr_mfc_seq_next,
.stop = ipmr_mfc_seq_stop,
sizeof(struct ipmr_mfc_iter));
}
-static struct file_operations ip6mr_mfc_fops = {
+static const struct file_operations ip6mr_mfc_fops = {
.owner = THIS_MODULE,
.open = ipmr_mfc_open,
.read = seq_read,
skb->protocol = htons(ETH_P_IPV6);
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
- dst_release(skb->dst);
+ skb_dst_drop(skb);
reg_dev->stats.rx_bytes += skb->len;
reg_dev->stats.rx_packets++;
- skb->dst = NULL;
nf_reset(skb);
netif_rx(skb);
dev_put(reg_dev);
return 0;
}
-static struct inet6_protocol pim6_protocol = {
+static const struct inet6_protocol pim6_protocol = {
.handler = pim6_rcv,
};
/* Service routines creating virtual interfaces: PIMREG */
-static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct net *net = dev_net(dev);
MRT6MSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static const struct net_device_ops reg_vif_netdev_ops = {
dev->flags = IFF_NOARP;
dev->netdev_ops = ®_vif_netdev_ops;
dev->destructor = free_netdev;
+ dev->features |= NETIF_F_NETNS_LOCAL;
}
static struct net_device *ip6mr_reg_vif(struct net *net)
ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
- skb->dst = dst_clone(pkt->dst);
+ skb_dst_set(skb, dst_clone(skb_dst(pkt)));
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
err = register_netdevice_notifier(&ip6_mr_notifier);
if (err)
goto reg_notif_fail;
+#ifdef CONFIG_IPV6_PIMSM_V2
+ if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
+ printk(KERN_ERR "ip6_mr_init: can't add PIM protocol\n");
+ err = -EAGAIN;
+ goto add_proto_fail;
+ }
+#endif
return 0;
+#ifdef CONFIG_IPV6_PIMSM_V2
+add_proto_fail:
+ unregister_netdevice_notifier(&ip6_mr_notifier);
+#endif
reg_notif_fail:
del_timer(&ipmr_expire_timer);
unregister_pernet_subsys(&ip6mr_net_ops);
* MOSPF/PIM router set up we can clean this up.
*/
-int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
+int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
{
int ret;
struct mif6ctl vif;
if (v != net->ipv6.mroute_do_pim) {
net->ipv6.mroute_do_pim = v;
net->ipv6.mroute_do_assert = v;
- if (net->ipv6.mroute_do_pim)
- ret = inet6_add_protocol(&pim6_protocol,
- IPPROTO_PIM);
- else
- ret = inet6_del_protocol(&pim6_protocol,
- IPPROTO_PIM);
- if (ret < 0)
- ret = -EAGAIN;
}
rtnl_unlock();
return ret;
static inline int ip6mr_forward2_finish(struct sk_buff *skb)
{
- IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst),
+ IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
IPSTATS_MIB_OUTFORWDATAGRAMS);
return dst_output(skb);
}
if (!dst)
goto out_free;
- dst_release(skb->dst);
- skb->dst = dst;
+ skb_dst_drop(skb);
+ skb_dst_set(skb, dst);
/*
* RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
{
int err;
struct mfc6_cache *cache;
- struct rt6_info *rt = (struct rt6_info *)skb->dst;
+ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
read_lock(&mrt_lock);
cache = ip6mr_cache_find(net, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);