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

📄 br2684.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (unlikely(skb == NULL)) {		/* skb==NULL means VCC is being destroyed */		br2684_close_vcc(brvcc);		if (list_empty(&brdev->brvccs)) {			read_lock(&devs_lock);			list_del(&brdev->br2684_devs);			read_unlock(&devs_lock);			unregister_netdev(net_dev);			free_netdev(net_dev);		}		return;	}	skb_debug(skb);	atm_return(atmvcc, skb->truesize);	DPRINTK("skb from brdev %p\n", brdev);	if (brvcc->encaps == e_llc) {		/* let us waste some time for checking the encapsulation.		   Note, that only 7 char is checked so frames with a valid FCS		   are also accepted (but FCS is not checked of course) */		if (memcmp(skb->data, llc_oui_pid_pad, 7)) {			brdev->stats.rx_errors++;			dev_kfree_skb(skb);			return;		}		/* Strip FCS if present */		if (skb->len > 7 && skb->data[7] == 0x01)			__skb_trim(skb, skb->len - 4);	} else {		plen = PADLEN + ETH_HLEN;	/* pad, dstmac,srcmac, ethtype */		/* first 2 chars should be 0 */		if (*((u16 *) (skb->data)) != 0) {			brdev->stats.rx_errors++;			dev_kfree_skb(skb);			return;		}	}	if (skb->len < plen) {		brdev->stats.rx_errors++;		dev_kfree_skb(skb);	/* dev_ not needed? */		return;	}#ifdef FASTER_VERSION	/* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,	   than should be. What else should I set? */	skb_pull(skb, plen);	skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;	skb->pkt_type = PACKET_HOST;#ifdef CONFIG_BR2684_FAST_TRANS	skb->protocol = ((u16 *) skb->data)[-1];#else				/* some protocols might require this: */	skb->protocol = br_type_trans(skb, net_dev);#endif /* CONFIG_BR2684_FAST_TRANS */#else	skb_pull(skb, plen - ETH_HLEN);	skb->protocol = eth_type_trans(skb, net_dev);#endif /* FASTER_VERSION */#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 ? */	DPRINTK("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_head copy;	struct sk_buff *skb;	struct br2684_dev *brdev;	struct net_device *net_dev;	struct atm_backend_br2684 be;	if (copy_from_user(&be, arg, sizeof be))		return -EFAULT;	brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);	if (!brvcc)		return -ENOMEM;	memset(brvcc, 0, sizeof(struct br2684_vcc));	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;	}	DPRINTK("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;	skb_queue_head_init(&copy);	skb_migrate(&atmvcc->sk->sk_receive_queue, &copy);	while ((skb = skb_dequeue(&copy)) != NULL) {		BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;		BRPRIV(skb->dev)->stats.rx_packets--;		br2684_push(atmvcc, skb);	}	__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;#ifdef FASTER_VERSION	my_eth_header = netdev->hard_header;	netdev->hard_header = br2684_header;	my_eth_header_cache = netdev->hard_header_cache;	netdev->hard_header_cache = br2684_header_cache;	netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN;	/* 10 + 14 */#endif	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;	DPRINTK("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);	DPRINTK("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){	loff_t offs = 0;	struct br2684_dev *brd;	read_lock(&devs_lock);	list_for_each_entry(brd, &br2684_devs, br2684_devs) {		if (offs == *pos)			return brd;		++offs;	}	return NULL;}static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct br2684_dev *brd = v;	++*pos;	brd = list_entry(brd->br2684_devs.next, 			 struct br2684_dev, br2684_devs);	return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;}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 = v;	const struct net_device *net_dev = brdev->net_dev;	const struct br2684_vcc *brvcc;	seq_printf(seq, "dev %.16s: num=%d, mac=%02X:%02X:"		       "%02X:%02X:%02X:%02X (%s)\n", net_dev->name,		       brdev->number,		       net_dev->dev_addr[0],		       net_dev->dev_addr[1],		       net_dev->dev_addr[2],		       net_dev->dev_addr[3],		       net_dev->dev_addr[4],		       net_dev->dev_addr[5],		       brdev->mac_was_set ? "set" : "auto");	list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {		seq_printf(seq, "  vcc %d.%d.%d: encaps=%s"#ifndef FASTER_VERSION				    ", failed copies %u/%u"#endif /* FASTER_VERSION */				    "\n", brvcc->atmvcc->dev->number,				    brvcc->atmvcc->vpi, brvcc->atmvcc->vci,				    (brvcc->encaps == e_llc) ? "LLC" : "VC"#ifndef FASTER_VERSION				    , brvcc->copies_failed				    , brvcc->copies_needed#endif /* FASTER_VERSION */				    );#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 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 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 + -