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

📄 br2684.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	}	skb_pull(skb, plen - ETH_HLEN);	skb->protocol = eth_type_trans(skb, net_dev);#ifdef CONFIG_ATM_BR2684_IPFILTER	if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {		brdev->stats.rx_dropped++;		dev_kfree_skb(skb);		return;	}#endif /* CONFIG_ATM_BR2684_IPFILTER */	skb->dev = net_dev;	ATM_SKB(skb)->vcc = atmvcc;	/* needed ? */	pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol));	skb_debug(skb);	if (unlikely(!(net_dev->flags & IFF_UP))) {		/* sigh, interface is down */		brdev->stats.rx_dropped++;		dev_kfree_skb(skb);		return;	}	brdev->stats.rx_packets++;	brdev->stats.rx_bytes += skb->len;	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));	netif_rx(skb);}static int br2684_regvcc(struct atm_vcc *atmvcc, void __user *arg){/* assign a vcc to a devNote: we do not have explicit unassign, but look at _push()*/	int err;	struct br2684_vcc *brvcc;	struct sk_buff *skb;	struct sk_buff_head *rq;	struct br2684_dev *brdev;	struct net_device *net_dev;	struct atm_backend_br2684 be;	unsigned long flags;	if (copy_from_user(&be, arg, sizeof be))		return -EFAULT;	brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);	if (!brvcc)		return -ENOMEM;	write_lock_irq(&devs_lock);	net_dev = br2684_find_dev(&be.ifspec);	if (net_dev == NULL) {		printk(KERN_ERR		    "br2684: tried to attach to non-existant device\n");		err = -ENXIO;		goto error;	}	brdev = BRPRIV(net_dev);	if (atmvcc->push == NULL) {		err = -EBADFD;		goto error;	}	if (!list_empty(&brdev->brvccs)) {		/* Only 1 VCC/dev right now */		err = -EEXIST;		goto error;	}	if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||	    be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=	    BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||	    be.min_size != 0) {		err = -EINVAL;		goto error;	}	pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,		brvcc);	if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {		unsigned char *esi = atmvcc->dev->esi;		if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])			memcpy(net_dev->dev_addr, esi, net_dev->addr_len);		else			net_dev->dev_addr[2] = 1;	}	list_add(&brvcc->brvccs, &brdev->brvccs);	write_unlock_irq(&devs_lock);	brvcc->device = net_dev;	brvcc->atmvcc = atmvcc;	atmvcc->user_back = brvcc;	brvcc->encaps = (enum br2684_encaps) be.encaps;	brvcc->old_push = atmvcc->push;	barrier();	atmvcc->push = br2684_push;	rq = &sk_atm(atmvcc)->sk_receive_queue;	spin_lock_irqsave(&rq->lock, flags);	if (skb_queue_empty(rq)) {		skb = NULL;	} else {		/* NULL terminate the list.  */		rq->prev->next = NULL;		skb = rq->next;	}	rq->prev = rq->next = (struct sk_buff *)rq;	rq->qlen = 0;	spin_unlock_irqrestore(&rq->lock, flags);	while (skb) {		struct sk_buff *next = skb->next;		skb->next = skb->prev = NULL;		BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;		BRPRIV(skb->dev)->stats.rx_packets--;		br2684_push(atmvcc, skb);		skb = next;	}	__module_get(THIS_MODULE);	return 0;    error:	write_unlock_irq(&devs_lock);	kfree(brvcc);	return err;}static void br2684_setup(struct net_device *netdev){	struct br2684_dev *brdev = BRPRIV(netdev);	ether_setup(netdev);	brdev->net_dev = netdev;	my_eth_mac_addr = netdev->set_mac_address;	netdev->set_mac_address = br2684_mac_addr;	netdev->hard_start_xmit = br2684_start_xmit;	netdev->get_stats = br2684_get_stats;	INIT_LIST_HEAD(&brdev->brvccs);}static int br2684_create(void __user *arg){	int err;	struct net_device *netdev;	struct br2684_dev *brdev;	struct atm_newif_br2684 ni;	pr_debug("br2684_create\n");	if (copy_from_user(&ni, arg, sizeof ni)) {		return -EFAULT;	}	if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {		return -EINVAL;	}	netdev = alloc_netdev(sizeof(struct br2684_dev),			      ni.ifname[0] ? ni.ifname : "nas%d",			      br2684_setup);	if (!netdev)		return -ENOMEM;	brdev = BRPRIV(netdev);	pr_debug("registered netdev %s\n", netdev->name);	/* open, stop, do_ioctl ? */	err = register_netdev(netdev);	if (err < 0) {		printk(KERN_ERR "br2684_create: register_netdev failed\n");		free_netdev(netdev);		return err;	}	write_lock_irq(&devs_lock);	brdev->number = list_empty(&br2684_devs) ? 1 :	    BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;	list_add_tail(&brdev->br2684_devs, &br2684_devs);	write_unlock_irq(&devs_lock);	return 0;}/* * This handles ioctls actually performed on our vcc - we must return * -ENOIOCTLCMD for any unrecognized ioctl */static int br2684_ioctl(struct socket *sock, unsigned int cmd,	unsigned long arg){	struct atm_vcc *atmvcc = ATM_SD(sock);	void __user *argp = (void __user *)arg;	int err;	switch(cmd) {	case ATM_SETBACKEND:	case ATM_NEWBACKENDIF: {		atm_backend_t b;		err = get_user(b, (atm_backend_t __user *) argp);		if (err)			return -EFAULT;		if (b != ATM_BACKEND_BR2684)			return -ENOIOCTLCMD;		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (cmd == ATM_SETBACKEND)			return br2684_regvcc(atmvcc, argp);		else			return br2684_create(argp);		}#ifdef CONFIG_ATM_BR2684_IPFILTER	case BR2684_SETFILT:		if (atmvcc->push != br2684_push)			return -ENOIOCTLCMD;		if (!capable(CAP_NET_ADMIN))			return -EPERM;		err = br2684_setfilt(atmvcc, argp);		return err;#endif /* CONFIG_ATM_BR2684_IPFILTER */	}	return -ENOIOCTLCMD;}static struct atm_ioctl br2684_ioctl_ops = {	.owner	= THIS_MODULE,	.ioctl	= br2684_ioctl,};#ifdef CONFIG_PROC_FSstatic void *br2684_seq_start(struct seq_file *seq, loff_t *pos){	read_lock(&devs_lock);	return seq_list_start(&br2684_devs, *pos);}static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos){	return seq_list_next(v, &br2684_devs, pos);}static void br2684_seq_stop(struct seq_file *seq, void *v){	read_unlock(&devs_lock);}static int br2684_seq_show(struct seq_file *seq, void *v){	const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,			br2684_devs);	const struct net_device *net_dev = brdev->net_dev;	const struct br2684_vcc *brvcc;	DECLARE_MAC_BUF(mac);	seq_printf(seq, "dev %.16s: num=%d, mac=%s (%s)\n",		   net_dev->name,		   brdev->number,		   print_mac(mac, net_dev->dev_addr),		   brdev->mac_was_set ? "set" : "auto");	list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {		seq_printf(seq, "  vcc %d.%d.%d: encaps=%s"				    ", failed copies %u/%u"				    "\n", brvcc->atmvcc->dev->number,				    brvcc->atmvcc->vpi, brvcc->atmvcc->vci,				    (brvcc->encaps == e_llc) ? "LLC" : "VC"				    , brvcc->copies_failed				    , brvcc->copies_needed				    );#ifdef CONFIG_ATM_BR2684_IPFILTER#define b1(var, byte)	((u8 *) &brvcc->filter.var)[byte]#define bs(var)		b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)			if (brvcc->filter.netmask != 0)				seq_printf(seq, "    filter=%d.%d.%d.%d/"						"%d.%d.%d.%d\n",						bs(prefix), bs(netmask));#undef bs#undef b1#endif /* CONFIG_ATM_BR2684_IPFILTER */	}	return 0;}static const struct seq_operations br2684_seq_ops = {	.start = br2684_seq_start,	.next  = br2684_seq_next,	.stop  = br2684_seq_stop,	.show  = br2684_seq_show,};static int br2684_proc_open(struct inode *inode, struct file *file){	return seq_open(file, &br2684_seq_ops);}static const struct file_operations br2684_proc_ops = {	.owner   = THIS_MODULE,	.open    = br2684_proc_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release,};extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */#endifstatic int __init br2684_init(void){#ifdef CONFIG_PROC_FS	struct proc_dir_entry *p;	if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)		return -ENOMEM;	p->proc_fops = &br2684_proc_ops;#endif	register_atm_ioctl(&br2684_ioctl_ops);	return 0;}static void __exit br2684_exit(void){	struct net_device *net_dev;	struct br2684_dev *brdev;	struct br2684_vcc *brvcc;	deregister_atm_ioctl(&br2684_ioctl_ops);#ifdef CONFIG_PROC_FS	remove_proc_entry("br2684", atm_proc_root);#endif	while (!list_empty(&br2684_devs)) {		net_dev = list_entry_brdev(br2684_devs.next);		brdev = BRPRIV(net_dev);		while (!list_empty(&brdev->brvccs)) {			brvcc = list_entry_brvcc(brdev->brvccs.next);			br2684_close_vcc(brvcc);		}		list_del(&brdev->br2684_devs);		unregister_netdev(net_dev);		free_netdev(net_dev);	}}module_init(br2684_init);module_exit(br2684_exit);MODULE_AUTHOR("Marcell GAL");MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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