⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcast.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
	spin_unlock(&ma->mca_lock);}int igmp6_event_query(struct sk_buff *skb){	struct ifmcaddr6 *ma;	struct in6_addr *addrp;	unsigned long resptime;	struct inet6_dev *idev;	struct icmp6hdr *hdr;	if (!pskb_may_pull(skb, sizeof(struct in6_addr)))		return -EINVAL;	hdr = (struct icmp6hdr*) skb->h.raw;	/* 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;}int igmp6_event_report(struct sk_buff *skb){	struct ifmcaddr6 *ma;	struct in6_addr *addrp;	struct inet6_dev *idev;	struct icmp6hdr *hdr;	/* Our own report looped back. Ignore it. */	if (skb->pkt_type == PACKET_LOOPBACK)		return 0;	if (!pskb_may_pull(skb, sizeof(struct in6_addr)))		return -EINVAL;	hdr = (struct icmp6hdr*) skb->h.raw;	/* 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;}void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type){	struct sock *sk = igmp6_socket->sk;        struct sk_buff *skb;        struct icmp6hdr *hdr;	struct in6_addr *snd_addr;	struct in6_addr *addrp;	struct in6_addr addr_buf;	struct in6_addr all_routers;	int err, len, payload_len, full_len;	u8 ra[8] = { IPPROTO_ICMPV6, 0,		     IPV6_TLV_ROUTERALERT, 2, 0, 0,		     IPV6_TLV_PADN, 0 };	snd_addr = addr;	if (type == ICMPV6_MGM_REDUCTION) {		snd_addr = &all_routers;		ipv6_addr_all_routers(&all_routers);	}	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);	payload_len = len + sizeof(ra);	full_len = sizeof(struct ipv6hdr) + payload_len;	skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 0, &err);	if (skb == NULL)		return;	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);	if (dev->hard_header) {		unsigned char ha[MAX_ADDR_LEN];		ndisc_mc_map(snd_addr, ha, dev, 1);		if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)			goto out;	}	if (ipv6_get_lladdr(dev, &addr_buf)) {#if MCAST_DEBUG >= 1		printk(KERN_DEBUG "igmp6: %s no linklocal address\n",		       dev->name);#endif		goto out;	}	ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);	memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));	hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr));	memset(hdr, 0, sizeof(struct icmp6hdr));	hdr->icmp6_type = type;	addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));	ipv6_addr_copy(addrp, addr);	hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,					   IPPROTO_ICMPV6,					   csum_partial((__u8 *) hdr, len, 0));	dev_queue_xmit(skb);	if (type == ICMPV6_MGM_REDUCTION)		ICMP6_INC_STATS(Icmp6OutGroupMembReductions);	else		ICMP6_INC_STATS(Icmp6OutGroupMembResponses);	ICMP6_INC_STATS(Icmp6OutMsgs);	return;out:	kfree_skb(skb);}static void igmp6_join_group(struct ifmcaddr6 *ma){	unsigned long delay;	int addr_type;	addr_type = ipv6_addr_type(&ma->mca_addr);	if ((addr_type & (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_LOOPBACK)))		return;	igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);	delay = net_random() % IGMP6_UNSOLICITED_IVAL;	spin_lock_bh(&ma->mca_lock);	if (del_timer(&ma->mca_timer)) {		atomic_dec(&ma->mca_refcnt);		delay = ma->mca_timer.expires - jiffies;	}	if (!mod_timer(&ma->mca_timer, jiffies + delay))		atomic_inc(&ma->mca_refcnt);	ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;	spin_unlock_bh(&ma->mca_lock);}static void igmp6_leave_group(struct ifmcaddr6 *ma){	int addr_type;	addr_type = ipv6_addr_type(&ma->mca_addr);	if ((addr_type & IPV6_ADDR_LINKLOCAL))		return;	if (ma->mca_flags & MAF_LAST_REPORTER)		igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REDUCTION);	spin_lock_bh(&ma->mca_lock);	if (del_timer(&ma->mca_timer))		atomic_dec(&ma->mca_refcnt);	spin_unlock_bh(&ma->mca_lock);}void igmp6_timer_handler(unsigned long data){	struct ifmcaddr6 *ma = (struct ifmcaddr6 *) data;	igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);	spin_lock(&ma->mca_lock);	ma->mca_flags |=  MAF_LAST_REPORTER;	ma->mca_flags &= ~MAF_TIMER_RUNNING;	spin_unlock(&ma->mca_lock);	ma_put(ma);}/* Device going down */void ipv6_mc_down(struct inet6_dev *idev){	struct ifmcaddr6 *i;	/* Withdraw multicast list */	read_lock_bh(&idev->lock);	for (i = idev->mc_list; i; i=i->next)		igmp6_group_dropped(i);	read_unlock_bh(&idev->lock);}/* Device going up */void ipv6_mc_up(struct inet6_dev *idev){	struct ifmcaddr6 *i;	/* Install multicast list, except for all-nodes (already installed) */	read_lock_bh(&idev->lock);	for (i = idev->mc_list; i; i=i->next)		igmp6_group_added(i);	read_unlock_bh(&idev->lock);}/* IPv6 device initialization. */void ipv6_mc_init_dev(struct inet6_dev *idev){	struct in6_addr maddr;	/* Add all-nodes address. */	ipv6_addr_all_nodes(&maddr);	ipv6_dev_mc_inc(idev->dev, &maddr);}/* *	Device is about to be destroyed: clean up. */void ipv6_mc_destroy_dev(struct inet6_dev *idev){	struct ifmcaddr6 *i;	struct in6_addr maddr;	/* Delete all-nodes address. */	ipv6_addr_all_nodes(&maddr);	ipv6_dev_mc_dec(idev->dev, &maddr);	write_lock_bh(&idev->lock);	while ((i = idev->mc_list) != NULL) {		idev->mc_list = i->next;		write_unlock_bh(&idev->lock);		igmp6_group_dropped(i);		ma_put(i);		write_lock_bh(&idev->lock);	}	write_unlock_bh(&idev->lock);}#ifdef CONFIG_PROC_FSstatic 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;}#endifint __init igmp6_init(struct net_proto_family *ops){	struct sock *sk;	int err;	igmp6_socket = sock_alloc();	if (igmp6_socket == NULL) {		printk(KERN_ERR		       "Failed to create the IGMP6 control socket.\n");		return -1;	}	igmp6_socket->inode->i_uid = 0;	igmp6_socket->inode->i_gid = 0;	igmp6_socket->type = SOCK_RAW;	if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) {		printk(KERN_DEBUG 		       "Failed to initialize the IGMP6 control socket (err %d).\n",		       err);		sock_release(igmp6_socket);		igmp6_socket = NULL; /* For safety. */		return err;	}	sk = igmp6_socket->sk;	sk->allocation = GFP_ATOMIC;	sk->prot->unhash(sk);	sk->net_pinfo.af_inet6.hop_limit = 1;#ifdef CONFIG_PROC_FS	create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);#endif	return 0;}void igmp6_cleanup(void){	sock_release(igmp6_socket);	igmp6_socket = NULL; /* for safety */#ifdef CONFIG_PROC_FS	remove_proc_entry("net/igmp6", 0);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -