示例#1
0
static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
{
	struct inet6_dev *idev = in6_dev_get(skb->dev);
	if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
		if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
			UDP6_INC_STATS_BH(UdpInErrors);
			IP6_INC_STATS_BH(idev,Ip6InDiscards);
			if (idev)
				in6_dev_put(idev);
			kfree_skb(skb);
			return 0;
		}
		skb->ip_summed = CHECKSUM_UNNECESSARY;
	}
	if (sock_queue_rcv_skb(sk,skb)<0) {
		UDP6_INC_STATS_BH(UdpInErrors);
		IP6_INC_STATS_BH(idev,Ip6InDiscards);
		if (idev)
			in6_dev_put(idev);
		kfree_skb(skb);
		return 0;
	}
  	IP6_INC_STATS_BH(idev,Ip6InDelivers);
	UDP6_INC_STATS_BH(UdpInDatagrams);

	if (idev)
		in6_dev_put(idev);
	return 0;
}
示例#2
0
文件: mcast.c 项目: dmgerman/original
/*
 *	device multicast group del
 */
int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
{
	struct inet6_dev *idev;
	struct ifmcaddr6 *ma, **map;

	idev = in6_dev_get(dev);
	if (idev == NULL)
		return -ENODEV;

	write_lock_bh(&idev->lock);
	for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) {
		if (ipv6_addr_cmp(&ma->mca_addr, addr) == 0) {
			if (--ma->mca_users == 0) {
				*map = ma->next;
				write_unlock_bh(&idev->lock);

				igmp6_group_dropped(ma);

				ma_put(ma);
				in6_dev_put(idev);
				return 0;
			}
			write_unlock_bh(&idev->lock);
			in6_dev_put(idev);
			return 0;
		}
	}
	write_unlock_bh(&idev->lock);
	in6_dev_put(idev);

	return -ENOENT;
}
示例#3
0
/*
 *	check if the interface/address pair is valid
 */
int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *addr)
{
	struct inet6_dev *idev;
	struct ifmcaddr6 *mc;
#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(addr, abuf);

	MDBG3((KERN_DEBUG
		"ipv6_chk_mcast_addr(dev=%p(%s), addr=%s)\n",
		dev, dev->name ? dev->name : "<null>", abuf));
#endif

	idev = in6_dev_get(dev);
	if (idev) {
		read_lock_bh(&idev->lock);
		for (mc = idev->mc_list; mc; mc=mc->next) {
			if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
				read_unlock_bh(&idev->lock);
				in6_dev_put(idev);
				return 1;
			}
		}
		read_unlock_bh(&idev->lock);
		in6_dev_put(idev);
	}
	return 0;
}
示例#4
0
static int igmp6_read_proc(char *buffer, char **start, off_t offset,
			   int length, int *eof, void *data)
{
	off_t pos=0, begin=0;
	struct ifmcaddr6 *im;
	int len=0;
	struct net_device *dev;
	
	read_lock(&dev_base_lock);
	for (dev = dev_base; dev; dev = dev->next) {
		struct inet6_dev *idev;

		if ((idev = in6_dev_get(dev)) == NULL)
			continue;

		read_lock_bh(&idev->lock);
		for (im = idev->mc_list; im; im = im->next) {
			int i;

			len += sprintf(buffer+len,"%-4d %-15s ", dev->ifindex, dev->name);

			for (i=0; i<16; i++)
				len += sprintf(buffer+len, "%02x", im->mca_addr.s6_addr[i]);

			len+=sprintf(buffer+len,
				     " %5d %08X %ld\n",
				     im->mca_users,
				     im->mca_flags,
				     (im->mca_flags&MAF_TIMER_RUNNING) ? im->mca_timer.expires-jiffies : 0);

			pos=begin+len;
			if (pos < offset) {
				len=0;
				begin=pos;
			}
			if (pos > offset+length) {
				read_unlock_bh(&idev->lock);
				in6_dev_put(idev);
				goto done;
			}
		}
		read_unlock_bh(&idev->lock);
		in6_dev_put(idev);
	}
	*eof = 1;

done:
	read_unlock(&dev_base_lock);

	*start=buffer+(offset-begin);
	len-=(offset-begin);
	if(len>length)
		len=length;
	if (len<0)
		len=0;
	return len;
}
示例#5
0
文件: mcast.c 项目: dmgerman/original
/*
 *	device multicast group inc (add if not found)
 */
int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev *idev;

	idev = in6_dev_get(dev);

	if (idev == NULL)
		return -EINVAL;

	write_lock_bh(&idev->lock);
	if (idev->dead) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENODEV;
	}

	for (mc = idev->mc_list; mc; mc = mc->next) {
		if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
			mc->mca_users++;
			write_unlock_bh(&idev->lock);
			in6_dev_put(idev);
			return 0;
		}
	}

	/*
	 *	not found: create a new one.
	 */

	mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);

	if (mc == NULL) {
		write_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	memset(mc, 0, sizeof(struct ifmcaddr6));
	mc->mca_timer.function = igmp6_timer_handler;
	mc->mca_timer.data = (unsigned long) mc;

	memcpy(&mc->mca_addr, addr, sizeof(struct in6_addr));
	mc->idev = idev;
	mc->mca_users = 1;
	atomic_set(&mc->mca_refcnt, 2);
	mc->mca_lock = SPIN_LOCK_UNLOCKED;

	mc->next = idev->mc_list;
	idev->mc_list = mc;
	write_unlock_bh(&idev->lock);

	igmp6_group_added(mc);
	ma_put(mc);
	return 0;
}
static void rmnet_usb_setup(struct net_device *dev)
{
#ifdef DISABLE_RMNET_USB_IPV6_ACCEPT_RA_DEFRTR
	struct inet6_dev *idev = NULL;
#endif //DISABLE_RMNET_USB_IPV6_ACCEPT_RA_DEFRTR

	/* Using Ethernet mode by default */
	dev->netdev_ops = &rmnet_usb_ops_ether;

	/* set this after calling ether_setup */
	dev->mtu = RMNET_DATA_LEN;

	dev->needed_headroom = HEADROOM_FOR_QOS;
	random_ether_addr(dev->dev_addr);
	dev->watchdog_timeo = 1000; /* 10 seconds? */

#ifdef DISABLE_RMNET_USB_IPV6_ACCEPT_RA_DEFRTR
	idev = in6_dev_get(dev);
	if (idev)
	{
		idev->cnf.accept_ra_defrtr = 0;
		if (idev->dev)
			pr_info("net_device:%s set accept_ra_defrtr:%d\n", idev->dev->name, idev->cnf.accept_ra_defrtr);
	}

	if (idev)
		in6_dev_put(idev);
#endif //DISABLE_RMNET_USB_IPV6_ACCEPT_RA_DEFRTR
}
示例#7
0
static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
			     int unregister)
{
	struct xfrm_dst *xdst;

	if (!unregister)
		return;

	xdst = (struct xfrm_dst *)dst;
	if (xdst->u.rt6.rt6i_idev->dev == dev) {
		struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
		BUG_ON(!loopback_idev);

		do {
			in6_dev_put(xdst->u.rt6.rt6i_idev);
			xdst->u.rt6.rt6i_idev = loopback_idev;
			in6_dev_hold(loopback_idev);
			xdst = (struct xfrm_dst *)xdst->u.dst.child;
		} while (xdst->u.dst.xfrm);

		__in6_dev_put(loopback_idev);
	}

	xfrm_dst_ifdown(dst, dev);
}
示例#8
0
文件: vrf.c 项目: AshishNamdev/linux
/* holding rtnl */
static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
{
	struct rt6_info *rt6 = rtnl_dereference(vrf->rt6);
	struct rt6_info *rt6_local = rtnl_dereference(vrf->rt6_local);
	struct net *net = dev_net(dev);
	struct dst_entry *dst;

	RCU_INIT_POINTER(vrf->rt6, NULL);
	RCU_INIT_POINTER(vrf->rt6_local, NULL);
	synchronize_rcu();

	/* move dev in dst's to loopback so this VRF device can be deleted
	 * - based on dst_ifdown
	 */
	if (rt6) {
		dst = &rt6->dst;
		dev_put(dst->dev);
		dst->dev = net->loopback_dev;
		dev_hold(dst->dev);
		dst_release(dst);
	}

	if (rt6_local) {
		if (rt6_local->rt6i_idev)
			in6_dev_put(rt6_local->rt6i_idev);

		dst = &rt6_local->dst;
		dev_put(dst->dev);
		dst->dev = net->loopback_dev;
		dev_hold(dst->dev);
		dst_release(dst);
	}
}
示例#9
0
文件: mcast.c 项目: dmgerman/original
static void ma_put(struct ifmcaddr6 *mc)
{
	if (atomic_dec_and_test(&mc->mca_refcnt)) {
		in6_dev_put(mc->idev);
		kfree(mc);
	}
}
示例#10
0
static void xfrm6_dst_destroy(struct dst_entry *dst)
{
	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;

	if (likely(xdst->u.rt6.rt6i_idev))
		in6_dev_put(xdst->u.rt6.rt6i_idev);
	xfrm_dst_destroy(xdst);
}
示例#11
0
static void aca_put(struct ifacaddr6 *ac)
{
	if (atomic_dec_and_test(&ac->aca_refcnt)) {
		in6_dev_put(ac->aca_idev);
		dst_release(&ac->aca_rt->u.dst);
		kfree(ac);
	}
}
示例#12
0
static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
{
	int ret;
	struct inet6_dev *idev = in6_dev_get(dev);
	if (idev == NULL)
		return -ENODEV;
	ret = __ipv6_dev_ac_dec(idev, addr);
	in6_dev_put(idev);
	return ret;
}
int ip6_pkt_discard(struct sk_buff *skb)
{
	struct inet6_dev *idev = in6_dev_get(skb->dev);
	IP6_INC_STATS(idev,Ip6OutNoRoutes);
	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
	if (idev)
		in6_dev_put(idev);
	kfree_skb(skb);
	return 0;
}
示例#14
0
static void xfrm6_dst_destroy(struct dst_entry *dst)
{
	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;

	if (likely(xdst->u.rt6.rt6i_idev))
		in6_dev_put(xdst->u.rt6.rt6i_idev);
	dst_destroy_metrics_generic(dst);
	if (likely(xdst->u.rt6.rt6i_peer))
		inet_putpeer(xdst->u.rt6.rt6i_peer);
	xfrm_dst_destroy(xdst);
}
示例#15
0
static void ma_put(struct ifmcaddr6 *mc)
{
	MDBG3((KERN_DEBUG
		"ma_put(mc=%p): refcnt=%d\n", 
		mc, atomic_read(&mc->mca_refcnt)));

	if (atomic_dec_and_test(&mc->mca_refcnt)) {
		in6_dev_put(mc->idev);
		kfree(mc);
	}
}
示例#16
0
文件: mcast.c 项目: dmgerman/original
/*
 *	check if the interface/address pair is valid
 */
int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *addr)
{
	struct inet6_dev *idev;
	struct ifmcaddr6 *mc;

	idev = in6_dev_get(dev);
	if (idev) {
		read_lock_bh(&idev->lock);
		for (mc = idev->mc_list; mc; mc=mc->next) {
			if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
				read_unlock_bh(&idev->lock);
				in6_dev_put(idev);
				return 1;
			}
		}
		read_unlock_bh(&idev->lock);
		in6_dev_put(idev);
	}
	return 0;
}
示例#17
0
/*
 *	device multicast group del
 */
int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
{
	struct inet6_dev *idev;
	struct ifmcaddr6 *ma, **map;

#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(addr, abuf);

	MDBG3((KERN_DEBUG
		"ipv6_dev_mc_dec(dev=%p(%s), addr=%s)\n",
		dev, dev->name ? dev->name : "<null>", abuf));
#endif

	idev = in6_dev_get(dev);
	if (idev == NULL)
		return -ENODEV;

	write_lock_bh(&idev->lock);
	for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) {
		if (ipv6_addr_cmp(&ma->mca_addr, addr) == 0) {
			if (--ma->mca_users == 0) {
				*map = ma->next;
				write_unlock_bh(&idev->lock);

				igmp6_group_dropped(ma);

				ma_put(ma);
				in6_dev_put(idev);
				return 0;
			}
			write_unlock_bh(&idev->lock);
			in6_dev_put(idev);
			return 0;
		}
	}
	write_unlock_bh(&idev->lock);
	in6_dev_put(idev);

	return -ENOENT;
}
示例#18
0
static int ipv6_get_hoplimit(struct net_device *dev)
{
	int hoplimit = ipv6_devconf.hop_limit;
	struct inet6_dev *idev;

	idev = in6_dev_get(dev);
	if (idev) {
		hoplimit = idev->cnf.hop_limit;
		in6_dev_put(idev);
	}
	return hoplimit;
}
示例#19
0
static int ipv6_get_mtu(struct net_device *dev)
{
	int mtu = IPV6_MIN_MTU;
	struct inet6_dev *idev;

	idev = in6_dev_get(dev);
	if (idev) {
		mtu = idev->cnf.mtu6;
		in6_dev_put(idev);
	}
	return mtu;
}
示例#20
0
static void xfrm6_dst_destroy(struct dst_entry *dst)
{
	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;

	if (likely(xdst->u.rt6.rt6i_idev))
		in6_dev_put(xdst->u.rt6.rt6i_idev);
	dst_destroy_metrics_generic(dst);
	if (rt6_has_peer(&xdst->u.rt6)) {
		struct inet_peer *peer = rt6_peer_ptr(&xdst->u.rt6);
		inet_putpeer(peer);
	}
	xfrm_dst_destroy(xdst);
}
示例#21
0
static int ndisc_constructor(struct neighbour *neigh)
{
	struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
	struct net_device *dev = neigh->dev;
	struct inet6_dev *in6_dev;
	struct neigh_parms *parms;
	int is_multicast = ipv6_addr_is_multicast(addr);

	rcu_read_lock();
	in6_dev = in6_dev_get(dev);
	if (in6_dev == NULL) {
		rcu_read_unlock();
		return -EINVAL;
	}

	parms = in6_dev->nd_parms;
	__neigh_parms_put(neigh->parms);
	neigh->parms = neigh_parms_clone(parms);
	rcu_read_unlock();

	neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
	if (dev->hard_header == NULL) {
		neigh->nud_state = NUD_NOARP;
		neigh->ops = &ndisc_direct_ops;
		neigh->output = neigh->ops->queue_xmit;
	} else {
		if (is_multicast) {
			neigh->nud_state = NUD_NOARP;
			ndisc_mc_map(addr, neigh->ha, dev, 1);
		} else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
			neigh->nud_state = NUD_NOARP;
			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
			if (dev->flags&IFF_LOOPBACK)
				neigh->type = RTN_LOCAL;
		} else if (dev->flags&IFF_POINTOPOINT) {
			neigh->nud_state = NUD_NOARP;
			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
		}
		if (dev->hard_header_cache)
			neigh->ops = &ndisc_hh_ops;
		else
			neigh->ops = &ndisc_generic_ops;
		if (neigh->nud_state&NUD_VALID)
			neigh->output = neigh->ops->connected_output;
		else
			neigh->output = neigh->ops->output;
	}
	in6_dev_put(in6_dev);
	return 0;
}
示例#22
0
/* Some devices are known to send Neigbor Solicitation messages and
 * require Neigbor Advertisement replies.  The IPv6 core will not
 * respond since IFF_NOARP is set, so we must handle them ourselves.
 */
static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
{
	struct ipv6hdr *iph = (void *)buf;
	struct nd_msg *msg = (void *)(iph + 1);
	struct net_device *netdev;
	struct inet6_dev *in6_dev;
	bool is_router;

	/* we'll only respond to requests from unicast addresses to
	 * our solicited node addresses.
	 */
	if (!ipv6_addr_is_solict_mult(&iph->daddr) ||
	    !(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST))
		return;

	/* need to send the NA on the VLAN dev, if any */
	rcu_read_lock();
	if (tci) {
		netdev = __vlan_find_dev_deep_rcu(dev->net, htons(ETH_P_8021Q),
						  tci);
		if (!netdev) {
			rcu_read_unlock();
			return;
		}
	} else {
		netdev = dev->net;
	}
	dev_hold(netdev);
	rcu_read_unlock();

	in6_dev = in6_dev_get(netdev);
	if (!in6_dev)
		goto out;
	is_router = !!in6_dev->cnf.forwarding;
	in6_dev_put(in6_dev);

	/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
	ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target,
				 is_router /* router */,
				 true /* solicited */,
				 false /* override */,
				 true /* inc_opt */);
#else
	ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target,
				 is_router, true, false, true);
#endif
out:
	dev_put(netdev);
}
示例#23
0
void ndisc_send_skb(struct sk_buff *skb,
		    struct net_device *dev,
		    struct neighbour *neigh,
		    const struct in6_addr *daddr,
		    const struct in6_addr *saddr,
		    struct icmp6hdr *icmp6h)
{
	struct flowi fl;
	struct dst_entry *dst;
	struct net *net = dev_net(dev);
	struct sock *sk = net->ipv6.ndisc_sk;
	struct inet6_dev *idev;
	int err;
	u8 type;

	type = icmp6h->icmp6_type;

	icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);

	dst = icmp6_dst_alloc(dev, neigh, daddr);
	if (!dst) {
		kfree_skb(skb);
		return;
	}

	err = xfrm_lookup(net, &dst, &fl, NULL, 0);
	if (err < 0) {
		kfree_skb(skb);
		return;
	}

	skb_dst_set(skb, dst);

	idev = in6_dev_get(dst->dev);
	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
		      dst_output);
	if (!err) {
		ICMP6MSGOUT_INC_STATS(net, idev, type);
		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
	}

	if (likely(idev != NULL))
		in6_dev_put(idev);
}
示例#24
0
/*
 *	check if the interface has this anycast address
 */
static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
{
	struct inet6_dev *idev;
	struct ifacaddr6 *aca;

	idev = in6_dev_get(dev);
	if (idev) {
		read_lock_bh(&idev->lock);
		for (aca = idev->ac_list; aca; aca = aca->aca_next)
			if (ipv6_addr_equal(&aca->aca_addr, addr))
				break;
		read_unlock_bh(&idev->lock);
		in6_dev_put(idev);
		return aca != NULL;
	}
	return 0;
}
示例#25
0
文件: stats.c 项目: magg/NAT64
static void inc_stats_ipv6(struct sk_buff *skb, int field)
{
	struct inet6_dev *idev;

	if (is_error(inc_stats_validate(skb))) {
		/* Maybe we can fall back to increase the stat on the other skb's dev... */
		skb = skb_original_skb(skb);
		if (is_error(inc_stats_validate(skb)))
			return;
	}
	idev = in6_dev_get(skb->dev);
	if (!idev)
		return;

	IP6_INC_STATS_BH(dev_net(skb->dev), idev, field);

	in6_dev_put(idev);
}
示例#26
0
文件: mcast.c 项目: dmgerman/original
int igmp6_event_query(struct sk_buff *skb, struct icmp6hdr *hdr, int len)
{
	struct ifmcaddr6 *ma;
	struct in6_addr *addrp;
	unsigned long resptime;
	struct inet6_dev *idev;


	if (len < sizeof(struct icmp6hdr) + sizeof(struct in6_addr))
		return -EINVAL;

	/* Drop queries with not link local source */
	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
		return -EINVAL;

	resptime = ntohs(hdr->icmp6_maxdelay);
	/* Translate milliseconds to jiffies */
	resptime = (resptime<<10)/(1024000/HZ);

	addrp = (struct in6_addr *) (hdr + 1);

	idev = in6_dev_get(skb->dev);

	if (idev == NULL)
		return 0;

	read_lock(&idev->lock);
	if (ipv6_addr_any(addrp)) {
		for (ma = idev->mc_list; ma; ma=ma->next)
			igmp6_group_queried(ma, resptime);
	} else {
		for (ma = idev->mc_list; ma; ma=ma->next) {
			if (ipv6_addr_cmp(addrp, &ma->mca_addr) == 0) {
				igmp6_group_queried(ma, resptime);
				break;
			}
		}
	}
	read_unlock(&idev->lock);
	in6_dev_put(idev);

	return 0;
}
示例#27
0
void ndisc_send_skb(struct sk_buff *skb,
		    struct net_device *dev,
		    struct neighbour *neigh,
		    struct in6_addr *daddr,
		    struct in6_addr *saddr,
		    struct icmp6hdr *icmp6h)
{
	struct flowi fl;
	struct dst_entry *dst;
	struct inet6_dev *idev;
	int err;
	u8 type;

	type = icmp6h->icmp6_type;

	ndisc_flow_init(&fl, icmp6h->icmp6_type, saddr, daddr, dev->ifindex);

	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
	if (!dst) {
		kfree_skb(skb);
		return;
	}

	err = xfrm_lookup(&dst, &fl, NULL, 0);
	if (err < 0) {
		kfree_skb(skb);
		return;
	}

	skb->dst = dst;

	idev = in6_dev_get(dst->dev);
	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);

	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
	if (!err) {
		ICMP6_INC_STATS(idev, type);
		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
	}

	if (likely(idev != NULL))
		in6_dev_put(idev);
}
示例#28
0
文件: mcast.c 项目: dmgerman/original
int igmp6_event_report(struct sk_buff *skb, struct icmp6hdr *hdr, int len)
{
	struct ifmcaddr6 *ma;
	struct in6_addr *addrp;
	struct inet6_dev *idev;

	/* Our own report looped back. Ignore it. */
	if (skb->pkt_type == PACKET_LOOPBACK)
		return 0;

	if (len < sizeof(struct icmp6hdr) + sizeof(struct in6_addr))
		return -EINVAL;

	/* Drop reports with not link local source */
	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
		return -EINVAL;

	addrp = (struct in6_addr *) (hdr + 1);

	idev = in6_dev_get(skb->dev);
	if (idev == NULL)
		return -ENODEV;

	/*
	 *	Cancel the timer for this group
	 */

	read_lock(&idev->lock);
	for (ma = idev->mc_list; ma; ma=ma->next) {
		if (ipv6_addr_cmp(&ma->mca_addr, addrp) == 0) {
			spin_lock(&ma->mca_lock);
			if (del_timer(&ma->mca_timer))
				atomic_dec(&ma->mca_refcnt);
			ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
			spin_unlock(&ma->mca_lock);
			break;
		}
	}
	read_unlock(&idev->lock);
	in6_dev_put(idev);
	return 0;
}
示例#29
0
文件: addrconf.c 项目: hugh712/Jollen
void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
{
	BUG_TRAP(ifp->if_next==NULL);
	BUG_TRAP(ifp->lst_next==NULL);
#ifdef NET_REFCNT_DEBUG
	printk(KERN_DEBUG "inet6_ifa_finish_destroy\n");
#endif

	in6_dev_put(ifp->idev);

	if (del_timer(&ifp->timer))
		printk("Timer is still running, when freeing ifa=%p\n", ifp);

	if (!ifp->dead) {
		printk("Freeing alive inet6 address %p\n", ifp);
		return;
	}
	inet6_ifa_count--;
	kfree(ifp);
}
示例#30
0
static void ip6_frag_expire(unsigned long data)
{
	struct frag_queue *fq = (struct frag_queue *) data;
	struct net_device *dev;
	struct inet6_dev *idev;

	spin_lock(&fq->lock);

	if (fq->last_in & COMPLETE)
		goto out;

	fq_kill(fq);

	dev = dev_get_by_index(fq->iif);
	idev = dev ? in6_dev_get(dev) : NULL;

	IP6_INC_STATS_BH(idev,Ip6ReasmTimeout);
	IP6_INC_STATS_BH(idev,Ip6ReasmFails);

	/* Send error only if the first segment arrived. */
	if (fq->last_in&FIRST_IN && fq->fragments) {
		/*
		   But use as source device on which LAST ARRIVED
		   segment was received. And do not use fq->dev
		   pointer directly, device might already disappeared.
		 */
		if (dev) {
			fq->fragments->dev = dev;
			icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
				    dev);
		}
	}
	if (idev)
		in6_dev_put(idev);
	if (dev)
		dev_put(dev);
out:
	spin_unlock(&fq->lock);
	fq_put(fq);
}