While using SPX as a module running the kernel 2.2.12 I found the
following problems and I wrote a patch that seems to solve them.
- select() does not work for an SPX socket (waiting to read)
The patch adds a function spx_datagram_poll() that is basically the same
function as the one in net/core. spx_datagram_poll() however checks the
buffers where the SPX implementation really puts the data.
- only three SPX packets can be exchanged between the server (not Linux)
and a Linux client
If the server checks the alloc field of the SPX frame it will notice
that the number stops increasing at three. When this happens the server
refuses to send packets whose sequence number is greater than three.
- kernel oops if the net number has no route to it
When trying to connect on a network to which there is no route IPX might
return a ENETUNREACH error code. The SPX code was not checking this,
what lead to an error in sock_alloc_send_skb() (the size parameter got
set to a huge unsigned number) after which the system would freeze.
This is the first time I send a patch. I read all the documents I could
find on sending patches and I looked at other people's patches but still
something might be wrong formatted. If that is the case please let me
know.
Bye, Eduardo.
--------------DBC946C5A0A990BE7ACE10E1
Content-Type: text/plain; charset=us-ascii;
name="patch-spx-0.2-linux-2.2.12.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="patch-spx-0.2-linux-2.2.12.txt"
--- linux/net/ipx/af_spx.c.orig Mon Oct 11 16:20:52 1999
+++ linux/net/ipx/af_spx.c Mon Oct 11 16:38:36 1999
@@ -15,6 +15,11 @@
* made static the ipx ops. Removed the hack
* ipx methods interface. Dropped AF_SPX - its
* the wrong abstraction.
+ * Eduardo Trapani : Added a check for the return value of
+ * ipx_if_offset that crashed sock_alloc_send_skb.
+ * Added spx_datagram_poll() so that select()
+ * works now on SPX sockets. Added updating
+ * of the alloc count to follow rmt_seq.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -37,6 +42,7 @@
#include <linux/uio.h>
#include <linux/unistd.h>
#include <linux/firewall.h>
+#include <linux/poll.h>
static struct proto_ops *ipx_operations;
static struct proto_ops spx_operations;
@@ -50,6 +56,45 @@
extern void ipx_remove_socket(struct sock *sk);
+/* Datagram poll: the same code as datagram_poll() in net/core
+ but the right spx buffers are looked at and
+ there is no question on the type of the socket
+ */
+static unsigned int spx_datagram_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
+ unsigned int mask;
+
+ poll_wait(file, sk->sleep, wait);
+ mask = 0;
+
+ /* exceptional events? */
+ if (sk->err || !skb_queue_empty(&sk->error_queue))
+ mask |= POLLERR;
+ if (sk->shutdown & RCV_SHUTDOWN)
+ mask |= POLLHUP;
+
+ /* readable? */
+ if (!skb_queue_empty(&pdata->rcv_queue))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* Need to check for termination and startup */
+ if (sk->state==TCP_CLOSE)
+ mask |= POLLHUP;
+ /* connection hasn't started yet? */
+ if (sk->state == TCP_SYN_SENT)
+ return mask;
+
+ /* writable? */
+ if (sock_writeable(sk))
+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+ else
+ sk->socket->flags |= SO_NOSPACE;
+
+ return mask;
+}
+
/* Create the SPX specific data */
static int spx_sock_init(struct sock *sk)
{
@@ -403,6 +448,9 @@
int offset = ipx_if_offset(pdata->dest_addr.net);
int size = offset + sizeof(struct ipxspxhdr);
+ if (offset < 0) /* ENETUNREACH */
+ return(-ENETUNREACH);
+
save_flags(flags);
cli();
skb = sock_alloc_send_skb(sk, size, 1, 0, &err);
@@ -662,6 +710,7 @@
{
pdata->rmt_seq = ntohs(ipxh->spx.sequence);
pdata->rmt_ack = ntohs(ipxh->spx.ackseq);
+ pdata->alloc = pdata->rmt_seq + 3;
if(pdata->rmt_ack > 0 || pdata->rmt_ack == 0)
spx_retransmit_chk(pdata,pdata->rmt_ack, ACK);
@@ -856,7 +905,7 @@
sock_no_socketpair,
spx_accept,
spx_getname,
- datagram_poll, /* this does seqpacket too */
+ spx_datagram_poll,
spx_ioctl,
spx_listen,
spx_shutdown,
--------------DBC946C5A0A990BE7ACE10E1--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/