📄 myigmp.c
字号:
if (reporter) myigmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE); goto done; } myigmpv3_add_delrec(in_dev, im); myigmp_ifc_event(in_dev); }done:#endif myip_mc_clear_src(im);}static void myigmp_group_added(struct ip_mc_list *im){ struct in_device *in_dev = im->interface; if( im->loaded == 0 ){ im->loaded = 1; myip_mc_filter_add(in_dev, im->multiaddr); }#ifdef CONFIG_IP_MULTICAST if (im->multiaddr == IGMP_ALL_HOSTS) return; if (in_dev->dead) return; if( MYIGMP_V1_SEEN(in_dev) || MYIGMP_V2_SEEN(in_dev) ){ spin_lock_bh(&im->lock); myigmp_start_timer(im, MYIGMP_Initial_Report_Delay); spin_unlock_bh(&im->lock); return; } im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; myigmp_ifc_event( in_dev );#endif}void myip_mc_inc_group(struct in_device *in_dev, u32 addr){ struct ip_mc_list *im; int i; ASSERT_RTNL(); for (im=in_dev->mc_list; im; im=im->next) { if (im->multiaddr == addr) { im->users++; i = myip_mc_add_src(in_dev, &addr, MCAST_EXCLUDE, 0, NULL, 0); goto out; } } im = kmalloc(sizeof(*im), GFP_KERNEL); if (!im) goto out; im->users=1; im->interface=in_dev; in_dev_hold(in_dev); im->multiaddr=addr; im->sfmode = MCAST_EXCLUDE; im->sfcount[MCAST_INCLUDE] = 0; im->sfcount[MCAST_EXCLUDE] = 1; im->sources = NULL; im->tomb = NULL; im->crcount = 0; atomic_set(&im->refcnt, 1); spin_lock_init(&im->lock);#ifdef CONFIG_IP_MULTICAST im->tm_running=0; init_timer(&im->timer); im->timer.data=(unsigned long)im; im->timer.function=&myigmp_timer_expire; im->unsolicit_count = MYIGMP_Unsolicited_Report_Count; im->reporter = 0; im->gsquery = 0;#endif im->loaded = 0; write_lock_bh(&in_dev->mc_list_lock); im->next=in_dev->mc_list; in_dev->mc_list=im; write_unlock_bh(&in_dev->mc_list_lock);#ifdef CONFIG_IP_MULTICAST myigmpv3_del_delrec(in_dev, im->multiaddr);#endif myigmp_group_added(im); if (!in_dev->dead) myip_rt_multicast_event(in_dev);out: return;}void myip_mc_dec_group(struct in_device *in_dev, u32 addr){ struct ip_mc_list *i, **ip; ASSERT_RTNL(); for( ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next ){ if (i->multiaddr==addr) { if (--i->users == 0) { write_lock_bh(&in_dev->mc_list_lock); *ip = i->next; write_unlock_bh(&in_dev->mc_list_lock); myigmp_group_dropped(i); if (!in_dev->dead) myip_rt_multicast_event(in_dev); myip_ma_put(i); return; } break; } }}void myip_mc_down(struct in_device *in_dev){}void myip_mc_up(struct in_device *in_dev){ struct ip_mc_list *i; ASSERT_RTNL(); myip_mc_inc_group(in_dev, IGMP_ALL_HOSTS); for (i=in_dev->mc_list; i; i=i->next) myigmp_group_added(i);}static void myigmp_ifc_timer_expire(unsigned long data){}static void myigmp_gq_timer_expire(unsigned long data){/* struct in_device *in_dev = (struct in_device *)data; in_dev->mr_gq_running = 0; igmpv3_send_report(in_dev, NULL); __in_dev_put(in_dev);*/}static struct in_device * myip_mc_find_dev(struct ip_mreqn *imr){ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = imr->imr_multiaddr.s_addr } } }; struct rtable *rt; struct net_device *dev = NULL; struct in_device *idev = NULL; if( imr->imr_ifindex ){ idev = inetdev_by_index(imr->imr_ifindex); if (idev) __in_dev_put(idev); return idev; } if( imr->imr_address.s_addr ){ dev = myip_dev_find(imr->imr_address.s_addr); if (!dev) return NULL; __dev_put(dev); } if( !dev && !myip_route_output_key(&rt, &fl) ){ dev = rt->u.dst.dev; ip_rt_put(rt); } if( dev ){ imr->imr_ifindex = dev->ifindex; idev = __in_dev_get_rtnl(dev); } return idev;}static int myip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode, int sfcount, __u32 *psfsrc, int delta){ struct ip_mc_list *pmc; int changerec = 0; int i, err; if (!in_dev) return -ENODEV; read_lock(&in_dev->mc_list_lock); for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) { if (*pmca == pmc->multiaddr) break; } if (!pmc) { read_unlock(&in_dev->mc_list_lock); return -ESRCH; } spin_lock_bh(&pmc->lock); read_unlock(&in_dev->mc_list_lock);#ifdef CONFIG_IP_MULTICAST mysf_markstate(pmc);#endif if (!delta) { err = -EINVAL; if (!pmc->sfcount[sfmode]) goto out_unlock; pmc->sfcount[sfmode]--; } err = 0; for (i=0; i<sfcount; i++) { int rv = myip_mc_del1_src(pmc, sfmode, &psfsrc[i]); changerec |= rv > 0; if (!err && rv < 0) err = rv; } if( pmc->sfmode == MCAST_EXCLUDE && pmc->sfcount[MCAST_EXCLUDE] == 0 && pmc->sfcount[MCAST_INCLUDE] ){#ifdef CONFIG_IP_MULTICAST struct ip_sf_list *psf;#endif pmc->sfmode = MCAST_INCLUDE;#ifdef CONFIG_IP_MULTICAST pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; in_dev->mr_ifc_count = pmc->crcount; for (psf=pmc->sources; psf; psf = psf->sf_next) psf->sf_crcount = 0; myigmp_ifc_event(pmc->interface); }else if( mysf_setstate(pmc) || changerec ){ myigmp_ifc_event(pmc->interface);#endif }out_unlock: spin_unlock_bh(&pmc->lock); return err;}static int myip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml, struct in_device *in_dev){ int err; if (iml->sflist == 0) { return myip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, iml->sfmode, 0, NULL, 0); } err = myip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, iml->sfmode, iml->sflist->sl_count, iml->sflist->sl_addr, 0); sock_kfree_s( sk, iml->sflist, IP_SFLSIZE(iml->sflist->sl_max) ); iml->sflist = NULL; return err;}int myip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr){ struct inet_sock *inet = inet_sk(sk); struct ip_mc_socklist *iml, **imlp; struct in_device *in_dev; u32 group = imr->imr_multiaddr.s_addr; u32 ifindex; rtnl_lock(); in_dev = myip_mc_find_dev(imr); if (!in_dev) { rtnl_unlock(); return -ENODEV; } ifindex = imr->imr_ifindex; for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { if (iml->multi.imr_multiaddr.s_addr == group && iml->multi.imr_ifindex == ifindex) { (void)myip_mc_leave_src(sk, iml, in_dev); *imlp = iml->next; myip_mc_dec_group(in_dev, group); rtnl_unlock(); sock_kfree_s(sk, iml, sizeof(*iml)); return 0; } } rtnl_unlock(); return -EADDRNOTAVAIL;}int myip_mc_join_group(struct sock *sk , struct ip_mreqn *imr){ int err; u32 addr = imr->imr_multiaddr.s_addr; struct ip_mc_socklist *iml=NULL, *i; struct in_device *in_dev; struct inet_sock *inet = inet_sk(sk); int ifindex; int count = 0; if (!MULTICAST(addr)) return -EINVAL; rtnl_shlock(); in_dev = myip_mc_find_dev(imr); if (!in_dev) { iml = NULL; err = -ENODEV; goto done; } err = -EADDRINUSE; ifindex = imr->imr_ifindex; for( i = inet->mc_list; i; i = i->next ){ if (i->multi.imr_multiaddr.s_addr == addr && i->multi.imr_ifindex == ifindex) goto done; count++; } err = -ENOBUFS; if (count >= sysctl_igmp_max_memberships) goto done; iml = sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL); if (iml == NULL) goto done; memcpy(&iml->multi, imr, sizeof(*imr)); iml->next = inet->mc_list; iml->sflist = NULL; iml->sfmode = MCAST_EXCLUDE; inet->mc_list = iml; myip_mc_inc_group(in_dev, addr); err = 0;done: rtnl_shunlock(); return err;}void myip_mc_init_dev(struct in_device *in_dev){ ASSERT_RTNL(); in_dev->mc_tomb = NULL;#ifdef CONFIG_IP_MULTICAST in_dev->mr_gq_running = 0; init_timer(&in_dev->mr_gq_timer); in_dev->mr_gq_timer.data=(unsigned long) in_dev; in_dev->mr_gq_timer.function=&myigmp_gq_timer_expire; in_dev->mr_ifc_count = 0; init_timer(&in_dev->mr_ifc_timer); in_dev->mr_ifc_timer.data=(unsigned long) in_dev; in_dev->mr_ifc_timer.function=&myigmp_ifc_timer_expire; in_dev->mr_qrv = MYIGMP_Unsolicited_Report_Count;#endif rwlock_init(&in_dev->mc_list_lock); spin_lock_init(&in_dev->mc_tomb_lock);}int myigmp_rcv(struct sk_buff *skb){ return 0;}void myip_mc_drop_socket(struct sock *sk){}static int myigmp_mc_seq_open(struct inode *inode, struct file *file){ return 0;}static struct file_operations myigmp_mc_seq_fops = { .owner = THIS_MODULE, .open = myigmp_mc_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release_private,};static int myigmp_mcf_seq_open(struct inode *inode, struct file *file){ return 0;}static struct file_operations myigmp_mcf_seq_fops = { .owner = THIS_MODULE, .open = myigmp_mcf_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release_private,};int __init myigmp_mc_proc_init(void){ proc_net_fops_create("myigmp", S_IRUGO, &myigmp_mc_seq_fops); proc_net_fops_create("mymcfilter", S_IRUGO, &myigmp_mcf_seq_fops); return 0;}void __exit myigmp_mc_proc_exit(void){ remove_proc_entry("myigmp", proc_net ); remove_proc_entry("mymcfilter", proc_net );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -