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

📄 af_ipx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			IPX_NODE_LEN);#endif	/* CONFIG_IPX_INTERN */		rc = ipx_bind(sock, (struct sockaddr *)&uaddr,			      sizeof(struct sockaddr_ipx));		if (rc)			goto out;	}	/* We can either connect to primary network or somewhere	 * we can route to */	rt = ipxrtr_lookup(addr->sipx_network);	rc = -ENETUNREACH;	if (!rt && !(!addr->sipx_network && ipx_primary_net))		goto out;	ipxs->dest_addr.net  = addr->sipx_network;	ipxs->dest_addr.sock = addr->sipx_port;	memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN);	ipxs->type = addr->sipx_type;	if (sock->type == SOCK_DGRAM) {		sock->state 	= SS_CONNECTED;		sk->sk_state 	= TCP_ESTABLISHED;	}	if (rt)		ipxrtr_put(rt);	rc = 0;out:	return rc;}static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,			int *uaddr_len, int peer){	struct ipx_address *addr;	struct sockaddr_ipx sipx;	struct sock *sk = sock->sk;	struct ipx_sock *ipxs = ipx_sk(sk);	int rc;	*uaddr_len = sizeof(struct sockaddr_ipx);	if (peer) {		rc = -ENOTCONN;		if (sk->sk_state != TCP_ESTABLISHED)			goto out;		addr = &ipxs->dest_addr;		sipx.sipx_network	= addr->net;		sipx.sipx_port		= addr->sock;		memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);	} else {		if (ipxs->intrfc) {			sipx.sipx_network = ipxs->intrfc->if_netnum;#ifdef CONFIG_IPX_INTERN			memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN);#else			memcpy(sipx.sipx_node, ipxs->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 = ipxs->port;	}	sipx.sipx_family = AF_IPX;	sipx.sipx_type	 = ipxs->type;	sipx.sipx_zero	 = 0;	memcpy(uaddr, &sipx, sizeof(sipx));	rc = 0;out:	return rc;}static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev){	/* NULL here for pt means the packet was looped back */	struct ipx_interface *intrfc;	struct ipxhdr *ipx;	u16 ipx_pktsize;	int rc = 0;	if (dev->nd_net != &init_net)		goto drop;	/* Not ours */	if (skb->pkt_type == PACKET_OTHERHOST)		goto drop;	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)		goto out;	if (!pskb_may_pull(skb, sizeof(struct ipxhdr)))		goto drop;	ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);	/* Too small or invalid header? */	if (ipx_pktsize < sizeof(struct ipxhdr) ||	    !pskb_may_pull(skb, ipx_pktsize))		goto drop;	ipx = ipx_hdr(skb);	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 &&		   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;	}	rc = ipxitf_rcv(intrfc, skb);	ipxitf_put(intrfc);	goto out;drop:	kfree_skb(skb);out:	return rc;}static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,	struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	struct ipx_sock *ipxs = ipx_sk(sk);	struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;	struct sockaddr_ipx local_sipx;	int rc = -EINVAL;	int flags = msg->msg_flags;	/* Socket gets bound below anyway *//*	if (sk->sk_zapped)		return -EIO; */	/* Socket not bound */	if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))		goto out;	/* Max possible packet size limited by 16 bit pktsize in header */	if (len >= 65535 - sizeof(struct ipxhdr))		goto out;	if (usipx) {		if (!ipxs->port) {			struct sockaddr_ipx uaddr;			uaddr.sipx_port		= 0;			uaddr.sipx_network	= 0;#ifdef CONFIG_IPX_INTERN			rc = -ENETDOWN;			if (!ipxs->intrfc)				goto out; /* Someone zonked the iface */			memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,				IPX_NODE_LEN);#endif			rc = ipx_bind(sock, (struct sockaddr *)&uaddr,					sizeof(struct sockaddr_ipx));			if (rc)				goto out;		}		rc = -EINVAL;		if (msg->msg_namelen < sizeof(*usipx) ||		    usipx->sipx_family != AF_IPX)			goto out;	} else {		rc = -ENOTCONN;		if (sk->sk_state != TCP_ESTABLISHED)			goto out;		usipx = &local_sipx;		usipx->sipx_family 	= AF_IPX;		usipx->sipx_type 	= ipxs->type;		usipx->sipx_port 	= ipxs->dest_addr.sock;		usipx->sipx_network 	= ipxs->dest_addr.net;		memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN);	}	rc = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,				 flags & MSG_DONTWAIT);	if (rc >= 0)		rc = len;out:	return rc;}static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,		struct msghdr *msg, size_t size, int flags){	struct sock *sk = sock->sk;	struct ipx_sock *ipxs = ipx_sk(sk);	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;	struct ipxhdr *ipx = NULL;	struct sk_buff *skb;	int copied, rc;	/* put the autobinding in */	if (!ipxs->port) {		struct sockaddr_ipx uaddr;		uaddr.sipx_port		= 0;		uaddr.sipx_network 	= 0;#ifdef CONFIG_IPX_INTERN		rc = -ENETDOWN;		if (!ipxs->intrfc)			goto out; /* Someone zonked the iface */		memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);#endif	/* CONFIG_IPX_INTERN */		rc = ipx_bind(sock, (struct sockaddr *)&uaddr,			      sizeof(struct sockaddr_ipx));		if (rc)			goto out;	}	rc = -ENOTCONN;	if (sock_flag(sk, SOCK_ZAPPED))		goto out;	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,				flags & MSG_DONTWAIT, &rc);	if (!skb)		goto out;	ipx 	= ipx_hdr(skb);	copied 	= ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);	if (copied > size) {		copied = size;		msg->msg_flags |= MSG_TRUNC;	}	rc = skb_copy_datagram_iovec(skb, sizeof(struct ipxhdr), msg->msg_iov,				     copied);	if (rc)		goto out_free;	if (skb->tstamp.tv64)		sk->sk_stamp = skb->tstamp;	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;		sipx->sipx_zero		= 0;	}	rc = copied;out_free:	skb_free_datagram(sk, skb);out:	return rc;}static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	int rc = 0;	long amount = 0;	struct sock *sk = sock->sk;	void __user *argp = (void __user *)arg;	switch (cmd) {	case TIOCOUTQ:		amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);		if (amount < 0)			amount = 0;		rc = put_user(amount, (int __user *)argp);		break;	case TIOCINQ: {		struct sk_buff *skb = skb_peek(&sk->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);		rc = put_user(amount, (int __user *)argp);		break;	}	case SIOCADDRT:	case SIOCDELRT:		rc = -EPERM;		if (capable(CAP_NET_ADMIN))			rc = ipxrtr_ioctl(cmd, argp);		break;	case SIOCSIFADDR:	case SIOCAIPXITFCRT:	case SIOCAIPXPRISLT:		rc = -EPERM;		if (!capable(CAP_NET_ADMIN))			break;	case SIOCGIFADDR:		rc = ipxitf_ioctl(cmd, argp);		break;	case SIOCIPXCFGDATA:		rc = ipxcfg_get_config_data(argp);		break;	case SIOCIPXNCPCONN:		/*		 * This socket wants to take care of the NCP connection		 * handed to us in arg.		 */		rc = -EPERM;		if (!capable(CAP_NET_ADMIN))			break;		rc = get_user(ipx_sk(sk)->ipx_ncp_conn,			      (const unsigned short __user *)argp);		break;	case SIOCGSTAMP:		rc = -EINVAL;		if (sk)			rc = sock_get_timestamp(sk, argp);		break;	case SIOCGIFDSTADDR:	case SIOCSIFDSTADDR:	case SIOCGIFBRDADDR:	case SIOCSIFBRDADDR:	case SIOCGIFNETMASK:	case SIOCSIFNETMASK:		rc = -EINVAL;		break;	default:		rc = -ENOIOCTLCMD;		break;	}	return rc;}#ifdef CONFIG_COMPATstatic int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	/*	 * These 4 commands use same structure on 32bit and 64bit.  Rest of IPX	 * commands is handled by generic ioctl code.  As these commands are	 * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic	 * code.	 */	switch (cmd) {	case SIOCAIPXITFCRT:	case SIOCAIPXPRISLT:	case SIOCIPXCFGDATA:	case SIOCIPXNCPCONN:		return ipx_ioctl(sock, cmd, arg);	default:		return -ENOIOCTLCMD;	}}#endif/* * Socket family declarations */static struct net_proto_family ipx_family_ops = {	.family		= PF_IPX,	.create		= ipx_create,	.owner		= THIS_MODULE,};static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {	.family		= PF_IPX,	.owner		= THIS_MODULE,	.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,#ifdef CONFIG_COMPAT	.compat_ioctl	= ipx_compat_ioctl,#endif	.listen		= sock_no_listen,	.shutdown	= sock_no_shutdown, /* FIXME: support shutdown */	.setsockopt	= ipx_setsockopt,	.getsockopt	= ipx_getsockopt,	.sendmsg	= ipx_sendmsg,	.recvmsg	= ipx_recvmsg,	.mmap		= sock_no_mmap,	.sendpage	= sock_no_sendpage,};SOCKOPS_WRAP(ipx_dgram, PF_IPX);static struct packet_type ipx_8023_packet_type = {	.type		= __constant_htons(ETH_P_802_3),	.func		= ipx_rcv,};static struct packet_type ipx_dix_packet_type = {	.type		= __constant_htons(ETH_P_IPX),	.func		= ipx_rcv,};static struct notifier_block ipx_dev_notifier = {	.notifier_call	= ipxitf_device_event,};extern struct datalink_proto *make_EII_client(void);extern void destroy_EII_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 ipx_EII_err_msg[] __initdata =	KERN_CRIT "IPX: Unable to register with Ethernet II\n";static char ipx_8023_err_msg[] __initdata =	KERN_CRIT "IPX: Unable to register with 802.3\n";static char ipx_llc_err_msg[] __initdata =	KERN_CRIT "IPX: Unable to register with 802.2\n";static char ipx_snap_err_msg[] __initdata =	KERN_CRIT "IPX: Unable to register with SNAP\n";static int __init ipx_init(void){	int rc = proto_register(&ipx_proto, 1);	if (rc != 0)		goto out;	sock_register(&ipx_family_ops);	pEII_datalink = make_EII_client();	if (pEII_datalink)		dev_add_pack(&ipx_dix_packet_type);	else		printk(ipx_EII_err_msg);	p8023_datalink = make_8023_client();	if (p8023_datalink)		dev_add_pack(&ipx_8023_packet_type);	else		printk(ipx_8023_err_msg);	p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);	if (!p8022_datalink)		printk(ipx_llc_err_msg);	pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);	if (!pSNAP_datalink)		printk(ipx_snap_err_msg);	register_netdevice_notifier(&ipx_dev_notifier);	ipx_register_sysctl();	ipx_proc_init();out:	return rc;}static void __exit ipx_proto_finito(void){	ipx_proc_exit();	ipx_unregister_sysctl();	unregister_netdevice_notifier(&ipx_dev_notifier);	ipxitf_cleanup();	if (pSNAP_datalink) {		unregister_snap_client(pSNAP_datalink);		pSNAP_datalink = NULL;	}	if (p8022_datalink) {		unregister_8022_client(p8022_datalink);		p8022_datalink = NULL;	}	dev_remove_pack(&ipx_8023_packet_type);	if (p8023_datalink) {		destroy_8023_client(p8023_datalink);		p8023_datalink = NULL;	}	dev_remove_pack(&ipx_dix_packet_type);	if (pEII_datalink) {		destroy_EII_client(pEII_datalink);		pEII_datalink = NULL;	}	proto_unregister(&ipx_proto);	sock_unregister(ipx_family_ops.family);}module_init(ipx_init);module_exit(ipx_proto_finito);MODULE_LICENSE("GPL");MODULE_ALIAS_NETPROTO(PF_IPX);

⌨️ 快捷键说明

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