summaryrefslogtreecommitdiffstats
path: root/net/ipx
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-21 22:34:01 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-21 22:34:01 +0000
commit9e30c3705aed9fbec4c3304570e4d6e707856bcb (patch)
treeb19e6acb5a67af31a4e7742e05c2166dc3f1444c /net/ipx
parent72919904796333a20c6a5d5c380091b42e407aa9 (diff)
Merge with Linux 2.3.22.
Diffstat (limited to 'net/ipx')
-rw-r--r--net/ipx/af_spx.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/net/ipx/af_spx.c b/net/ipx/af_spx.c
index b9110c3ab..60dbdc288 100644
--- a/net/ipx/af_spx.c
+++ b/net/ipx/af_spx.c
@@ -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
@@ -36,6 +41,7 @@
#include <asm/uaccess.h>
#include <linux/uio.h>
#include <linux/unistd.h>
+#include <linux/poll.h>
static struct proto_ops *ipx_operations;
static struct proto_ops spx_ops;
@@ -49,6 +55,45 @@ void spx_rcv(struct sock *sk, int bytes);
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)
{
@@ -390,6 +435,9 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
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);
@@ -649,6 +697,7 @@ void spx_rcv(struct sock *sk, int bytes)
{
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);
@@ -842,7 +891,7 @@ static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
sock_no_socketpair,
spx_accept,
spx_getname,
- datagram_poll, /* this does seqpacket too */
+ spx_datagram_poll,
spx_ioctl,
spx_listen,
sock_no_shutdown,