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

📄 af_ipx.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
		memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,			IPX_NODE_LEN);		ret = -EADDRINUSE;		if (ipxitf_find_socket(intrfc, addr->sipx_port)) {			SOCK_DEBUG(sk,				"IPX: bind failed because port %X in use.\n",				ntohs((int)addr->sipx_port));			goto out_put;		}	}#else	/* !def CONFIG_IPX_INTERN */	/* Source addresses are easy. It must be our network:node pair for	   an interface routed to IPX with the ipx routing ioctl() */	ret = -EADDRINUSE;	if (ipxitf_find_socket(intrfc, addr->sipx_port)) {		SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",				ntohs((int)addr->sipx_port));		goto out_put;	}#endif	/* CONFIG_IPX_INTERN */	ipxitf_insert_socket(intrfc, sk);	sk->zapped = 0;	SOCK_DEBUG(sk, "IPX: bound socket 0x%04X.\n", ntohs(addr->sipx_port) );	ret = 0;out_put:	ipxitf_put(intrfc);out:	return ret;}static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,	int addr_len, int flags){	struct sock *sk = sock->sk;	struct sockaddr_ipx *addr;	int ret = -EINVAL;	ipx_route *rt;	sk->state	= TCP_CLOSE;	sock->state 	= SS_UNCONNECTED;	if (addr_len != sizeof(*addr))		goto out;	addr = (struct sockaddr_ipx *)uaddr;	/* put the autobinding in */	if (!sk->protinfo.af_ipx.port) {		struct sockaddr_ipx uaddr;		uaddr.sipx_port		= 0;		uaddr.sipx_network 	= 0;#ifdef CONFIG_IPX_INTERN		ret = -ENETDOWN;		if (!sk->protinfo.af_ipx.intrfc)			goto out; /* Someone zonked the iface */		memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,			IPX_NODE_LEN);#endif	/* CONFIG_IPX_INTERN */		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,				sizeof(struct sockaddr_ipx));		if (ret)			goto out;	}        /* We can either connect to primary network or somewhere	 * we can route to */	rt = ipxrtr_lookup(addr->sipx_network);	ret = -ENETUNREACH;	if (!rt && !(!addr->sipx_network && ipx_primary_net))		goto out;	sk->protinfo.af_ipx.dest_addr.net  = addr->sipx_network;	sk->protinfo.af_ipx.dest_addr.sock = addr->sipx_port;	memcpy(sk->protinfo.af_ipx.dest_addr.node,		addr->sipx_node, IPX_NODE_LEN);	sk->protinfo.af_ipx.type = addr->sipx_type;	if (sock->type == SOCK_DGRAM) {		sock->state 	= SS_CONNECTED;		sk->state 	= TCP_ESTABLISHED;	}	if (rt)		ipxrtr_put(rt);	ret = 0;out:	return ret;}static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,			int *uaddr_len, int peer){	ipx_address *addr;	struct sockaddr_ipx sipx;	struct sock *sk = sock->sk;	int ret;	*uaddr_len = sizeof(struct sockaddr_ipx);	if (peer) {		ret = -ENOTCONN;		if (sk->state != TCP_ESTABLISHED)			goto out;		addr = &sk->protinfo.af_ipx.dest_addr;		sipx.sipx_network	= addr->net;		sipx.sipx_port		= addr->sock;		memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);	} else {		if (sk->protinfo.af_ipx.intrfc) {			sipx.sipx_network =				sk->protinfo.af_ipx.intrfc->if_netnum;#ifdef CONFIG_IPX_INTERN			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node,				IPX_NODE_LEN);#else			memcpy(sipx.sipx_node,				sk->protinfo.af_ipx.intrfc->if_node,				IPX_NODE_LEN);#endif	/* CONFIG_IPX_INTERN */		} else {			sipx.sipx_network = 0;			memset(sipx.sipx_node, '\0', IPX_NODE_LEN);		}		sipx.sipx_port = sk->protinfo.af_ipx.port;	}	sipx.sipx_family = AF_IPX;	sipx.sipx_type	 = sk->protinfo.af_ipx.type;	memcpy(uaddr, &sipx, sizeof(sipx));	ret = 0;out:	return ret;}int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){	/* NULL here for pt means the packet was looped back */	ipx_interface *intrfc;	struct ipxhdr *ipx;	u16 ipx_pktsize;	int ret = 0;			/* Not ours */	        if (skb->pkt_type == PACKET_OTHERHOST)        	goto drop;	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)		goto out;	ipx		= skb->nh.ipxh;	ipx_pktsize	= ntohs(ipx->ipx_pktsize);		/* Too small or invalid header? */	if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)		goto drop;                        	if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&	   ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))		goto drop;	IPX_SKB_CB(skb)->ipx_tctrl	= ipx->ipx_tctrl;	IPX_SKB_CB(skb)->ipx_dest_net	= ipx->ipx_dest.net;	IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;	/* Determine what local ipx endpoint this is */	intrfc = ipxitf_find_using_phys(dev, pt->type);	if (!intrfc) {		if (ipxcfg_auto_create_interfaces &&		   ntohl(IPX_SKB_CB(skb)->ipx_dest_net)) {			intrfc = ipxitf_auto_create(dev, pt->type);			if (intrfc)				ipxitf_hold(intrfc);		}		if (!intrfc)	/* Not one of ours */				/* or invalid packet for auto creation */			goto drop;	}	ret = ipxitf_rcv(intrfc, skb);	ipxitf_put(intrfc);	goto out;drop:	kfree_skb(skb);out:	return ret;}static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,	struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;	struct sockaddr_ipx local_sipx;	int ret = -EINVAL;	int flags = msg->msg_flags;	/* Socket gets bound below anyway *//*	if (sk->zapped)		return -EIO; */	/* Socket not bound */	if (flags & ~MSG_DONTWAIT)		goto out;	if (usipx) {		if (!sk->protinfo.af_ipx.port) {			struct sockaddr_ipx uaddr;			uaddr.sipx_port		= 0;			uaddr.sipx_network	= 0;#ifdef CONFIG_IPX_INTERN			ret = -ENETDOWN;			if (!sk->protinfo.af_ipx.intrfc)				goto out; /* Someone zonked the iface */			memcpy(uaddr.sipx_node,				sk->protinfo.af_ipx.intrfc->if_node,				IPX_NODE_LEN);#endif			ret = ipx_bind(sock, (struct sockaddr *)&uaddr,					sizeof(struct sockaddr_ipx));			if (ret)				goto out;		}		ret = -EINVAL;		if (msg->msg_namelen < sizeof(*usipx) ||		    usipx->sipx_family != AF_IPX)			goto out;	} else {		ret = -ENOTCONN;		if (sk->state != TCP_ESTABLISHED)			goto out;		usipx = &local_sipx;		usipx->sipx_family 	= AF_IPX;		usipx->sipx_type 	= sk->protinfo.af_ipx.type;		usipx->sipx_port 	= sk->protinfo.af_ipx.dest_addr.sock;		usipx->sipx_network 	= sk->protinfo.af_ipx.dest_addr.net;		memcpy(usipx->sipx_node, sk->protinfo.af_ipx.dest_addr.node,				IPX_NODE_LEN);	}	ret = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,				     flags & MSG_DONTWAIT);	if (ret >= 0)		ret = len;out:	return ret;}static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size,		int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;	struct ipxhdr *ipx = NULL;	struct sk_buff *skb;	int copied, err;	/* put the autobinding in */	if (!sk->protinfo.af_ipx.port) {		struct sockaddr_ipx uaddr;		uaddr.sipx_port		= 0;		uaddr.sipx_network 	= 0;#ifdef CONFIG_IPX_INTERN		err = -ENETDOWN;		if (!sk->protinfo.af_ipx.intrfc)			goto out; /* Someone zonked the iface */		memcpy(uaddr.sipx_node,			sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);#endif	/* CONFIG_IPX_INTERN */		err = ipx_bind(sock, (struct sockaddr *)&uaddr,				sizeof(struct sockaddr_ipx));		if (err)			goto out;	}		err = -ENOTCONN;	if (sk->zapped)		goto out;	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,					flags & MSG_DONTWAIT, &err);	if (!skb)		goto out;	ipx 	= skb->nh.ipxh;	copied 	= ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);	if (copied > size) {		copied = size;		msg->msg_flags |= MSG_TRUNC;	}	err = skb_copy_datagram_iovec(skb, sizeof(struct ipxhdr), msg->msg_iov,					copied);	if (err)		goto out_free;	sk->stamp = skb->stamp;	msg->msg_namelen = sizeof(*sipx);	if (sipx) {		sipx->sipx_family	= AF_IPX;		sipx->sipx_port		= ipx->ipx_source.sock;		memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;		sipx->sipx_type 	= ipx->ipx_type;	}	err = copied;out_free:	skb_free_datagram(sk, skb);out:	return err;}static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	long amount = 0;	struct sock *sk = sock->sk;	switch (cmd) {		case TIOCOUTQ:			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);			if (amount < 0)				amount = 0;			return put_user(amount, (int *)arg);		case TIOCINQ: {			struct sk_buff *skb = skb_peek(&sk->receive_queue);			/* These two are safe on a single CPU system as only			 * user tasks fiddle here */			if (skb)				amount = skb->len - sizeof(struct ipxhdr);			return put_user(amount, (int *)arg);		}		case SIOCADDRT:		case SIOCDELRT:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			return ipxrtr_ioctl(cmd, (void *)arg);		case SIOCSIFADDR:		case SIOCAIPXITFCRT:		case SIOCAIPXPRISLT:			if (!capable(CAP_NET_ADMIN))				return -EPERM;		case SIOCGIFADDR:			return ipxitf_ioctl(cmd, (void *)arg);		case SIOCIPXCFGDATA:			return ipxcfg_get_config_data((void *)arg);		case SIOCIPXNCPCONN:			/*			 * This socket wants to take care of the NCP connection			 * handed to us in arg.			 */                	if (!capable(CAP_NET_ADMIN))                		return -EPERM;			return get_user(sk->protinfo.af_ipx.ipx_ncp_conn,					(const unsigned short *)(arg));		case SIOCGSTAMP: {			int ret = -EINVAL;			if (sk) {				if (!sk->stamp.tv_sec)					return -ENOENT;				ret = -EFAULT;				if (!copy_to_user((void *)arg, &sk->stamp,						sizeof(struct timeval)))					ret = 0;			}			return ret;		}		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:			return -EINVAL;		default:			return dev_ioctl(cmd,(void *) arg);	}	/*NOT REACHED*/	return 0;}/* *      SPX interface support */int ipx_register_spx(struct proto_ops **p, struct net_proto_family *spx){        if (spx_family_ops)                return -EBUSY;        cli();        MOD_INC_USE_COUNT;        *p = &ipx_dgram_ops;        spx_family_ops = spx;        sti();        return 0;}int ipx_unregister_spx(void){        spx_family_ops = NULL;        MOD_DEC_USE_COUNT;        return 0;}/* * Socket family declarations */static struct net_proto_family ipx_family_ops = {	family:		PF_IPX,	create:		ipx_create,};static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {	family:		PF_IPX,	release:	ipx_release,	bind:		ipx_bind,	connect:	ipx_connect,	socketpair:	sock_no_socketpair,	accept:		sock_no_accept,	getname:	ipx_getname,	poll:		datagram_poll,	ioctl:		ipx_ioctl,	listen:		sock_no_listen,	shutdown:	sock_no_shutdown, /* FIXME: have to support shutdown */	setsockopt:	ipx_setsockopt,	getsockopt:	ipx_getsockopt,	sendmsg:	ipx_sendmsg,	recvmsg:	ipx_recvmsg,	mmap:		sock_no_mmap,	sendpage:	sock_no_sendpage,};#include <linux/smp_lock.h>SOCKOPS_WRAP(ipx_dgram, PF_IPX);static struct packet_type ipx_8023_packet_type = {	type:		__constant_htons(ETH_P_802_3),	func:		ipx_rcv,	data:		(void *) 1,	/* yap, I understand shared skbs :-) */};static struct packet_type ipx_dix_packet_type = {	type:		__constant_htons(ETH_P_IPX),	func:		ipx_rcv,	data:		(void *) 1,	/* yap, I understand shared skbs :-) */};static struct notifier_block ipx_dev_notifier = {	notifier_call:	ipxitf_device_event,};extern struct datalink_proto *make_EII_client(void);extern struct datalink_proto *make_8023_client(void);extern void destroy_EII_client(struct datalink_proto *);extern void destroy_8023_client(struct datalink_proto *);static unsigned char ipx_8022_type = 0xE0;static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };static char banner[] __initdata =	KERN_INFO "NET4: Linux IPX 0.47 for NET4.0\n"	KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \	KERN_INFO "IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.\n";static int __init ipx_init(void){	sock_register(&ipx_family_ops);	pEII_datalink = make_EII_client();	dev_add_pack(&ipx_dix_packet_type);	p8023_datalink = make_8023_client();	dev_add_pack(&ipx_8023_packet_type);	p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);	if (!p8022_datalink)		printk(KERN_CRIT "IPX: Unable to register with 802.2\n");	pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);	if (!pSNAP_datalink)		printk(KERN_CRIT "IPX: Unable to register with SNAP\n");	register_netdevic

⌨️ 快捷键说明

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