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

📄 af_ipx.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
	skb->sk = sk;	/* Fill in IPX header */	ipx = (struct ipxhdr *)skb_put(skb, sizeof(struct ipxhdr));	ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));	IPX_SKB_CB(skb)->ipx_tctrl = 0;	ipx->ipx_type 	 = usipx->sipx_type;	skb->h.raw 	 = (void *)skb->nh.ipxh = ipx;	IPX_SKB_CB(skb)->last_hop.index = -1;#ifdef CONFIG_IPX_INTERN	IPX_SKB_CB(skb)->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum;	memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);#else	err = ntohs(sk->protinfo.af_ipx.port);	if (err == 0x453 || err == 0x452) {		/* RIP/SAP special handling for mars_nwe */		IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;		memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);	} else {		IPX_SKB_CB(skb)->ipx_source_net =					sk->protinfo.af_ipx.intrfc->if_netnum;		memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);	}#endif	/* CONFIG_IPX_INTERN */	ipx->ipx_source.sock		= sk->protinfo.af_ipx.port;	IPX_SKB_CB(skb)->ipx_dest_net	= usipx->sipx_network;	memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);	ipx->ipx_dest.sock		= usipx->sipx_port;	err = memcpy_fromiovec(skb_put(skb, len), iov, len);	if (err) {		kfree_skb(skb);		goto out_put;	}		/* Apply checksum. Not allowed on 802.3 links. */	if (sk->no_check || intrfc->if_dlink_type == IPX_FRAME_8023)		ipx->ipx_checksum = 0xFFFF;	else		ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));	err = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? 				rt->ir_router_node : ipx->ipx_dest.node);out_put:	ipxitf_put(intrfc);	if (rt)		ipxrtr_put(rt);out:	return err;}/* the skb has to be unshared, we'll end up calling ipxitf_send, that'll * modify the packet */int ipxrtr_route_skb(struct sk_buff *skb){	struct ipxhdr *ipx = skb->nh.ipxh;	ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net);	if (!r) {	/* no known route */		kfree_skb(skb);		return 0;	}	ipxitf_hold(r->ir_intrfc);	ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?			r->ir_router_node : ipx->ipx_dest.node);	ipxitf_put(r->ir_intrfc);	ipxrtr_put(r);	return 0;}/* * We use a normal struct rtentry for route handling */static int ipxrtr_ioctl(unsigned int cmd, void *arg){	struct rtentry rt;	/* Use these to behave like 'other' stacks */	struct sockaddr_ipx *sg, *st;	int ret = -EFAULT;	if (copy_from_user(&rt, arg, sizeof(rt)))		goto out;	sg = (struct sockaddr_ipx *)&rt.rt_gateway;	st = (struct sockaddr_ipx *)&rt.rt_dst;	ret = -EINVAL;	if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */	    sg->sipx_family != AF_IPX ||	    st->sipx_family != AF_IPX)		goto out;	switch (cmd) {		case SIOCDELRT:			ret = ipxrtr_delete(st->sipx_network);			break;		case SIOCADDRT: {			struct ipx_route_definition f;			f.ipx_network		= st->sipx_network;			f.ipx_router_network	= sg->sipx_network;			memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);			ret = ipxrtr_create(&f);			break;		}	}out:	return ret;}static const char *ipx_frame_name(unsigned short frame){	char* ret = "None";	switch (ntohs(frame)) {		case ETH_P_IPX:		ret = "EtherII";	break;		case ETH_P_802_2:	ret = "802.2";		break;		case ETH_P_SNAP:	ret = "SNAP";		break;		case ETH_P_802_3:	ret = "802.3";		break;		case ETH_P_TR_802_2:	ret = "802.2TR";	break;	}	return ret;}static const char *ipx_device_name(ipx_interface *intrfc){	return intrfc->if_internal ? "Internal" :		intrfc->if_dev ? intrfc->if_dev->name : "Unknown";}/* Called from proc fs */static int ipx_interface_get_info(char *buffer, char **start, off_t offset,				  int length){	ipx_interface *i;	off_t begin = 0, pos = 0;	int len = 0;	/* Theory.. Keep printing in the same place until we pass offset */	len += sprintf(buffer, "%-11s%-15s%-9s%-11s%s", "Network",		"Node_Address", "Primary", "Device", "Frame_Type");#ifdef IPX_REFCNT_DEBUG	len += sprintf(buffer + len, "  refcnt");#endif	strcat(buffer + len++, "\n");	spin_lock_bh(&ipx_interfaces_lock);	for (i = ipx_interfaces; i; i = i->if_next) {		len += sprintf(buffer + len, "%08lX   ",				(long unsigned int) ntohl(i->if_netnum));		len += sprintf(buffer + len, "%02X%02X%02X%02X%02X%02X   ",				i->if_node[0], i->if_node[1], i->if_node[2],				i->if_node[3], i->if_node[4], i->if_node[5]);		len += sprintf(buffer + len, "%-9s", i == ipx_primary_net ?			"Yes" : "No");		len += sprintf(buffer + len, "%-11s", ipx_device_name(i));		len += sprintf(buffer + len, "%-9s",			ipx_frame_name(i->if_dlink_type));#ifdef IPX_REFCNT_DEBUG		len += sprintf(buffer + len, "%6d", atomic_read(&i->refcnt));#endif		strcat(buffer + len++, "\n");		/* 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(&ipx_interfaces_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;}static int ipx_get_info(char *buffer, char **start, off_t offset, int length){	struct sock *s;	ipx_interface *i;	off_t begin = 0, pos = 0;	int len = 0;	/* Theory.. Keep printing in the same place until we pass offset */#ifdef CONFIG_IPX_INTERN	len += sprintf(buffer, "%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",#else	len += sprintf(buffer, "%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",#endif	/* CONFIG_IPX_INTERN */			"Remote_Address", "Tx_Queue", "Rx_Queue",			"State", "Uid");	spin_lock_bh(&ipx_interfaces_lock);	for (i = ipx_interfaces; i; i = i->if_next) {		ipxitf_hold(i);		spin_lock_bh(&i->if_sklist_lock);		for (s = i->if_sklist; s; s = s->next) {#ifdef CONFIG_IPX_INTERN			len += sprintf(buffer + len,				       "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",                                       (unsigned long) htonl(s->protinfo.af_ipx.intrfc->if_netnum),				       s->protinfo.af_ipx.node[0],				       s->protinfo.af_ipx.node[1],				       s->protinfo.af_ipx.node[2],				       s->protinfo.af_ipx.node[3],				       s->protinfo.af_ipx.node[4],				       s->protinfo.af_ipx.node[5],				       htons(s->protinfo.af_ipx.port));#else			len += sprintf(buffer + len, "%08lX:%04X  ",				       (unsigned long) htonl(i->if_netnum),				       htons(s->protinfo.af_ipx.port));#endif	/* CONFIG_IPX_INTERN */			if (s->state != TCP_ESTABLISHED)				len += sprintf(buffer + len, "%-28s",						"Not_Connected");			else {				len += sprintf(buffer + len,					"%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",					(unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net),					s->protinfo.af_ipx.dest_addr.node[0],					s->protinfo.af_ipx.dest_addr.node[1],					s->protinfo.af_ipx.dest_addr.node[2],					s->protinfo.af_ipx.dest_addr.node[3],					s->protinfo.af_ipx.dest_addr.node[4],					s->protinfo.af_ipx.dest_addr.node[5],					htons(s->protinfo.af_ipx.dest_addr.sock));			}			len += sprintf(buffer + len, "%08X  %08X  ",				atomic_read(&s->wmem_alloc),				atomic_read(&s->rmem_alloc));			len += sprintf(buffer + len, "%02X     %03d\n",				s->state, SOCK_INODE(s->socket)->i_uid);			pos = begin + len;			if (pos < offset) {				len   = 0;				begin = pos;			}			if (pos > offset + length)  /* We have dumped enough */				break;		}		spin_unlock_bh(&i->if_sklist_lock);		ipxitf_put(i);	}	spin_unlock_bh(&ipx_interfaces_lock);	/* The data in question runs from begin to begin+len */	*start = buffer + offset - begin;	len -= (offset - begin);	if (len > length)		len = length;	return len;}static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length){	ipx_route *rt;	off_t begin = 0, pos = 0;	int len = 0;	len += sprintf(buffer, "%-11s%-13s%s\n",			"Network", "Router_Net", "Router_Node");	read_lock_bh(&ipx_routes_lock);	for (rt = ipx_routes; rt; rt = rt->ir_next) {		len += sprintf(buffer + len, "%08lX   ",				(long unsigned int) ntohl(rt->ir_net));		if (rt->ir_routed) {			len += sprintf(buffer + len,					"%08lX     %02X%02X%02X%02X%02X%02X\n",			(long unsigned int) ntohl(rt->ir_intrfc->if_netnum),				rt->ir_router_node[0], rt->ir_router_node[1],				rt->ir_router_node[2], rt->ir_router_node[3],				rt->ir_router_node[4], rt->ir_router_node[5]);		} else {			len += sprintf(buffer + len, "%-13s%s\n",					"Directly", "Connected");		}		pos = begin + len;		if (pos < offset) {			len = 0;			begin = pos;		}		if (pos > offset + length)			break;	}	read_unlock_bh(&ipx_routes_lock);	*start = buffer + (offset - begin);	len -= (offset - begin);	if (len > length)		len = length;	return len;}/* Handling for system calls applied via the various interfaces to an IPX * socket object. */static int ipx_setsockopt(struct socket *sock, int level, int optname,			  char *optval, int optlen){	struct sock *sk = sock->sk;	int opt;	int ret = -EINVAL;	if (optlen != sizeof(int))		goto out;	ret = -EFAULT;	if (get_user(opt, (unsigned int *)optval))		goto out;	ret = -ENOPROTOOPT;	if (!(level == SOL_IPX && optname == IPX_TYPE))		goto out;	sk->protinfo.af_ipx.type = opt;	ret = 0;out:	return ret;}static int ipx_getsockopt(struct socket *sock, int level, int optname,	char *optval, int *optlen){	struct sock *sk = sock->sk;	int val = 0;	int len;	int ret = -ENOPROTOOPT;	if (!(level == SOL_IPX && optname == IPX_TYPE))		goto out;	val = sk->protinfo.af_ipx.type;	ret = -EFAULT;	if (get_user(len, optlen))		goto out;	len = min_t(unsigned int, len, sizeof(int));	ret = -EINVAL;	if(len < 0)		goto out;			ret = -EFAULT;	if (put_user(len, optlen) || copy_to_user(optval, &val, len))		goto out;	ret = 0;out:	return ret;}static int ipx_create(struct socket *sock, int protocol){	int ret = -ESOCKTNOSUPPORT;	struct sock *sk;	switch (sock->type) {		case SOCK_DGRAM:			sk = sk_alloc(PF_IPX, GFP_KERNEL, 1);                	ret = -ENOMEM;			if (!sk)				goto out;                        sock->ops = &ipx_dgram_ops;                        break;		case SOCK_SEQPACKET:			/*			 * From this point on SPX sockets are handled			 * by af_spx.c and the methods replaced.			 */			if (spx_family_ops) {				ret = spx_family_ops->create(sock, protocol);				goto out;			}			/* Fall through if SPX is not loaded */		case SOCK_STREAM:       /* Allow higher levels to piggyback */		default:			goto out;	}#ifdef IPX_REFCNT_DEBUG        atomic_inc(&ipx_sock_nr);        printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,			atomic_read(&ipx_sock_nr));#endif	sock_init_data(sock, sk);	sk->destruct	= NULL;	sk->no_check 	= 1;		/* Checksum off by default */	MOD_INC_USE_COUNT;	ret = 0;out:	return ret;}static int ipx_release(struct socket *sock){	struct sock *sk = sock->sk;	if (!sk)		goto out;	if (!sk->dead)		sk->state_change(sk);	sk->dead = 1;	sock->sk = NULL;	ipx_destroy_socket(sk);	if (sock->type == SOCK_DGRAM)		MOD_DEC_USE_COUNT;out:	return 0;}/* caller must hold a reference to intrfc */static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc){	unsigned short socketNum = intrfc->if_sknum;	spin_lock_bh(&intrfc->if_sklist_lock);	if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)		socketNum = IPX_MIN_EPHEMERAL_SOCKET;	while (__ipxitf_find_socket(intrfc, ntohs(socketNum)))		if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)			socketNum = IPX_MIN_EPHEMERAL_SOCKET;		else			socketNum++;	spin_unlock_bh(&intrfc->if_sklist_lock);	intrfc->if_sknum = socketNum;	return ntohs(socketNum);}static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sock *sk = sock->sk;	ipx_interface *intrfc;	struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;	int ret = -EINVAL;	if (!sk->zapped || addr_len != sizeof(struct sockaddr_ipx))		goto out;	intrfc = ipxitf_find_using_net(addr->sipx_network);	ret = -EADDRNOTAVAIL;	if (!intrfc)		goto out;	if (!addr->sipx_port) {		addr->sipx_port = ipx_first_free_socketnum(intrfc);		ret = -EINVAL;		if (!addr->sipx_port)			goto out_put;	}	/* protect IPX system stuff like routing/sap */	ret = -EACCES;	if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&	    !capable(CAP_NET_ADMIN))		goto out_put;	sk->protinfo.af_ipx.port = addr->sipx_port;#ifdef CONFIG_IPX_INTERN	if (intrfc == ipx_internal_net) {		/* The source address is to be set explicitly if the		 * socket is to be bound on the internal network. If a		 * node number 0 was specified, the default is used.		 */		ret = -EINVAL;		if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN))			goto out_put;		if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))			memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,			       IPX_NODE_LEN);		else			memcpy(sk->protinfo.af_ipx.node, addr->sipx_node,				IPX_NODE_LEN);		ret = -EADDRINUSE;		if (ipxitf_find_internal_socket(intrfc,						sk->protinfo.af_ipx.node,						sk->protinfo.af_ipx.port)) {			SOCK_DEBUG(sk,				"IPX: bind failed because port %X in use.\n",				ntohs((int)addr->sipx_port));			goto out_put;		}	} else {		/* Source addresses are easy. It must be our		 * network:node pair for an interface routed to IPX		 * with the ipx routing ioctl()		 */

⌨️ 快捷键说明

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