Commit d28e0e20 authored by David S. Miller's avatar David S. Miller

SPX updates from Arnaldo Carvalho de Melo:

- CodingStyle cleanups
- Adds MODULE_LICENSE
- Fix missing release_sock calls
- Remove leftovers from sock cleanup patches
- Use skb_queue_purge
parent 04c1e5a1
......@@ -8,6 +8,7 @@
* Developers:
* Jay Schulist <jschlst@samba.org>
* Jim Freeman <jfree@caldera.com>
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* Changes:
* Alan Cox : Fixed an skb_unshare check for NULL
......@@ -22,6 +23,8 @@
* of the alloc count to follow rmt_seq.
* Arnaldo C. Melo : Use a private slabcache for the old tp_pinfo
* struct sock member, use spx_sk and ipx_sk
* Arnaldo C. Melo : Big CodingStyle cleanup, fixes some lock leaks,
* removes a leftover of the slabcache patch.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -44,7 +47,7 @@
#include <linux/unistd.h>
#include <linux/poll.h>
static struct proto_ops *ipx_operations;
static struct proto_ops *ipx_ops;
static struct proto_ops spx_ops;
static __u16 connids;
......@@ -60,7 +63,8 @@ extern void ipx_remove_socket(struct sock *sk);
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)
static unsigned int spx_datagram_poll(struct file * file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
struct spx_opt *pdata = spx_sk(sk);
......@@ -84,15 +88,14 @@ static unsigned int spx_datagram_poll(struct file * file, struct socket *sock, p
mask |= POLLHUP;
/* connection hasn't started yet? */
if (sk->state == TCP_SYN_SENT)
return mask;
goto out;
/* writable? */
if (sock_writeable(sk))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
else
set_bit(SOCK_ASYNC_NOSPACE,&sk->socket->flags);
return mask;
out: return mask;
}
/* Create the SPX specific data */
......@@ -123,43 +126,42 @@ static int spx_sock_init(struct sock *sk)
skb_queue_head_init(&pdata->transmit_queue);
skb_queue_head_init(&pdata->retransmit_queue);
return (0);
return 0;
}
static int spx_create(struct socket *sock, int protocol)
{
struct sock *sk;
int rc = -ENOMEM;
/*
* Called on connection receive so cannot be GFP_KERNEL
*/
MOD_INC_USE_COUNT;
/* Called on connection receive so cannot be GFP_KERNEL */
sk = sk_alloc(PF_IPX, GFP_ATOMIC, 1);
if(sk == NULL)
return (-ENOMEM);
if (!sk)
goto decmod;
switch(sock->type)
{
rc = -ESOCKTNOSUPPORT;
switch (sock->type) {
case SOCK_SEQPACKET:
sock->ops = &spx_ops;
break;
default:
sk_free(sk);
return (-ESOCKTNOSUPPORT);
goto out;
}
rc = 0;
sock_init_data(sock, sk);
spx_sock_init(sk);
sk->data_ready = spx_rcv;
sk->destruct = NULL;
sk->no_check = 1;
MOD_INC_USE_COUNT;
return (0);
out: return rc;
decmod: MOD_DEC_USE_COUNT;
goto out;
}
void spx_close_socket(struct sock *sk)
{
struct spx_opt *pdata = spx_sk(sk);
......@@ -173,18 +175,12 @@ void spx_close_socket(struct sock *sk)
void spx_destroy_socket(struct sock *sk)
{
struct spx_opt *pdata = spx_sk(sk);
struct sk_buff *skb;
ipx_remove_socket(sk);
while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
kfree_skb(skb);
while((skb = skb_dequeue(&pdata->transmit_queue)) != NULL)
kfree_skb(skb);
while((skb = skb_dequeue(&pdata->retransmit_queue)) != NULL)
kfree_skb(skb);
while((skb = skb_dequeue(&pdata->rcv_queue)) != NULL)
kfree_skb(skb);
skb_queue_purge(&sk->receive_queue);
skb_queue_purge(&pdata->transmit_queue);
skb_queue_purge(&pdata->retransmit_queue);
skb_queue_purge(&pdata->rcv_queue);
sk_free(sk);
MOD_DEC_USE_COUNT;
}
......@@ -195,14 +191,13 @@ static int spx_release(struct socket *sock)
struct sock *sk = sock->sk;
struct spx_opt *pdata = spx_sk(sk);
if(sk == NULL)
return (0);
if(!sk->dead)
if (!sk)
goto out;
if (!sk->dead)
sk->state_change(sk);
sk->dead = 1;
if(pdata->state != SPX_CLOSED)
{
if (pdata->state != SPX_CLOSED) {
spx_transmit(sk, NULL, DISCON, 0);
spx_close_socket(sk);
}
......@@ -210,87 +205,78 @@ static int spx_release(struct socket *sock)
sock->sk = NULL;
sk->socket = NULL;
spx_destroy_socket(sk);
return (0);
out: return 0;
}
/* Move a socket into listening state. */
static int spx_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
if(sock->state != SS_UNCONNECTED)
return (-EINVAL);
if(sock->type != SOCK_SEQPACKET)
return (-EOPNOTSUPP);
if(sk->zapped != 0)
return (-EAGAIN);
int rc = -EINVAL;
if (sock->state != SS_UNCONNECTED)
goto out;
rc = -EOPNOTSUPP;
if (sock->type != SOCK_SEQPACKET)
goto out;
rc = -EAGAIN;
if (sk->zapped)
goto out;
rc = 0;
sk->max_ack_backlog = backlog;
if(sk->state != TCP_LISTEN)
{
if (sk->state != TCP_LISTEN) {
sk->ack_backlog = 0;
sk->state = TCP_LISTEN;
}
sk->socket->flags |= __SO_ACCEPTCON;
return (0);
out: return rc;
}
/* Accept a pending SPX connection */
static int spx_accept(struct socket *sock, struct socket *newsock, int flags)
{
struct sock *sk;
struct sock *sk = sock->sk;
struct sock *newsk;
struct sk_buff *skb;
int err;
if(sock->sk == NULL)
return (-EINVAL);
sk = sock->sk;
if((sock->state != SS_UNCONNECTED) || !(sock->flags & __SO_ACCEPTCON))
return (-EINVAL);
if(sock->type != SOCK_SEQPACKET)
return (-EOPNOTSUPP);
if(sk->state != TCP_LISTEN)
return (-EINVAL);
int rc = -EINVAL;
if (!sk || sk->state != TCP_LISTEN ||
sock->state != SS_UNCONNECTED || !(sock->flags & __SO_ACCEPTCON))
goto out;
rc = -EOPNOTSUPP;
if (sock->type != SOCK_SEQPACKET)
goto out;
cli();
do {
skb = skb_dequeue(&sk->receive_queue);
if(skb == NULL)
{
if(flags & O_NONBLOCK)
{
sti();
return (-EWOULDBLOCK);
}
if (!skb) {
rc = -EWOULDBLOCK;
if (flags & O_NONBLOCK)
goto out_unlock;
interruptible_sleep_on(sk->sleep);
if(signal_pending(current))
{
sti();
return (-ERESTARTSYS);
}
rc = -ERESTARTSYS;
if (signal_pending(current))
goto out_unlock;
}
} while (skb == NULL);
} while (!skb);
newsk = skb->sk;
newsk->pair = NULL;
sti();
err = spx_transmit(newsk, skb, CONACK, 0); /* Connection ACK */
if(err)
return (err);
rc = spx_transmit(newsk, skb, CONACK, 0); /* Connection ACK */
if (rc)
goto out;
/* Now attach up the new socket */
sock->sk = NULL;
sk->ack_backlog--;
newsock->sk = newsk;
newsk->state = TCP_ESTABLISHED;
ipx_sk(newsk)->dest_addr = spx_sk(newsk)->dest_addr;
return (0);
out: return rc;
out_unlock:
sti();
goto out;
}
/* Build a connection to an SPX socket */
......@@ -301,20 +287,19 @@ static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
struct spx_opt *pdata = spx_sk(sk);
struct sockaddr_ipx src;
struct sk_buff *skb;
int size, err;
int size = sizeof(src);
int rc = ipx_ops->getname(sock, (struct sockaddr *)&src, &size, 0);
size = sizeof(src);
err = ipx_operations->getname(sock, (struct sockaddr *)&src, &size, 0);
if(err)
return (err);
if (rc)
goto out;
pdata->source_addr.net = src.sipx_network;
memcpy(pdata->source_addr.node, src.sipx_node, IPX_NODE_LEN);
pdata->source_addr.sock = (unsigned short)src.sipx_port;
err = ipx_operations->connect(sock, uaddr, addr_len, flags);
if(err)
return (err);
rc = ipx_ops->connect(sock, uaddr, addr_len, flags);
if (rc)
goto out;
pdata->dest_addr = ipx_sk(sk)->dest_addr;
pdata->state = SPX_CONNECTING;
......@@ -322,42 +307,36 @@ static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
sk->state = TCP_SYN_SENT;
/* Send Connection request */
err = spx_transmit(sk, NULL, CONREQ, 0);
if(err)
return (err);
rc = spx_transmit(sk, NULL, CONREQ, 0);
if (rc)
goto out;
cli();
do {
skb = skb_dequeue(&sk->receive_queue);
if(skb == NULL)
{
if(flags & O_NONBLOCK)
{
sti();
return (-EWOULDBLOCK);
}
if (!skb) {
rc = -EWOULDBLOCK;
if (flags & O_NONBLOCK)
goto unlock;
interruptible_sleep_on(sk->sleep);
if(signal_pending(current))
{
sti();
return (-ERESTARTSYS);
rc = -ERESTARTSYS;
if (signal_pending(current))
goto unlock;
}
}
} while (skb == NULL);
} while (!skb);
if(pdata->state == SPX_CLOSED)
{
sti();
rc = -ETIMEDOUT;
if (pdata->state == SPX_CLOSED) {
del_timer(&pdata->watchdog);
return (-ETIMEDOUT);
goto unlock;
}
rc = 0;
sock->state = SS_CONNECTED;
sk->state = TCP_ESTABLISHED;
kfree_skb(skb);
sti();
return (0);
unlock: sti();
out: return rc;
}
/*
......@@ -371,56 +350,59 @@ static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
*/
static inline unsigned long spx_calc_rtt(int tries)
{
if(tries < 1)
return (RETRY_TIME);
if(tries > 5)
return (MAX_RETRY_DELAY);
return (tries * HZ);
int rc;
if (tries < 1)
rc = RETRY_TIME;
else if (tries > 5)
rc = MAX_RETRY_DELAY;
else
rc = tries * HZ;
return rc;
}
static int spx_route_skb(struct spx_opt *pdata, struct sk_buff *skb, int type)
{
struct sk_buff *skb2;
int err = 0;
int rc = -ENOBUFS;
skb = skb_unshare(skb, GFP_ATOMIC);
if(skb == NULL)
return (-ENOBUFS);
switch(type)
{
case (CONREQ):
case (DATA):
if(!skb_queue_empty(&pdata->retransmit_queue))
{
if (!skb)
goto out;
rc = 0;
switch (type) {
case CONREQ:
case DATA:
if (!skb_queue_empty(&pdata->retransmit_queue)) {
skb_queue_tail(&pdata->transmit_queue, skb);
return 0;
goto out;
}
case (TQUEUE):
case TQUEUE: {
struct sk_buff *skb2;
pdata->retransmit.expires = jiffies + spx_calc_rtt(0);
add_timer(&pdata->retransmit);
skb2 = skb_clone(skb, GFP_NOIO);
if(skb2 == NULL)
return -ENOBUFS;
if (!skb2) {
rc = -ENOBUFS;
goto out;
}
skb_queue_tail(&pdata->retransmit_queue, skb2);
case (ACK):
case (CONACK):
case (WDREQ):
case (WDACK):
case (DISCON):
case (DISACK):
case (RETRAN):
default:
/* Send data */
err = ipxrtr_route_skb(skb);
if(err)
/* Fall thru */
}
case ACK:
case CONACK:
case WDREQ:
case WDACK:
case DISCON:
case DISACK:
case RETRAN:
default: /* Send data */
rc = ipxrtr_route_skb(skb);
if (rc)
kfree_skb(skb);
}
return (err);
out: return rc;
}
/* SPX packet transmit engine */
......@@ -429,25 +411,27 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
struct spx_opt *pdata = spx_sk(sk);
struct ipxspxhdr *ipxh;
unsigned long flags;
int err;
int rc;
if(skb == NULL)
{
if (!skb) {
int offset = ipx_if_offset(pdata->dest_addr.net);
int size = offset + sizeof(struct ipxspxhdr);
if (offset < 0) /* ENETUNREACH */
return(-ENETUNREACH);
rc = -ENETUNREACH;
if (offset < 0)
goto out;
save_flags(flags);
cli();
skb = sock_alloc_send_skb(sk, size, 0, &err);
if(skb == NULL) {
rc = -ENOMEM;
if (!skb) {
restore_flags(flags);
return (-ENOMEM);
goto out;
}
skb_reserve(skb, offset);
skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
skb->h.raw = skb->nh.raw =
skb_put(skb, sizeof(struct ipxspxhdr));
restore_flags(flags);
}
......@@ -471,40 +455,39 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
/* Reset/Set WD timer */
mod_timer(&pdata->watchdog, jiffies+VERIFY_TIMEOUT);
switch(type)
{
case (DATA): /* Data */
switch (type) {
case DATA: /* Data */
ipxh->ipx.ipx_pktsize = htons(SPX_SYS_PKT_LEN + len);
ipxh->spx.cctl = (CCTL_ACK | CCTL_EOM);
pdata->sequence++;
break;
case (ACK): /* ACK */
case ACK: /* ACK */
pdata->rmt_seq++;
case (WDACK): /* WD ACK */
case (CONACK): /* Connection ACK */
case WDACK: /* WD ACK */
case CONACK: /* Connection ACK */
ipxh->spx.cctl = CCTL_SYS;
ipxh->spx.ackseq = htons(pdata->rmt_seq);
break;
case (CONREQ): /* Connection Request */
case CONREQ: /* Connection Request */
del_timer(&pdata->watchdog);
case (WDREQ): /* WD Request */
case WDREQ: /* WD Request */
pdata->source_connid = htons(connids++);
pdata->dest_connid = 0xFFFF;
pdata->alloc = 3 + pdata->rmt_seq;
ipxh->spx.cctl = (CCTL_ACK | CCTL_SYS);
ipxh->spx.cctl = CCTL_ACK | CCTL_SYS;
ipxh->spx.sconn = pdata->source_connid;
ipxh->spx.dconn = pdata->dest_connid;
ipxh->spx.allocseq = htons(pdata->alloc);
break;
case (DISCON): /* Informed Disconnect */
case DISCON: /* Informed Disconnect */
ipxh->spx.cctl = CCTL_ACK;
ipxh->spx.dtype = SPX_DTYPE_ECONN;
break;
case (DISACK): /* Informed Disconnect ACK */
case DISACK: /* Informed Disconnect ACK */
ipxh->spx.cctl = 0;
ipxh->spx.dtype = SPX_DTYPE_ECACK;
ipxh->spx.sequence = 0;
......@@ -512,11 +495,13 @@ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
break;
default:
return (-EOPNOTSUPP);
rc = -EOPNOTSUPP;
goto out;
}
/* Send data */
return (spx_route_skb(pdata, skb, type));
rc = spx_route_skb(pdata, skb, type);
out: return rc;
}
/* Check the state of the connection and send a WD request if needed. */
......@@ -526,19 +511,16 @@ static void spx_watchdog(unsigned long data)
struct spx_opt *pdata = spx_sk(sk);
del_timer(&pdata->watchdog);
if(pdata->state == SPX_CLOSED)
return;
if(pdata->retries > pdata->max_retries)
{
if (pdata->state == SPX_CLOSED)
goto out;
if (pdata->retries > pdata->max_retries) {
spx_close_socket(sk); /* Unilateral Abort */
return;
goto out;
}
/* Send WD request */
spx_transmit(sk, NULL, WDREQ, 0);
pdata->retries++;
return;
out:;
}
static void spx_retransmit(unsigned long data)
......@@ -547,22 +529,19 @@ static void spx_retransmit(unsigned long data)
struct spx_opt *pdata = spx_sk(sk);
struct sk_buff *skb;
unsigned long flags;
int err;
del_timer(&pdata->retransmit);
if(pdata->state == SPX_CLOSED)
return;
if(pdata->retransmits > RETRY_COUNT)
{
if (pdata->state == SPX_CLOSED)
goto out;
if (pdata->retransmits > RETRY_COUNT) {
spx_close_socket(sk); /* Unilateral Abort */
return;
goto out;
}
/* Need to leave skb on the queue, aye the fear */
save_flags(flags);
cli();
skb = skb_peek(&pdata->retransmit_queue);
if(skb_cloned(skb))
if (skb_cloned(skb))
skb = skb_copy(skb, GFP_ATOMIC);
else
skb = skb_clone(skb, GFP_ATOMIC);
......@@ -571,67 +550,60 @@ static void spx_retransmit(unsigned long data)
pdata->retransmit.expires = jiffies + spx_calc_rtt(pdata->retransmits);
add_timer(&pdata->retransmit);
err = spx_route_skb(pdata, skb, RETRAN);
spx_route_skb(pdata, skb, RETRAN);
pdata->retransmits++;
return;
out:;
}
/* Check packet for retransmission, ConReqAck aware */
static int spx_retransmit_chk(struct spx_opt *pdata, int ackseq, int type)
{
struct ipxspxhdr *ipxh;
struct sk_buff *skb;
skb = skb_dequeue(&pdata->retransmit_queue);
if(!skb)
return (-ENOENT);
int rc = -ENOENT;
struct sk_buff *skb = skb_dequeue(&pdata->retransmit_queue);
if (!skb)
goto out;
rc = 0;
/* Check Data/ACK seq */
switch(type)
{
switch (type) {
case ACK: /* Check Sequence, Should == 1 */
ipxh = (struct ipxspxhdr *)skb->nh.raw;
if(!(ntohs(ipxh->spx.sequence) - htons(ackseq)))
if (!(ntohs(ipxh->spx.sequence) - htons(ackseq)))
break;
case CONACK:
del_timer(&pdata->retransmit);
pdata->retransmits = 0;
kfree_skb(skb);
if(skb_queue_empty(&pdata->retransmit_queue))
{
if (skb_queue_empty(&pdata->retransmit_queue)) {
skb = skb_dequeue(&pdata->transmit_queue);
if(skb != NULL)
if (skb)
spx_route_skb(pdata, skb, TQUEUE);
}
return (0);
goto out;
}
skb_queue_head(&pdata->retransmit_queue, skb);
return (-1);
rc = -1;
out: return rc;
}
/* SPX packet receive engine */
void spx_rcv(struct sock *sk, int bytes)
{
struct sk_buff *skb;
struct ipxspxhdr *ipxh;
struct spx_opt *pdata = spx_sk(sk);
struct sk_buff *skb = skb_dequeue(&sk->receive_queue);
skb = skb_dequeue(&sk->receive_queue);
if(skb == NULL)
return;
if (!skb)
goto out;
ipxh = (struct ipxspxhdr *)skb->nh.raw;
/* Can't receive on a closed connection */
if((pdata->state == SPX_CLOSED) && (ipxh->spx.sequence != 0))
goto toss_skb;
if(ntohs(ipxh->ipx.ipx_pktsize) < SPX_SYS_PKT_LEN)
goto toss_skb;
if(ipxh->ipx.ipx_type != IPX_TYPE_SPX)
goto toss_skb;
if(ntohs(ipxh->spx.ackseq) > pdata->sequence)
if ((pdata->state == SPX_CLOSED && ipxh->spx.sequence) ||
ntohs(ipxh->ipx.ipx_pktsize) < SPX_SYS_PKT_LEN ||
ipxh->ipx.ipx_type != IPX_TYPE_SPX ||
ntohs(ipxh->spx.ackseq) > pdata->sequence)
goto toss_skb;
/* Reset WD timer on any received packet */
......@@ -640,13 +612,11 @@ void spx_rcv(struct sock *sk, int bytes)
pdata->watchdog.expires = jiffies + ABORT_TIMEOUT;
add_timer(&pdata->watchdog);
switch(ipxh->spx.cctl)
{
switch (ipxh->spx.cctl) {
case (CCTL_SYS | CCTL_ACK):
if((ipxh->spx.sequence == 0) /* ConReq */
&& (ipxh->spx.ackseq == 0)
&& (ipxh->spx.dconn == 0xFFFF))
{
if (!ipxh->spx.sequence && /* ConReq */
!ipxh->spx.ackseq &&
ipxh->spx.dconn == 0xFFFF) {
pdata->state = SPX_CONNECTED;
pdata->dest_addr = ipxh->ipx.ipx_source;
pdata->source_addr = ipxh->ipx.ipx_dest;
......@@ -655,63 +625,57 @@ void spx_rcv(struct sock *sk, int bytes)
skb_queue_tail(&sk->receive_queue, skb);
wake_up_interruptible(sk->sleep);
}
else /* WD Request */
} else /* WD Request */
spx_transmit(sk, skb, WDACK, 0);
goto finish;
goto out;
case CCTL_SYS: /* ACK */
if((ipxh->spx.dtype == 0) /* ConReq ACK */
&& (ipxh->spx.sconn != 0xFFFF)
&& (ipxh->spx.dconn != 0xFFFF)
&& (ipxh->spx.sequence == 0)
&& (ipxh->spx.ackseq == 0)
&& (pdata->state != SPX_CONNECTED))
{
if (!ipxh->spx.dtype && /* ConReq ACK */
ipxh->spx.sconn != 0xFFFF &&
ipxh->spx.dconn != 0xFFFF &&
!ipxh->spx.sequence &&
!ipxh->spx.ackseq &&
pdata->state != SPX_CONNECTED) {
pdata->state = SPX_CONNECTED;
pdata->dest_connid = ipxh->spx.sconn;
if(spx_retransmit_chk(pdata, 0, CONACK) < 0)
if (spx_retransmit_chk(pdata, 0, CONACK) < 0)
goto toss_skb;
skb_queue_tail(&sk->receive_queue, skb);
wake_up_interruptible(sk->sleep);
goto finish;
goto out;
}
spx_retransmit_chk(pdata, ipxh->spx.ackseq, ACK);
goto toss_skb;
case (CCTL_ACK):
case CCTL_ACK:
/* Informed Disconnect */
if(ipxh->spx.dtype == SPX_DTYPE_ECONN)
{
if (ipxh->spx.dtype == SPX_DTYPE_ECONN) {
spx_transmit(sk, skb, DISACK, 0);
spx_close_socket(sk);
goto finish;
goto out;
}
/* Fall through */
default:
if(ntohs(ipxh->spx.sequence) == pdata->rmt_seq)
{
if (ntohs(ipxh->spx.sequence) == pdata->rmt_seq) {
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);
if (pdata->rmt_ack > 0 || !pdata->rmt_ack)
spx_retransmit_chk(pdata,
pdata->rmt_ack, ACK);
skb_queue_tail(&pdata->rcv_queue, skb);
wake_up_interruptible(sk->sleep);
if(ipxh->spx.cctl&CCTL_ACK)
if (ipxh->spx.cctl&CCTL_ACK)
spx_transmit(sk, NULL, ACK, 0);
goto finish;
goto out;
}
if(ipxh->spx.dtype == SPX_DTYPE_ECACK)
{
if(pdata->state != SPX_CLOSED)
if (ipxh->spx.dtype == SPX_DTYPE_ECACK) {
if (pdata->state != SPX_CLOSED)
spx_close_socket(sk);
goto toss_skb;
}
......@@ -719,8 +683,7 @@ void spx_rcv(struct sock *sk, int bytes)
toss_skb: /* Catch All */
kfree_skb(skb);
finish:
return;
out:;
}
/* Get message/packet data from user-land */
......@@ -730,40 +693,38 @@ static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct sock *sk = sock->sk;
int flags = msg->msg_flags;
struct sk_buff *skb;
int err, offset, size;
int offset, size, rc = -EMSGSIZE;
if(len > 534)
return (-EMSGSIZE);
if(sk->zapped)
return (-ENOTCONN); /* Socket not bound */
if(flags&~MSG_DONTWAIT)
return (-EINVAL);
if (len > 534)
goto out;
rc = -ENOTCONN; /* Socket not bound */
if (sk->zapped)
goto out;
rc = -EINVAL;
if (flags & ~MSG_DONTWAIT)
goto out;
offset = ipx_if_offset(spx_sk(sk)->dest_addr.net);
size = offset + sizeof(struct ipxspxhdr) + len;
cli();
skb = sock_alloc_send_skb(sk, size, flags&MSG_DONTWAIT, &err);
skb = sock_alloc_send_skb(sk, size, flags&MSG_DONTWAIT, &rc);
sti();
if(skb == NULL)
return (err);
if (!skb)
goto out;
skb->sk = sk;
skb_reserve(skb, offset);
skb->h.raw = skb->nh.raw = skb_put(skb, sizeof(struct ipxspxhdr));
err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if(err)
{
rc = -EFAULT;
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
kfree_skb(skb);
return (-EFAULT);
goto out;
}
err = spx_transmit(sk, skb, DATA, len);
if(err)
return (-EAGAIN);
return (len);
rc = len;
if (!spx_transmit(sk, skb, DATA, len))
rc = -EAGAIN;
out: return rc;
}
/* Send message/packet data to user-land */
......@@ -775,70 +736,67 @@ static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
struct sock *sk = sock->sk;
struct spx_opt *pdata = spx_sk(sk);
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;
int copied, err;
if(sk->zapped)
return (-ENOTCONN); /* Socket not bound */
int copied, rc = -ENOTCONN;
if (sk->zapped) /* Socket not bound */
goto out;
lock_sock(sk);
restart:
while(skb_queue_empty(&pdata->rcv_queue)) /* No data */
{
while (skb_queue_empty(&pdata->rcv_queue)) { /* No data */
/* Socket errors? */
err = sock_error(sk);
if(err)
return (err);
rc = sock_error(sk);
if (rc)
goto out_release_sock;
/* Socket shut down? */
if(sk->shutdown & RCV_SHUTDOWN)
return (-ESHUTDOWN);
rc = -ESHUTDOWN;
if (sk->shutdown & RCV_SHUTDOWN)
goto out_release_sock;
/* handle signals */
if(signal_pending(current))
return (-ERESTARTSYS);
rc = -ERESTARTSYS;
if (signal_pending(current))
goto out_release_sock;
/* User doesn't want to wait */
if(flags&MSG_DONTWAIT)
return (-EAGAIN);
rc = -EAGAIN;
if (flags & MSG_DONTWAIT)
goto out_release_sock;
release_sock(sk);
save_flags(flags);
cli();
if(skb_peek(&pdata->rcv_queue) == NULL)
if (!skb_peek(&pdata->rcv_queue))
interruptible_sleep_on(sk->sleep);
restore_flags(flags);
lock_sock(sk);
}
skb = skb_dequeue(&pdata->rcv_queue);
if(skb == NULL)
if (!skb)
goto restart;
ispxh = (struct ipxspxhdr *)skb->nh.raw;
copied = ntohs(ispxh->ipx.ipx_pktsize) - SPX_SYS_PKT_LEN;
if(copied > size)
{
if (copied > size) {
copied = size;
msg->msg_flags |= MSG_TRUNC;
}
err = memcpy_toiovec(msg->msg_iov, skb->nh.raw+SPX_SYS_PKT_LEN, copied);
if(err)
return (-EFAULT);
rc = -EFAULT;
if (memcpy_toiovec(msg->msg_iov, skb->nh.raw + SPX_SYS_PKT_LEN, copied))
goto out_kfree_skb;
msg->msg_namelen = sizeof(*sipx);
if(sipx)
{
if (sipx) {
sipx->sipx_family = AF_IPX;
sipx->sipx_port = ispxh->ipx.ipx_source.sock;
memcpy(sipx->sipx_node,ispxh->ipx.ipx_source.node,IPX_NODE_LEN);
sipx->sipx_network = ispxh->ipx.ipx_source.net;
sipx->sipx_type = ispxh->ipx.ipx_type;
}
rc = copied;
out_kfree_skb:
kfree_skb(skb);
out_release_sock:
release_sock(sk);
return (copied);
out: return rc;
}
/*
......@@ -847,41 +805,31 @@ static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
static int spx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
int err;
err = ipx_operations->bind(sock, uaddr, addr_len);
return (err);
return ipx_ops->bind(sock, uaddr, addr_len);
}
static int spx_getname (struct socket *sock, struct sockaddr *uaddr,
int *usockaddr_len, int peer)
{
int err;
err = ipx_operations->getname(sock, uaddr, usockaddr_len, peer);
return (err);
return ipx_ops->getname(sock, uaddr, usockaddr_len, peer);
}
static int spx_ioctl (struct socket *sock, unsigned int cmd,
unsigned long arg)
{
int err;
err = ipx_operations->ioctl(sock, cmd, arg);
return (err);
return ipx_ops->ioctl(sock, cmd, arg);
}
static int spx_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
int err;
err = ipx_operations->setsockopt(sock, level, optname, optval, optlen);
return (err);
return ipx_ops->setsockopt(sock, level, optname, optval, optlen);
}
static int spx_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen)
{
int err;
err = ipx_operations->getsockopt(sock, level, optname, optval, optlen);
return (err);
return ipx_ops->getsockopt(sock, level, optname, optval, optlen);
}
static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
......@@ -911,16 +859,13 @@ SOCKOPS_WRAP(spx, PF_IPX);
static struct net_proto_family spx_family_ops = {
family: PF_IPX,
create: spx_create,
sk_size: sizeof(struct sock) + sizeof(struct ipx_opt) +
sizeof(struct spx_opt),
};
static char banner[] __initdata = KERN_INFO "NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0\n";
static char banner[] __initdata =
KERN_INFO "NET4: Sequenced Packet eXchange (SPX) 0.03\n";
static int __init spx_proto_init(void)
{
int error;
connids = (__u16)jiffies; /* initalize random */
/* allocate our sock slab cache */
......@@ -933,8 +878,7 @@ static int __init spx_proto_init(void)
printk(KERN_CRIT __FUNCTION__
": Cannot create spx_sock SLAB cache!\n");
error = ipx_register_spx(&ipx_operations, &spx_family_ops);
if (error)
if (ipx_register_spx(&ipx_ops, &spx_family_ops))
printk(KERN_ERR "SPX: unable to register with IPX.\n");
/* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
......@@ -942,11 +886,12 @@ static int __init spx_proto_init(void)
printk(banner);
return 0;
}
module_init(spx_proto_init);
static void __exit spx_proto_finito(void)
{
ipx_unregister_spx();
return;
}
module_init(spx_proto_init);
module_exit(spx_proto_finito);
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment