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

📄 irlan_common.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/********************************************************************* * * Filename:      irlan_common.c * Version:       0.9 * Description:   IrDA LAN Access Protocol Implementation * Status:        Experimental. * Author:        Dag Brattli <dagb@cs.uit.no> * Created at:    Sun Aug 31 20:14:37 1997 * Modified at:   Sun Dec 26 21:53:10 1999 * Modified by:   Dag Brattli <dagb@cs.uit.no> * *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, *     All Rights Reserved. * *     This program is free software; you can redistribute it and/or *     modify it under the terms of the GNU General Public License as *     published by the Free Software Foundation; either version 2 of *     the License, or (at your option) any later version. * *     Neither Dag Brattli nor University of Tromsø admit liability nor *     provide warranty for any of this software. This material is *     provided "AS-IS" and at no charge. * ********************************************************************/#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/random.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/rtnetlink.h>#include <linux/moduleparam.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/byteorder.h>#include <net/irda/irda.h>#include <net/irda/irttp.h>#include <net/irda/irlmp.h>#include <net/irda/iriap.h>#include <net/irda/timer.h>#include <net/irda/irlan_common.h>#include <net/irda/irlan_client.h>#include <net/irda/irlan_provider.h>#include <net/irda/irlan_eth.h>#include <net/irda/irlan_filter.h>/* * Send gratuitous ARP when connected to a new AP or not. May be a clever * thing to do, but for some reason the machine crashes if you use DHCP. So * lets not use it by default. */#undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP/* extern char sysctl_devname[]; *//* *  Master structure */static LIST_HEAD(irlans);static void *ckey;static void *skey;/* Module parameters */static int eth;   /* Use "eth" or "irlan" name for devices */static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */#ifdef CONFIG_PROC_FSstatic const char *irlan_access[] = {	"UNKNOWN",	"DIRECT",	"PEER",	"HOSTED"};static const char *irlan_media[] = {	"UNKNOWN",	"802.3",	"802.5"};extern struct proc_dir_entry *proc_irda;static int irlan_seq_open(struct inode *inode, struct file *file);static const struct file_operations irlan_fops = {	.owner	 = THIS_MODULE,	.open    = irlan_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release,};extern struct proc_dir_entry *proc_irda;#endif /* CONFIG_PROC_FS */static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr);static void __irlan_close(struct irlan_cb *self);static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,				__u8 value_byte, __u16 value_short,				__u8 *value_array, __u16 value_len);static void irlan_open_unicast_addr(struct irlan_cb *self);static void irlan_get_unicast_addr(struct irlan_cb *self);void irlan_close_tsaps(struct irlan_cb *self);/* * Function irlan_init (void) * *    Initialize IrLAN layer * */static int __init irlan_init(void){	struct irlan_cb *new;	__u16 hints;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );#ifdef CONFIG_PROC_FS	{ struct proc_dir_entry *proc;	proc = create_proc_entry("irlan", 0, proc_irda);	if (!proc) {		printk(KERN_ERR "irlan_init: can't create /proc entry!\n");		return -ENODEV;	}	proc->proc_fops = &irlan_fops;	}#endif /* CONFIG_PROC_FS */	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	hints = irlmp_service_to_hint(S_LAN);	/* Register with IrLMP as a client */	ckey = irlmp_register_client(hints, &irlan_client_discovery_indication,				     NULL, NULL);	if (!ckey)		goto err_ckey;	/* Register with IrLMP as a service */	skey = irlmp_register_service(hints);	if (!skey)		goto err_skey;	/* Start the master IrLAN instance (the only one for now) */	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);	if (!new)		goto err_open;	/* The master will only open its (listen) control TSAP */	irlan_provider_open_ctrl_tsap(new);	/* Do some fast discovery! */	irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);	return 0;err_open:	irlmp_unregister_service(skey);err_skey:	irlmp_unregister_client(ckey);err_ckey:#ifdef CONFIG_PROC_FS	remove_proc_entry("irlan", proc_irda);#endif /* CONFIG_PROC_FS */	return -ENOMEM;}static void __exit irlan_cleanup(void){	struct irlan_cb *self, *next;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	irlmp_unregister_client(ckey);	irlmp_unregister_service(skey);#ifdef CONFIG_PROC_FS	remove_proc_entry("irlan", proc_irda);#endif /* CONFIG_PROC_FS */	/* Cleanup any leftover network devices */	rtnl_lock();	list_for_each_entry_safe(self, next, &irlans, dev_list) {		__irlan_close(self);	}	rtnl_unlock();}/* * Function irlan_open (void) * *    Open new instance of a client/provider, we should only register the *    network device if this instance is ment for a particular client/provider */static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr){	struct net_device *dev;	struct irlan_cb *self;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	/* Create network device with irlan */	dev = alloc_irlandev(eth ? "eth%d" : "irlan%d");	if (!dev)		return NULL;	self = dev->priv;	self->dev = dev;	/*	 *  Initialize local device structure	 */	self->magic = IRLAN_MAGIC;	self->saddr = saddr;	self->daddr = daddr;	/* Provider access can only be PEER, DIRECT, or HOSTED */	self->provider.access_type = access;	if (access == ACCESS_DIRECT) {		/*		 * Since we are emulating an IrLAN sever we will have to		 * give ourself an ethernet address!		 */		dev->dev_addr[0] = 0x40;		dev->dev_addr[1] = 0x00;		dev->dev_addr[2] = 0x00;		dev->dev_addr[3] = 0x00;		get_random_bytes(dev->dev_addr+4, 1);		get_random_bytes(dev->dev_addr+5, 1);	}	self->media = MEDIA_802_3;	self->disconnect_reason = LM_USER_REQUEST;	init_timer(&self->watchdog_timer);	init_timer(&self->client.kick_timer);	init_waitqueue_head(&self->open_wait);	skb_queue_head_init(&self->client.txq);	irlan_next_client_state(self, IRLAN_IDLE);	irlan_next_provider_state(self, IRLAN_IDLE);	if (register_netdev(dev)) {		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n",			   __FUNCTION__ );		self = NULL;		free_netdev(dev);	} else {		rtnl_lock();		list_add_rcu(&self->dev_list, &irlans);		rtnl_unlock();	}	return self;}/* * Function __irlan_close (self) * *    This function closes and deallocates the IrLAN client instances. Be *    aware that other functions which calls client_close() must *    remove self from irlans list first. */static void __irlan_close(struct irlan_cb *self){	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	ASSERT_RTNL();	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	del_timer_sync(&self->watchdog_timer);	del_timer_sync(&self->client.kick_timer);	/* Close all open connections and remove TSAPs */	irlan_close_tsaps(self);	if (self->client.iriap)		iriap_close(self->client.iriap);	/* Remove frames queued on the control channel */	skb_queue_purge(&self->client.txq);	/* Unregister and free self via destructor */	unregister_netdevice(self->dev);}/* Find any instance of irlan, used for client discovery wakeup */struct irlan_cb *irlan_get_any(void){	struct irlan_cb *self;	list_for_each_entry_rcu(self, &irlans, dev_list) {		return self;	}	return NULL;}/* * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb) * *    Here we receive the connect indication for the data channel * */static void irlan_connect_indication(void *instance, void *sap,				     struct qos_info *qos,				     __u32 max_sdu_size,				     __u8 max_header_size,				     struct sk_buff *skb){	struct irlan_cb *self;	struct tsap_cb *tsap;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	self = (struct irlan_cb *) instance;	tsap = (struct tsap_cb *) sap;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	IRDA_ASSERT(tsap == self->tsap_data,return;);	self->max_sdu_size = max_sdu_size;	self->max_header_size = max_header_size;	IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);	del_timer(&self->watchdog_timer);	/* If you want to pass the skb to *both* state machines, you will	 * need to skb_clone() it, so that you don't free it twice.	 * As the state machines don't need it, git rid of it here...	 * Jean II */	if (skb)		dev_kfree_skb(skb);	irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);	irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);	if (self->provider.access_type == ACCESS_PEER) {		/*		 * Data channel is open, so we are now allowed to		 * configure the remote filter		 */		irlan_get_unicast_addr(self);		irlan_open_unicast_addr(self);	}	/* Ready to transfer Ethernet frames (at last) */	netif_start_queue(self->dev); /* Clear reason */}static void irlan_connect_confirm(void *instance, void *sap,				  struct qos_info *qos,				  __u32 max_sdu_size,				  __u8 max_header_size,				  struct sk_buff *skb){	struct irlan_cb *self;	self = (struct irlan_cb *) instance;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	self->max_sdu_size = max_sdu_size;	self->max_header_size = max_header_size;	/* TODO: we could set the MTU depending on the max_sdu_size */	IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);	del_timer(&self->watchdog_timer);	/*	 * Data channel is open, so we are now allowed to configure the remote	 * filter	 */	irlan_get_unicast_addr(self);	irlan_open_unicast_addr(self);	/* Open broadcast and multicast filter by default */	irlan_set_broadcast_filter(self, TRUE);	irlan_set_multicast_filter(self, TRUE);	/* Ready to transfer Ethernet frames */	netif_start_queue(self->dev);	self->disconnect_reason = 0; /* Clear reason */#ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP	irlan_eth_send_gratuitous_arp(&self->dev);#endif	wake_up_interruptible(&self->open_wait);}/* * Function irlan_client_disconnect_indication (handle) * *    Callback function for the IrTTP layer. Indicates a disconnection of *    the specified connection (handle) */static void irlan_disconnect_indication(void *instance,					void *sap, LM_REASON reason,					struct sk_buff *userdata){	struct irlan_cb *self;	struct tsap_cb *tsap;

⌨️ 快捷键说明

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