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

📄 lec.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		"ESI_FORWARD_DIRECT"	};	if (status > ESI_FORWARD_DIRECT)		status = 3;	/* ESI_UNDEFINED */	return lec_arp_status_string[status];}static void lec_info(struct seq_file *seq, struct lec_arp_table *entry){	int i;	for (i = 0; i < ETH_ALEN; i++)		seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff);	seq_printf(seq, " ");	for (i = 0; i < ATM_ESA_LEN; i++)		seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff);	seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status),		   entry->flags & 0xffff);	if (entry->vcc)		seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);	else		seq_printf(seq, "        ");	if (entry->recv_vcc) {		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,			   entry->recv_vcc->vci);	}	seq_putc(seq, '\n');}struct lec_state {	unsigned long flags;	struct lec_priv *locked;	struct hlist_node *node;	struct net_device *dev;	int itf;	int arp_table;	int misc_table;};static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,			  loff_t *l){	struct hlist_node *e = state->node;	struct lec_arp_table *tmp;	if (!e)		e = tbl->first;	if (e == (void *)1) {		e = tbl->first;		--*l;	}	hlist_for_each_entry_from(tmp, e, next) {		if (--*l < 0)			break;	}	state->node = e;	return (*l < 0) ? state : NULL;}static void *lec_arp_walk(struct lec_state *state, loff_t *l,			  struct lec_priv *priv){	void *v = NULL;	int p;	for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {		v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);		if (v)			break;	}	state->arp_table = p;	return v;}static void *lec_misc_walk(struct lec_state *state, loff_t *l,			   struct lec_priv *priv){	struct hlist_head *lec_misc_tables[] = {		&priv->lec_arp_empty_ones,		&priv->lec_no_forward,		&priv->mcast_fwds	};	void *v = NULL;	int q;	for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {		v = lec_tbl_walk(state, lec_misc_tables[q], l);		if (v)			break;	}	state->misc_table = q;	return v;}static void *lec_priv_walk(struct lec_state *state, loff_t *l,			   struct lec_priv *priv){	if (!state->locked) {		state->locked = priv;		spin_lock_irqsave(&priv->lec_arp_lock, state->flags);	}	if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {		spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);		state->locked = NULL;		/* Partial state reset for the next time we get called */		state->arp_table = state->misc_table = 0;	}	return state->locked;}static void *lec_itf_walk(struct lec_state *state, loff_t *l){	struct net_device *dev;	void *v;	dev = state->dev ? state->dev : dev_lec[state->itf];	v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL;	if (!v && dev) {		dev_put(dev);		/* Partial state reset for the next time we get called */		dev = NULL;	}	state->dev = dev;	return v;}static void *lec_get_idx(struct lec_state *state, loff_t l){	void *v = NULL;	for (; state->itf < MAX_LEC_ITF; state->itf++) {		v = lec_itf_walk(state, &l);		if (v)			break;	}	return v;}static void *lec_seq_start(struct seq_file *seq, loff_t *pos){	struct lec_state *state = seq->private;	state->itf = 0;	state->dev = NULL;	state->locked = NULL;	state->arp_table = 0;	state->misc_table = 0;	state->node = (void *)1;	return *pos ? lec_get_idx(state, *pos) : (void *)1;}static void lec_seq_stop(struct seq_file *seq, void *v){	struct lec_state *state = seq->private;	if (state->dev) {		spin_unlock_irqrestore(&state->locked->lec_arp_lock,				       state->flags);		dev_put(state->dev);	}}static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct lec_state *state = seq->private;	v = lec_get_idx(state, 1);	*pos += !!PTR_ERR(v);	return v;}static int lec_seq_show(struct seq_file *seq, void *v){	static char lec_banner[] = "Itf  MAC          ATM destination"	    "                          Status            Flags "	    "VPI/VCI Recv VPI/VCI\n";	if (v == (void *)1)		seq_puts(seq, lec_banner);	else {		struct lec_state *state = seq->private;		struct net_device *dev = state->dev;		struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);		seq_printf(seq, "%s ", dev->name);		lec_info(seq, entry);	}	return 0;}static const struct seq_operations lec_seq_ops = {	.start = lec_seq_start,	.next = lec_seq_next,	.stop = lec_seq_stop,	.show = lec_seq_show,};static int lec_seq_open(struct inode *inode, struct file *file){	struct lec_state *state;	struct seq_file *seq;	int rc = -EAGAIN;	state = kmalloc(sizeof(*state), GFP_KERNEL);	if (!state) {		rc = -ENOMEM;		goto out;	}	rc = seq_open(file, &lec_seq_ops);	if (rc)		goto out_kfree;	seq = file->private_data;	seq->private = state;out:	return rc;out_kfree:	kfree(state);	goto out;}static int lec_seq_release(struct inode *inode, struct file *file){	return seq_release_private(inode, file);}static const struct file_operations lec_seq_fops = {	.owner = THIS_MODULE,	.open = lec_seq_open,	.read = seq_read,	.llseek = seq_lseek,	.release = lec_seq_release,};#endifstatic int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct atm_vcc *vcc = ATM_SD(sock);	int err = 0;	switch (cmd) {	case ATMLEC_CTRL:	case ATMLEC_MCAST:	case ATMLEC_DATA:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		break;	default:		return -ENOIOCTLCMD;	}	switch (cmd) {	case ATMLEC_CTRL:		err = lecd_attach(vcc, (int)arg);		if (err >= 0)			sock->state = SS_CONNECTED;		break;	case ATMLEC_MCAST:		err = lec_mcast_attach(vcc, (int)arg);		break;	case ATMLEC_DATA:		err = lec_vcc_attach(vcc, (void __user *)arg);		break;	}	return err;}static struct atm_ioctl lane_ioctl_ops = {	.owner = THIS_MODULE,	.ioctl = lane_ioctl,};static int __init lane_module_init(void){#ifdef CONFIG_PROC_FS	struct proc_dir_entry *p;	p = create_proc_entry("lec", S_IRUGO, atm_proc_root);	if (p)		p->proc_fops = &lec_seq_fops;#endif	register_atm_ioctl(&lane_ioctl_ops);	printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");	return 0;}static void __exit lane_module_cleanup(void){	int i;	struct lec_priv *priv;	remove_proc_entry("lec", atm_proc_root);	deregister_atm_ioctl(&lane_ioctl_ops);	for (i = 0; i < MAX_LEC_ITF; i++) {		if (dev_lec[i] != NULL) {			priv = (struct lec_priv *)dev_lec[i]->priv;			unregister_netdev(dev_lec[i]);			free_netdev(dev_lec[i]);			dev_lec[i] = NULL;		}	}	return;}module_init(lane_module_init);module_exit(lane_module_cleanup);/* * LANE2: 3.1.3, LE_RESOLVE.request * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs. * If sizeoftlvs == NULL the default TLVs associated with with this * lec will be used. * If dst_mac == NULL, targetless LE_ARP will be sent */static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,			 u8 **tlvs, u32 *sizeoftlvs){	unsigned long flags;	struct lec_priv *priv = (struct lec_priv *)dev->priv;	struct lec_arp_table *table;	struct sk_buff *skb;	int retval;	if (force == 0) {		spin_lock_irqsave(&priv->lec_arp_lock, flags);		table = lec_arp_find(priv, dst_mac);		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);		if (table == NULL)			return -1;		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);		if (*tlvs == NULL)			return -1;		*sizeoftlvs = table->sizeoftlvs;		return 0;	}	if (sizeoftlvs == NULL)		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);	else {		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);		if (skb == NULL)			return -1;		skb->len = *sizeoftlvs;		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);	}	return retval;}/* * LANE2: 3.1.4, LE_ASSOCIATE.request * Associate the *tlvs with the *lan_dst address. * Will overwrite any previous association * Returns 1 for success, 0 for failure (out of memory) * */static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,			       u8 *tlvs, u32 sizeoftlvs){	int retval;	struct sk_buff *skb;	struct lec_priv *priv = (struct lec_priv *)dev->priv;	if (compare_ether_addr(lan_dst, dev->dev_addr))		return (0);	/* not our mac address */	kfree(priv->tlvs);	/* NULL if there was no previous association */	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);	if (priv->tlvs == NULL)		return (0);	priv->sizeoftlvs = sizeoftlvs;	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);	if (skb == NULL)		return 0;	skb->len = sizeoftlvs;	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);	retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);	if (retval != 0)		printk("lec.c: lane2_associate_req() failed\n");	/*	 * If the previous association has changed we must	 * somehow notify other LANE entities about the change	 */	return (1);}/* * LANE2: 3.1.5, LE_ASSOCIATE.indication * */static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,				u8 *tlvs, u32 sizeoftlvs){#if 0	int i = 0;#endif	struct lec_priv *priv = (struct lec_priv *)dev->priv;#if 0				/*				 * Why have the TLVs in LE_ARP entries				 * since we do not use them? When you				 * uncomment this code, make sure the				 * TLVs get freed when entry is killed				 */	struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);	if (entry == NULL)		return;		/* should not happen */	kfree(entry->tlvs);	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);	if (entry->tlvs == NULL)		return;	entry->sizeoftlvs = sizeoftlvs;#endif#if 0	printk("lec.c: lane2_associate_ind()\n");	printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);	while (i < sizeoftlvs)		printk("%02x ", tlvs[i++]);	printk("\n");#endif	/* tell MPOA about the TLVs we saw */	if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {		priv->lane2_ops->associate_indicator(dev, mac_addr,						     tlvs, sizeoftlvs);	}	return;}/* * Here starts what used to lec_arpc.c * * lec_arpc.c was added here when making * lane client modular. October 1997 */#include <linux/types.h>#include <linux/timer.h>#include <asm/param.h>#include <asm/atomic.h>#include <linux/inetdevice.h>#include <net/route.h>#if 0#define pr_debug(format,args...)/*#define pr_debug printk*/#endif#define DEBUG_ARP_TABLE 0#define LEC_ARP_REFRESH_INTERVAL (3*HZ)static void lec_arp_check_expire(struct work_struct *work);static void lec_arp_expire_arp(unsigned long data);/* * Arp table funcs */#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))/* * Initialization of arp-cache */

⌨️ 快捷键说明

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