* 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
* 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
#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;
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);
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 */
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;
+
+ MOD_INC_USE_COUNT;
- /*
- * Called on connection receive so cannot be GFP_KERNEL
- */
-
+ /* 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);
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;
}
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);
}
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 */
static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags)
+ int addr_len, int flags)
{
struct sock *sk = sock->sk;
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;
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;
}
/*
*/
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 */
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);
}
/* 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;
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. */
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)
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);
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 */
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;
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;
}
toss_skb: /* Catch All */
kfree_skb(skb);
-finish:
- return;
+out:;
}
/* Get message/packet data from user-land */
static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
- struct scm_cookie *scm)
+ struct scm_cookie *scm)
{
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 */
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);
- release_sock(sk);
-
- return (copied);
+out_release_sock:
+ release_sock(sk);
+out: return rc;
}
/*
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) = {
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 */
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() */
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");