patch-2.2.0-pre1 linux/net/ipx/af_ipx.c

Next file: linux/net/netrom/nr_dev.c
Previous file: linux/net/ipv6/af_inet6.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.132/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
@@ -50,6 +50,9 @@
  *	Revision 0.39:  SPX interfaces
  *	Revision 0.40:  Tiny SIOCGSTAMP fix (chris@cybernet.co.nz)
  *      Revision 0.41:  802.2TR removed (p.norton@computer.org)
+ *			Fixed connecting to primary net,
+ *			Automatic binding on send & receive,
+ *			Martijn van Oosterhout <kleptogimp@geocities.com>
  *
  *	Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *	pair. Also, now usage count is managed this way
@@ -450,7 +453,57 @@
 	struct sock *sock1 = NULL, *sock2 = NULL;
 	struct sk_buff *skb1 = NULL, *skb2 = NULL;
 
-	sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
+	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) 
+	{
+		/* 
+	 	 * The packet's target is a NCP connection handler. We want to
+	 	 * hand it to the correct socket directly within the kernel,
+	 	 * so that the mars_nwe packet distribution process
+	 	 * does not have to do it. Here we only care about NCP and
+	 	 * BURST packets.
+	 	 * You might call this a hack, but believe me, you do not
+	 	 * want a complete NCP layer in the kernel, and this is
+	 	 * VERY fast as well.
+	 	 */
+	 	int connection = 0;
+
+	 	if (*((char*)(ipx+1)) == 0x22 &&  *((char*)(ipx+1)+1) == 0x22) 
+		{
+	  		/*
+			 * The packet is a NCP request
+			 */
+			connection = ( ((int) *((char*)(ipx+1)+5)) << 8 )
+		 	       | (int) *((char*)(ipx+1)+3);
+		} 
+		else if (*((char*)(ipx+1))== 0x77 &&  *((char*)(ipx+1)+1) == 0x77) 
+		{
+			/*
+			 * The packet is a BURST packet
+			 */
+			connection = ( ((int) *((char*)(ipx+1)+9)) << 8 )
+		 	       | (int) *((char*)(ipx+1)+8);
+		}
+
+        	if (connection) 
+		{
+			/*
+			 * Now we have to look for a special NCP connection handling
+			 * socket. Only these sockets have ipx_ncp_conn != 0, set
+			 * by SIOCIPXNCPCONN.
+			 */
+			for (sock1=intrfc->if_sklist;
+				(sock1 != NULL) &&
+				(sock1->protinfo.af_ipx.ipx_ncp_conn != connection);
+					sock1=sock1->next);
+		}
+        }
+        if (sock1 == NULL) 
+	{
+		/* No special socket found, forward the packet the
+		 * normal way.
+		 */
+		sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
+	}
 
 	/*
 	 * We need to check if there is a primary net and if
@@ -1822,7 +1875,7 @@
 	}
 
 	/* protect IPX system stuff like routing/sap */
-	if(ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && !suser())
+	if(ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && !capable(CAP_NET_ADMIN))
 		return (-EACCES);
 
 	sk->protinfo.af_ipx.port = addr->sipx_port;
@@ -1930,7 +1983,8 @@
 			return (ret);
 	}
 
-	if(ipxrtr_lookup(addr->sipx_network) == NULL)
+        /* 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;
@@ -2061,8 +2115,9 @@
 	int retval;
 	int flags = msg->msg_flags;
 
-	if(sk->zapped)
-		return (-EIO);	/* Socket not bound */
+	/* Socket gets bound below anyway */
+/*	if(sk->zapped)
+		return (-EIO); */	/* Socket not bound */
 	if(flags & ~MSG_DONTWAIT)
 		return (-EINVAL);
 
@@ -2120,6 +2175,26 @@
 	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
+		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 != 0)
+			return (ret);
+	}
+	
 	if(sk->zapped)
 		return (-ENOTCONN);
 
@@ -2191,14 +2266,14 @@
 
 		case SIOCADDRT:
 		case SIOCDELRT:
-			if(!suser())
+			if(!capable(CAP_NET_ADMIN))
 				return (-EPERM);
 			return (ipxrtr_ioctl(cmd,(void *)arg));
 
 		case SIOCSIFADDR:
 		case SIOCAIPXITFCRT:
 		case SIOCAIPXPRISLT:
-			if(!suser())
+			if(!capable(CAP_NET_ADMIN))
 				return (-EPERM);
 
 		case SIOCGIFADDR:
@@ -2206,6 +2281,17 @@
 
 		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:
 		{

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov