Messages in this thread Patch in this message | | | Date | Mon, 11 Oct 1999 16:52:31 -0300 | From | Eduardo Trapani <> | Subject | PATCH: SPX 0.2 for Linux 2.2.12 |
| |
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.--- 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, | |