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

📄 af_ipx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef CONFIG_IPX_INTERN		if(sk->protinfo.af_ipx.intrfc)			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);		else			return -ENETDOWN;		/* Someone zonked the iface */#endif	/* CONFIG_IPX_INTERN */		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,				sizeof(struct sockaddr_ipx));		if(ret != 0)			return (ret);	}        /* We can either connect to primary network or somewhere we can route to */	if( !(addr->sipx_network == 0 && ipx_primary_net != NULL) && ipxrtr_lookup(addr->sipx_network) == NULL)		return (-ENETUNREACH);	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;	}	return (0);}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;	sk = sock->sk;	*uaddr_len = sizeof(struct sockaddr_ipx);	if(peer)	{		if(sk->state != TCP_ESTABLISHED)			return (-ENOTCONN);		addr = &sk->protinfo.af_ipx.dest_addr;		sipx.sipx_network = addr->net;		memcpy(sipx.sipx_node,addr->node,IPX_NODE_LEN);		sipx.sipx_port = addr->sock;	}	else	{		if(sk->protinfo.af_ipx.intrfc != NULL)		{			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));	return (0);}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;	int ret;	ipx = skb->nh.ipxh;		/* Too small? */	if(ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr))		goto drop;	/* Invalid header */	if(ntohs(ipx->ipx_pktsize) > skb->len)		goto drop;			/* Not ours */	        if (skb->pkt_type == PACKET_OTHERHOST)        	goto drop;                        	if(ipx->ipx_checksum != IPX_NO_CHECKSUM) 	{		if(ipx_set_checksum(ipx, ntohs(ipx->ipx_pktsize)) != ipx->ipx_checksum)			goto drop;	}	/* Determine what local ipx endpoint this is */	intrfc = ipxitf_find_using_phys(dev, pt->type);	if(intrfc == NULL)	{		if(ipxcfg_auto_create_interfaces		    && ntohl(ipx->ipx_dest.net) != 0L)		{			intrfc = ipxitf_auto_create(dev, pt->type);			ipxitf_hold(intrfc);		}		if(intrfc == NULL)	/* Not one of ours */			goto drop;	}	ret = ipxitf_rcv(intrfc, skb);	ipxitf_put(intrfc);	return ret;drop:	kfree_skb(skb);	return (0);}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 retval;	int flags = msg->msg_flags;	/* Socket gets bound below anyway *//*	if(sk->zapped)		return (-EIO); */	/* Socket not bound */	if(flags & ~MSG_DONTWAIT)		return (-EINVAL);	if(usipx)	{		if(sk->protinfo.af_ipx.port == 0)		{			struct sockaddr_ipx uaddr;			int ret;			uaddr.sipx_port = 0;			uaddr.sipx_network = 0L;#ifdef CONFIG_IPX_INTERN			if(sk->protinfo.af_ipx.intrfc)				memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc						->if_node,IPX_NODE_LEN);			else				return -ENETDOWN;               /* Someone zonked the iface */#endif			ret = ipx_bind(sock, (struct sockaddr *)&uaddr,					sizeof(struct sockaddr_ipx));			if(ret != 0)				return (ret);		}		if(msg->msg_namelen < sizeof(*usipx))			return (-EINVAL);		if(usipx->sipx_family != AF_IPX)			return (-EINVAL);	}	else	{		if(sk->state != TCP_ESTABLISHED)			return (-ENOTCONN);		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);	}	retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, flags&MSG_DONTWAIT);	if(retval < 0)		return (retval);	return (len);}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 == 0)	{		struct sockaddr_ipx uaddr;		int ret;		uaddr.sipx_port		= 0;		uaddr.sipx_network 	= 0;#ifdef CONFIG_IPX_INTERN		if(sk->protinfo.af_ipx.intrfc)			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);		else			return -ENETDOWN;		/* Someone zonked the iface */#endif	/* CONFIG_IPX_INTERN */		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,				sizeof(struct sockaddr_ipx));		if(ret != 0)			return (ret);	}		if(sk->zapped)		return (-ENOTCONN);	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->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;			/* These two are safe on a single CPU system as only user tasks fiddle here */			if((skb = skb_peek(&sk->receive_queue)) != NULL)				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 == 0)					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!=NULL)                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 = {	PF_IPX,	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: We have to really support shutdown. */	setsockopt:	ipx_setsockopt,	getsockopt:	ipx_getsockopt,	sendmsg:	ipx_sendmsg,	recvmsg:	ipx_recvmsg,	mmap:		sock_no_mmap,};#include <linux/smp_lock.h>SOCKOPS_WRAP(ipx_dgram, PF_IPX);static struct packet_type ipx_8023_packet_type ={	__constant_htons(ETH_P_802_3),	NULL,		/* All devices */	ipx_rcv,	NULL,	NULL,};static struct packet_type ipx_dix_packet_type ={	__constant_htons(ETH_P_IPX),	NULL,		/* All devices */	ipx_rcv,	NULL,	NULL,};static struct notifier_block ipx_dev_notifier={	ipxitf_device_event,	NULL,	0};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 int __init ipx_init(void){	(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);	if((p8022_datalink = register_8022_client(ipx_8022_type,ipx_rcv)) == NULL)		printk(KERN_CRIT "IPX: Unable to register with 802.2\n");	if((pSNAP_datalink = register_snap_client(ipx_snap_id,ipx_rcv)) == NULL)		printk(KERN_CRIT "IPX: Unable to register with SNAP\n");	register_netdevice_notifier(&ipx_dev_notifier);#ifdef CONFIG_PROC_FS	proc_net_create("ipx", 0, ipx_get_info);	proc_net_create("ipx_interface", 0, ipx_interface_get_info);	proc_net_create("ipx_route", 0, ipx_rt_get_info);#endif	printk(KERN_INFO "NET4: Linux IPX 0.42v4 for NET4.0\n");	printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");	printk(KERN_INFO "IPX Portions Copyright (c) 2000 Conectiva, Inc.\n");	return 0;}module_init(ipx_init);/* Higher layers need this info to prep tx pkts */int ipx_if_offset(unsigned long ipx_net_number){	ipx_route *rt = NULL;	rt = ipxrtr_lookup(ipx_net_number);	return (rt ? rt->ir_intrfc->if_ipx_offset : -ENETUNREACH);}/* Export symbols for higher layers */EXPORT_SYMBOL(ipxrtr_route_skb);EXPORT_SYMBOL(ipx_if_offset);EXPORT_SYMBOL(ipx_remove_socket);EXPORT_SYMBOL(ipx_register_spx);EXPORT_SYMBOL(ipx_unregister_spx);/* Note on MOD_{INC,DEC}_USE_COUNT: * * Use counts are incremented/decremented when * sockets are created/deleted. * * Routes are always associated with an interface, and * allocs/frees will remain properly accounted for by * their associated interfaces. * * Ergo, before the ipx module can be removed, all IPX * sockets be closed from user space. */#ifdef MODULEstatic void ipx_proto_finito(void){	/* no need to worry about having anything on the ipx_interfaces	 * list, when a interface is created we increment the module	 * usage count, so the module will only be unloaded when there	 * are no more interfaces */	proc_net_remove("ipx_route");	proc_net_remove("ipx_interface");	proc_net_remove("ipx");	unregister_netdevice_notifier(&ipx_dev_notifier);	unregister_snap_client(ipx_snap_id);	pSNAP_datalink 	= NULL;	unregister_8022_client(ipx_8022_type);	p8022_datalink 	= NULL;	dev_remove_pack(&ipx_8023_packet_type);	destroy_8023_client(p8023_datalink);	p8023_datalink 	= NULL;	dev_remove_pack(&ipx_dix_packet_type);	destroy_EII_client(pEII_datalink);	pEII_datalink 	= NULL;	(void) sock_unregister(ipx_family_ops.family);	return;}module_exit(ipx_proto_finito);#endif /* MODULE */#endif /* CONFIG_IPX || CONFIG_IPX_MODULE */

⌨️ 快捷键说明

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