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

📄 ddp.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *	DDP:	An implementation of the AppleTalk DDP protocol for *		Ethernet 'ELAP'. * *		Alan Cox  <Alan.Cox@linux.org> * *		With more than a little assistance from * *		Wesley Craig <netatalk@umich.edu> * *	Fixes: *		Michael Callahan	:	Made routing work *		Wesley Craig		:	Fix probing to listen to a *						passed node id. *		Alan Cox		:	Added send/recvmsg support *		Alan Cox		:	Moved at. to protinfo in *						socket. *		Alan Cox		:	Added firewall hooks. *		Alan Cox		:	Supports new ARPHRD_LOOPBACK *		Christer Weinigel	: 	Routing and /proc fixes. *		Bradford Johnson	:	LocalTalk. *		Tom Dyas		:	Module support. *		Alan Cox		:	Hooks for PPP (based on the *						LocalTalk hook). *		Alan Cox		:	Posix bits *		Alan Cox/Mike Freeman	:	Possible fix to NBP problems *		Bradford Johnson	:	IP-over-DDP (experimental) *		Jay Schulist		:	Moved IP-over-DDP to its own *						driver file. (ipddp.c & ipddp.h) *		Jay Schulist		:	Made work as module with  *						AppleTalk drivers, cleaned it. *		Rob Newberry		:	Added proxy AARP and AARP *						procfs, moved probing to AARP *						module. *              Adrian Sun/  *              Michael Zuelsdorff      :       fix for net.0 packets. don't  *                                              allow illegal ether/tokentalk *                                              port assignment. we lose a  *                                              valid localtalk port as a  *                                              result. *		Arnaldo C. de Melo	:	Cleanup, in preparation for *						shared skb support 8) * *		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. *  */#include <linux/config.h>#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)#include <linux/module.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/bitops.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/in.h>#include <linux/errno.h>#include <linux/interrupt.h>#include <linux/if_ether.h>#include <linux/notifier.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/route.h>#include <linux/inet.h>#include <linux/etherdevice.h>#include <linux/if_arp.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/termios.h>	/* For TIOCOUTQ/INQ */#include <net/datalink.h>#include <net/p8022.h>#include <net/psnap.h>#include <net/sock.h>#include <linux/ip.h>#include <net/route.h>#include <linux/atalk.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/init.h>#ifdef CONFIG_PROC_FSextern void aarp_register_proc_fs(void);extern void aarp_unregister_proc_fs(void);#endifextern void aarp_cleanup_module(void);extern void aarp_probe_network(struct atalk_iface *atif);extern int  aarp_proxy_probe_network(struct atalk_iface *atif,					struct at_addr *sa);extern void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa);#undef APPLETALK_DEBUG#ifdef APPLETALK_DEBUG#define DPRINT(x)		print(x)#else#define DPRINT(x)#endif /* APPLETALK_DEBUG */#ifdef CONFIG_SYSCTLextern inline void atalk_register_sysctl(void);extern inline void atalk_unregister_sysctl(void);#endif /* CONFIG_SYSCTL */struct datalink_proto *ddp_dl, *aarp_dl;static struct proto_ops atalk_dgram_ops;/**************************************************************************\*                                                                          ** Handlers for the socket list.                                            **                                                                          *\**************************************************************************/static struct sock *atalk_sockets;static spinlock_t atalk_sockets_lock = SPIN_LOCK_UNLOCKED;extern inline void atalk_insert_socket(struct sock *sk){	spin_lock_bh(&atalk_sockets_lock);	sk->next = atalk_sockets;	if (sk->next)		atalk_sockets->pprev = &sk->next;	atalk_sockets = sk;	sk->pprev = &atalk_sockets;	spin_unlock_bh(&atalk_sockets_lock);}extern inline void atalk_remove_socket(struct sock *sk){	spin_lock_bh(&atalk_sockets_lock);	if (sk->pprev) {		if (sk->next)			sk->next->pprev = sk->pprev;		*sk->pprev = sk->next;		sk->pprev = NULL;	}	spin_unlock_bh(&atalk_sockets_lock);}static struct sock *atalk_search_socket(struct sockaddr_at *to,					struct atalk_iface *atif){	struct sock *s;	spin_lock_bh(&atalk_sockets_lock);	for (s = atalk_sockets; s; s = s->next) {		if (to->sat_port != s->protinfo.af_at.src_port)			continue;	    	if (to->sat_addr.s_net == ATADDR_ANYNET &&		    to->sat_addr.s_node == ATADDR_BCAST &&		    s->protinfo.af_at.src_net == atif->address.s_net)			break;	    	if (to->sat_addr.s_net == s->protinfo.af_at.src_net &&		    (to->sat_addr.s_node == s->protinfo.af_at.src_node ||		     to->sat_addr.s_node == ATADDR_BCAST ||		     to->sat_addr.s_node == ATADDR_ANYNODE))			break;	    	/* XXXX.0 -- we got a request for this router. make sure		 * that the node is appropriately set. */		if (to->sat_addr.s_node == ATADDR_ANYNODE &&		    to->sat_addr.s_net != ATADDR_ANYNET &&		    atif->address.s_node == s->protinfo.af_at.src_node) {			to->sat_addr.s_node = atif->address.s_node;			break; 		}	}	spin_unlock_bh(&atalk_sockets_lock);	return s;}/* * Try to find a socket matching ADDR in the socket list, * if found then return it.  If not, insert SK into the * socket list. * * This entire operation must execute atomically. */static struct sock *atalk_find_or_insert_socket(struct sock *sk,						struct sockaddr_at *sat){	struct sock *s;	spin_lock_bh(&atalk_sockets_lock);	for (s = atalk_sockets; s; s = s->next)		if (s->protinfo.af_at.src_net == sat->sat_addr.s_net &&		    s->protinfo.af_at.src_node == sat->sat_addr.s_node &&		    s->protinfo.af_at.src_port == sat->sat_port)			break;	if (!s) {		/* Wheee, it's free, assign and insert. */		sk->next = atalk_sockets;		if (sk->next)			atalk_sockets->pprev = &sk->next;		atalk_sockets = sk;		sk->pprev = &atalk_sockets;	}	spin_unlock_bh(&atalk_sockets_lock);	return s;}static void atalk_destroy_timer(unsigned long data){	struct sock *sk = (struct sock *) data;	if (!atomic_read(&sk->wmem_alloc) &&	    !atomic_read(&sk->rmem_alloc) && sk->dead) {		sock_put(sk);		MOD_DEC_USE_COUNT;	} else {		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;		add_timer(&sk->timer);	}}extern inline void atalk_destroy_socket(struct sock *sk){	atalk_remove_socket(sk);	skb_queue_purge(&sk->receive_queue);	if (!atomic_read(&sk->wmem_alloc) &&	    !atomic_read(&sk->rmem_alloc) && sk->dead) {		sock_put(sk);		MOD_DEC_USE_COUNT;	} else {		init_timer(&sk->timer);		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;		sk->timer.function = atalk_destroy_timer;		sk->timer.data = (unsigned long) sk;		add_timer(&sk->timer);	}}/* Called from proc fs */static int atalk_get_info(char *buffer, char **start, off_t offset, int length){	off_t pos = 0;	off_t begin = 0;	int len = sprintf(buffer, "Type local_addr  remote_addr tx_queue "				  "rx_queue st uid\n");	struct sock *s;	/* Output the AppleTalk data for the /proc filesystem */	spin_lock_bh(&atalk_sockets_lock);	for (s = atalk_sockets; s; s = s->next) {		len += sprintf(buffer + len,"%02X   ", s->type);		len += sprintf(buffer + len,"%04X:%02X:%02X  ",			       ntohs(s->protinfo.af_at.src_net),			       s->protinfo.af_at.src_node,			       s->protinfo.af_at.src_port);		len += sprintf(buffer + len,"%04X:%02X:%02X  ",			       ntohs(s->protinfo.af_at.dest_net),			       s->protinfo.af_at.dest_node,			       s->protinfo.af_at.dest_port);		len += sprintf(buffer + len,"%08X:%08X ",			       atomic_read(&s->wmem_alloc),			       atomic_read(&s->rmem_alloc));		len += sprintf(buffer + len,"%02X %d\n", s->state, 			       SOCK_INODE(s->socket)->i_uid);		/* Are we still dumping unwanted data then discard the record */		pos = begin + len;		if (pos < offset) {			len = 0;	/* Keep dumping into the buffer start */			begin = pos;		}		if (pos > offset + length)	/* We have dumped enough */			break;	}	spin_unlock_bh(&atalk_sockets_lock);	/* The data in question runs from begin to begin+len */	*start = buffer + offset - begin;	/* Start of wanted data */	len -= offset - begin;   /* Remove unwanted header data from length */	if (len > length)		len = length;	   /* Remove unwanted tail data from length */	return len;}/**************************************************************************\*                                                                          ** Routing tables for the AppleTalk socket layer.                           **                                                                          *\**************************************************************************//* Anti-deadlock ordering is router_lock --> iface_lock -DaveM */static struct atalk_route *atalk_router_list;static rwlock_t atalk_router_lock = RW_LOCK_UNLOCKED;static struct atalk_iface *atalk_iface_list;static spinlock_t atalk_iface_lock = SPIN_LOCK_UNLOCKED;/* For probing devices or in a routerless network */static struct atalk_route atrtr_default;/* AppleTalk interface control *//* * Drop a device. Doesn't drop any of its routes - that is the caller's * problem. Called when we down the interface or delete the address. */static void atif_drop_device(struct net_device *dev){	struct atalk_iface **iface = &atalk_iface_list;	struct atalk_iface *tmp;	spin_lock_bh(&atalk_iface_lock);	while ((tmp = *iface) != NULL) {		if (tmp->dev == dev) {			*iface = tmp->next;			kfree(tmp);			dev->atalk_ptr = NULL;			MOD_DEC_USE_COUNT;		} else			iface = &tmp->next;	}	spin_unlock_bh(&atalk_iface_lock);}static struct atalk_iface *atif_add_device(struct net_device *dev,					   struct at_addr *sa){	struct atalk_iface *iface = kmalloc(sizeof(*iface), GFP_KERNEL);	if (!iface)		return NULL;	iface->dev = dev;	dev->atalk_ptr = iface;	iface->address = *sa;	iface->status = 0;	spin_lock_bh(&atalk_iface_lock);	iface->next = atalk_iface_list;	atalk_iface_list = iface;	spin_unlock_bh(&atalk_iface_lock);	MOD_INC_USE_COUNT;	return iface;}/* Perform phase 2 AARP probing on our tentative address */static int atif_probe_device(struct atalk_iface *atif){	int netrange = ntohs(atif->nets.nr_lastnet) -			ntohs(atif->nets.nr_firstnet) + 1;	int probe_net = ntohs(atif->address.s_net);	int probe_node = atif->address.s_node;	int netct, nodect;	/* Offset the network we start probing with */	if (probe_net == ATADDR_ANYNET) {		probe_net = ntohs(atif->nets.nr_firstnet);		if (netrange)			probe_net += jiffies % netrange;	}	if (probe_node == ATADDR_ANYNODE)		probe_node = jiffies & 0xFF;	/* Scan the networks */	atif->status |= ATIF_PROBE;	for (netct = 0; netct <= netrange; netct++) {		/* Sweep the available nodes from a given start */		atif->address.s_net = htons(probe_net);		for (nodect = 0; nodect < 256; nodect++) {			atif->address.s_node = ((nodect+probe_node) & 0xFF);			if (atif->address.s_node > 0 &&			    atif->address.s_node < 254) {				/* Probe a proposed address */				aarp_probe_network(atif);				if (!(atif->status & ATIF_PROBE_FAIL)) {					atif->status &= ~ATIF_PROBE;					return 0;				}			}			atif->status &= ~ATIF_PROBE_FAIL;		}		probe_net++;		if (probe_net > ntohs(atif->nets.nr_lastnet))			probe_net = ntohs(atif->nets.nr_firstnet);	}	atif->status &= ~ATIF_PROBE;	return -EADDRINUSE;	/* Network is full... */}/* Perform AARP probing for a proxy address */static int atif_proxy_probe_device(struct atalk_iface *atif,				   struct at_addr* proxy_addr){	int netrange = ntohs(atif->nets.nr_lastnet) -			ntohs(atif->nets.nr_firstnet) + 1;	/* we probe the interface's network */	int probe_net = ntohs(atif->address.s_net);	int probe_node = ATADDR_ANYNODE;	    /* we'll take anything */	int netct, nodect;	/* Offset the network we start probing with */	if (probe_net == ATADDR_ANYNET) {		probe_net = ntohs(atif->nets.nr_firstnet);		if (netrange)			probe_net += jiffies % netrange;	}	if (probe_node == ATADDR_ANYNODE)		probe_node = jiffies & 0xFF;			/* Scan the networks */	for (netct = 0; netct <= netrange; netct++) {		/* Sweep the available nodes from a given start */		proxy_addr->s_net = htons(probe_net);		for (nodect = 0; nodect < 256; nodect++) {			proxy_addr->s_node = ((nodect + probe_node) & 0xFF);			if (proxy_addr->s_node > 0 &&			    proxy_addr->s_node < 254) {				/* Tell AARP to probe a proposed address */				int ret = aarp_proxy_probe_network(atif,								    proxy_addr);				if (ret != -EADDRINUSE)					return ret;			}		}		probe_net++;		if (probe_net > ntohs(atif->nets.nr_lastnet))			probe_net = ntohs(atif->nets.nr_firstnet);	}	return -EADDRINUSE;	/* Network is full... */}struct at_addr *atalk_find_dev_addr(struct net_device *dev){	struct atalk_iface *iface = dev->atalk_ptr;	return iface ? &iface->address : NULL;}static struct at_addr *atalk_find_primary(void){	struct atalk_iface *fiface = NULL;	struct at_addr *retval;	struct atalk_iface *iface;	/*	 * Return a point-to-point interface only if	 * there is no non-ptp interface available.	 */	spin_lock_bh(&atalk_iface_lock);	for (iface = atalk_iface_list; iface; iface = iface->next) {		if (!fiface && !(iface->dev->flags & IFF_LOOPBACK))			fiface = iface;		if (!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {			retval = &iface->address;			goto out;		}	}	if (fiface)		retval = &fiface->address;	else if (atalk_iface_list)		retval = &atalk_iface_list->address;	else		retval = NULL;out:	spin_unlock_bh(&atalk_iface_lock);	return retval;}/* * Find a match for 'any network' - ie any of our interfaces with that * node number will do just nicely. */static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev){	struct atalk_iface *iface = dev->atalk_ptr;	if (!iface || iface->status & ATIF_PROBE)		return NULL;	if (node == ATADDR_BCAST ||	    iface->address.s_node == node ||	    node == ATADDR_ANYNODE)		return iface;	return NULL;}/* Find a match for a specific network:node pair */static struct atalk_iface *atalk_find_interface(int net, int node){	struct atalk_iface *iface;

⌨️ 快捷键说明

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