2 * This module implements the (SPP-derived) Sequenced Packet eXchange
3 * (SPX) protocol for Linux 2.1.X as specified in
4 * NetWare SPX Services Specification, Semantics and API
6 * Revision Date: February 9, 1993
9 * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
10 * Jim Freeman <jfree@caldera.com>
13 * Alan Cox : Fixed an skb_unshare check for NULL
14 * that crashed it under load. Renamed and
15 * made static the ipx ops. Removed the hack
16 * ipx methods interface. Dropped AF_SPX - its
17 * the wrong abstraction.
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
24 * None of the authors or maintainers or their employers admit
25 * liability nor provide warranty for any of this software.
26 * This material is provided "as is" and at no charge.
29 #include <linux/config.h>
30 #if defined(CONFIG_SPX) || defined(CONFIG_SPX_MODULE)
31 #include <linux/module.h>
35 #include <asm/byteorder.h>
36 #include <asm/uaccess.h>
37 #include <linux/uio.h>
38 #include <linux/unistd.h>
40 static struct proto_ops
*ipx_operations
;
41 static struct proto_ops spx_ops
;
44 /* Functions needed for SPX connection start up */
45 static int spx_transmit(struct sock
*sk
,struct sk_buff
*skb
,int type
,int len
);
46 static void spx_retransmit(unsigned long data
);
47 static void spx_watchdog(unsigned long data
);
48 void spx_rcv(struct sock
*sk
, int bytes
);
50 extern void ipx_remove_socket(struct sock
*sk
);
52 /* Create the SPX specific data */
53 static int spx_sock_init(struct sock
*sk
)
55 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
57 pdata
->state
= SPX_CLOSED
;
59 pdata
->acknowledge
= 0;
60 pdata
->source_connid
= htons(connids
);
64 pdata
->owner
= (void *)sk
;
65 pdata
->sndbuf
= sk
->sndbuf
;
67 pdata
->watchdog
.function
= spx_watchdog
;
68 pdata
->watchdog
.data
= (unsigned long)sk
;
69 pdata
->wd_interval
= VERIFY_TIMEOUT
;
70 pdata
->retransmit
.function
= spx_retransmit
;
71 pdata
->retransmit
.data
= (unsigned long)sk
;
72 pdata
->retransmits
= 0;
74 pdata
->max_retries
= RETRY_COUNT
;
76 skb_queue_head_init(&pdata
->rcv_queue
);
77 skb_queue_head_init(&pdata
->transmit_queue
);
78 skb_queue_head_init(&pdata
->retransmit_queue
);
83 static int spx_create(struct socket
*sock
, int protocol
)
88 * Called on connection receive so cannot be GFP_KERNEL
91 sk
= sk_alloc(PF_IPX
, GFP_ATOMIC
, 1);
102 return (-ESOCKTNOSUPPORT
);
105 sock_init_data(sock
, sk
);
107 sk
->data_ready
= spx_rcv
;
117 void spx_close_socket(struct sock
*sk
)
119 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
121 pdata
->state
= SPX_CLOSED
;
122 sk
->state
= TCP_CLOSE
;
123 del_timer(&pdata
->retransmit
);
124 del_timer(&pdata
->watchdog
);
127 void spx_destroy_socket(struct sock
*sk
)
129 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
132 ipx_remove_socket(sk
);
133 while((skb
= skb_dequeue(&sk
->receive_queue
)) != NULL
)
135 while((skb
= skb_dequeue(&pdata
->transmit_queue
)) != NULL
)
137 while((skb
= skb_dequeue(&pdata
->retransmit_queue
)) != NULL
)
139 while((skb
= skb_dequeue(&pdata
->rcv_queue
)) != NULL
)
146 /* Release an SPX socket */
147 static int spx_release(struct socket
*sock
)
149 struct sock
*sk
= sock
->sk
;
150 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
155 sk
->state_change(sk
);
158 if(pdata
->state
!= SPX_CLOSED
)
160 spx_transmit(sk
, NULL
, DISCON
, 0);
161 spx_close_socket(sk
);
166 spx_destroy_socket(sk
);
171 /* Move a socket into listening state. */
172 static int spx_listen(struct socket
*sock
, int backlog
)
174 struct sock
*sk
= sock
->sk
;
176 if(sock
->state
!= SS_UNCONNECTED
)
178 if(sock
->type
!= SOCK_SEQPACKET
)
179 return (-EOPNOTSUPP
);
183 sk
->max_ack_backlog
= backlog
;
184 if(sk
->state
!= TCP_LISTEN
)
187 sk
->state
= TCP_LISTEN
;
189 sk
->socket
->flags
|= SO_ACCEPTCON
;
194 /* Accept a pending SPX connection */
195 static int spx_accept(struct socket
*sock
, struct socket
*newsock
, int flags
)
206 if((sock
->state
!= SS_UNCONNECTED
) || !(sock
->flags
& SO_ACCEPTCON
))
208 if(sock
->type
!= SOCK_SEQPACKET
)
209 return (-EOPNOTSUPP
);
210 if(sk
->state
!= TCP_LISTEN
)
215 skb
= skb_dequeue(&sk
->receive_queue
);
218 if(flags
& O_NONBLOCK
)
221 return (-EWOULDBLOCK
);
223 interruptible_sleep_on(sk
->sleep
);
224 if(signal_pending(current
))
227 return (-ERESTARTSYS
);
230 } while (skb
== NULL
);
236 err
= spx_transmit(newsk
, skb
, CONACK
, 0); /* Connection ACK */
240 /* Now attach up the new socket */
244 newsk
->state
= TCP_ESTABLISHED
;
245 newsk
->protinfo
.af_ipx
.dest_addr
= newsk
->tp_pinfo
.af_spx
.dest_addr
;
250 /* Build a connection to an SPX socket */
251 static int spx_connect(struct socket
*sock
, struct sockaddr
*uaddr
,
252 int addr_len
, int flags
)
254 struct sock
*sk
= sock
->sk
;
255 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
256 struct sockaddr_ipx src
;
261 err
= ipx_operations
->getname(sock
, (struct sockaddr
*)&src
, &size
, 0);
265 pdata
->source_addr
.net
= src
.sipx_network
;
266 memcpy(pdata
->source_addr
.node
, src
.sipx_node
, IPX_NODE_LEN
);
267 pdata
->source_addr
.sock
= (unsigned short)src
.sipx_port
;
269 err
= ipx_operations
->connect(sock
, uaddr
, addr_len
, flags
);
273 pdata
->dest_addr
= sk
->protinfo
.af_ipx
.dest_addr
;
274 pdata
->state
= SPX_CONNECTING
;
275 sock
->state
= SS_CONNECTING
;
276 sk
->state
= TCP_SYN_SENT
;
278 /* Send Connection request */
279 err
= spx_transmit(sk
, NULL
, CONREQ
, 0);
285 skb
= skb_dequeue(&sk
->receive_queue
);
288 if(flags
& O_NONBLOCK
)
291 return (-EWOULDBLOCK
);
293 interruptible_sleep_on(sk
->sleep
);
294 if(signal_pending(current
))
297 return (-ERESTARTSYS
);
300 } while (skb
== NULL
);
302 if(pdata
->state
== SPX_CLOSED
)
305 del_timer(&pdata
->watchdog
);
309 sock
->state
= SS_CONNECTED
;
310 sk
->state
= TCP_ESTABLISHED
;
318 * Calculate the timeout for a packet. Thankfully SPX has a large
319 * fudge factor (3/4 secs) and does not pay much attention to RTT.
320 * As we simply have a default retry time of 1*HZ and a max retry
321 * time of 5*HZ. Between those values we increase the timeout based
322 * on the number of retransmit tries.
324 * FixMe: This is quite fake, but will work for now. (JS)
326 static inline unsigned long spx_calc_rtt(int tries
)
331 return (MAX_RETRY_DELAY
);
335 static int spx_route_skb(struct spx_opt
*pdata
, struct sk_buff
*skb
, int type
)
337 struct sk_buff
*skb2
;
340 skb
= skb_unshare(skb
, GFP_ATOMIC
);
348 if(!skb_queue_empty(&pdata
->retransmit_queue
))
350 skb_queue_tail(&pdata
->transmit_queue
, skb
);
355 pdata
->retransmit
.expires
= jiffies
+ spx_calc_rtt(0);
356 add_timer(&pdata
->retransmit
);
358 skb2
= skb_clone(skb
, GFP_BUFFER
);
361 skb_queue_tail(&pdata
->retransmit_queue
, skb2
);
372 err
= ipxrtr_route_skb(skb
);
380 /* SPX packet transmit engine */
381 static int spx_transmit(struct sock
*sk
, struct sk_buff
*skb
, int type
, int len
)
383 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
384 struct ipxspxhdr
*ipxh
;
390 int offset
= ipx_if_offset(pdata
->dest_addr
.net
);
391 int size
= offset
+ sizeof(struct ipxspxhdr
);
395 skb
= sock_alloc_send_skb(sk
, size
, 1, 0, &err
);
398 skb_reserve(skb
, offset
);
399 skb
->h
.raw
= skb
->nh
.raw
= skb_put(skb
,sizeof(struct ipxspxhdr
));
400 restore_flags(flags
);
404 ipxh
= (struct ipxspxhdr
*)skb
->nh
.raw
;
405 ipxh
->ipx
.ipx_checksum
= 0xFFFF;
406 ipxh
->ipx
.ipx_pktsize
= htons(SPX_SYS_PKT_LEN
);
407 ipxh
->ipx
.ipx_tctrl
= 0;
408 ipxh
->ipx
.ipx_type
= IPX_TYPE_SPX
;
409 ipxh
->ipx
.ipx_dest
= pdata
->dest_addr
;
410 ipxh
->ipx
.ipx_source
= pdata
->source_addr
;
414 ipxh
->spx
.sequence
= htons(pdata
->sequence
);
415 ipxh
->spx
.ackseq
= htons(pdata
->rmt_seq
);
416 ipxh
->spx
.sconn
= pdata
->source_connid
;
417 ipxh
->spx
.dconn
= pdata
->dest_connid
;
418 ipxh
->spx
.allocseq
= htons(pdata
->alloc
);
420 /* Reset/Set WD timer */
421 del_timer(&pdata
->watchdog
);
422 pdata
->watchdog
.expires
= jiffies
+ VERIFY_TIMEOUT
;
423 add_timer(&pdata
->watchdog
);
427 case (DATA
): /* Data */
428 ipxh
->ipx
.ipx_pktsize
= htons(SPX_SYS_PKT_LEN
+ len
);
429 ipxh
->spx
.cctl
= (CCTL_ACK
| CCTL_EOM
);
433 case (ACK
): /* ACK */
435 case (WDACK
): /* WD ACK */
436 case (CONACK
): /* Connection ACK */
437 ipxh
->spx
.cctl
= CCTL_SYS
;
438 ipxh
->spx
.ackseq
= htons(pdata
->rmt_seq
);
441 case (CONREQ
): /* Connection Request */
442 del_timer(&pdata
->watchdog
);
443 case (WDREQ
): /* WD Request */
444 pdata
->source_connid
= htons(connids
++);
445 pdata
->dest_connid
= 0xFFFF;
446 pdata
->alloc
= 3 + pdata
->rmt_seq
;
447 ipxh
->spx
.cctl
= (CCTL_ACK
| CCTL_SYS
);
448 ipxh
->spx
.sconn
= pdata
->source_connid
;
449 ipxh
->spx
.dconn
= pdata
->dest_connid
;
450 ipxh
->spx
.allocseq
= htons(pdata
->alloc
);
453 case (DISCON
): /* Informed Disconnect */
454 ipxh
->spx
.cctl
= CCTL_ACK
;
455 ipxh
->spx
.dtype
= SPX_DTYPE_ECONN
;
458 case (DISACK
): /* Informed Disconnect ACK */
460 ipxh
->spx
.dtype
= SPX_DTYPE_ECACK
;
461 ipxh
->spx
.sequence
= 0;
462 ipxh
->spx
.ackseq
= htons(pdata
->rmt_seq
++);
466 return (-EOPNOTSUPP
);
470 return (spx_route_skb(pdata
, skb
, type
));
473 /* Check the state of the connection and send a WD request if needed. */
474 static void spx_watchdog(unsigned long data
)
476 struct sock
*sk
= (struct sock
*)data
;
477 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
479 del_timer(&pdata
->watchdog
);
480 if(pdata
->state
== SPX_CLOSED
)
482 if(pdata
->retries
> pdata
->max_retries
)
484 spx_close_socket(sk
); /* Unilateral Abort */
488 /* Send WD request */
489 spx_transmit(sk
, NULL
, WDREQ
, 0);
495 static void spx_retransmit(unsigned long data
)
497 struct sock
*sk
= (struct sock
*)data
;
498 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
503 del_timer(&pdata
->retransmit
);
504 if(pdata
->state
== SPX_CLOSED
)
506 if(pdata
->retransmits
> RETRY_COUNT
)
508 spx_close_socket(sk
); /* Unilateral Abort */
512 /* Need to leave skb on the queue, aye the fear */
515 skb
= skb_peek(&pdata
->retransmit_queue
);
517 skb
= skb_copy(skb
, GFP_ATOMIC
);
519 skb
= skb_clone(skb
, GFP_ATOMIC
);
520 restore_flags(flags
);
522 pdata
->retransmit
.expires
= jiffies
+ spx_calc_rtt(pdata
->retransmits
);
523 add_timer(&pdata
->retransmit
);
525 err
= spx_route_skb(pdata
, skb
, RETRAN
);
526 pdata
->retransmits
++;
531 /* Check packet for retransmission, ConReqAck aware */
532 static int spx_retransmit_chk(struct spx_opt
*pdata
, int ackseq
, int type
)
534 struct ipxspxhdr
*ipxh
;
537 skb
= skb_dequeue(&pdata
->retransmit_queue
);
541 /* Check Data/ACK seq */
544 case ACK
: /* Check Sequence, Should == 1 */
545 ipxh
= (struct ipxspxhdr
*)skb
->nh
.raw
;
546 if(!(ntohs(ipxh
->spx
.sequence
) - htons(ackseq
)))
550 del_timer(&pdata
->retransmit
);
551 pdata
->retransmits
= 0;
553 if(skb_queue_empty(&pdata
->retransmit_queue
))
555 skb
= skb_dequeue(&pdata
->transmit_queue
);
557 spx_route_skb(pdata
, skb
, TQUEUE
);
562 skb_queue_head(&pdata
->retransmit_queue
, skb
);
566 /* SPX packet receive engine */
567 void spx_rcv(struct sock
*sk
, int bytes
)
570 struct ipxspxhdr
*ipxh
;
571 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
573 skb
= skb_dequeue(&sk
->receive_queue
);
576 ipxh
= (struct ipxspxhdr
*)skb
->nh
.raw
;
578 /* Can't receive on a closed connection */
579 if((pdata
->state
== SPX_CLOSED
) && (ipxh
->spx
.sequence
!= 0))
581 if(ntohs(ipxh
->ipx
.ipx_pktsize
) < SPX_SYS_PKT_LEN
)
583 if(ipxh
->ipx
.ipx_type
!= IPX_TYPE_SPX
)
585 if(ntohs(ipxh
->spx
.ackseq
) > pdata
->sequence
)
588 /* Reset WD timer on any received packet */
589 del_timer(&pdata
->watchdog
);
591 pdata
->watchdog
.expires
= jiffies
+ ABORT_TIMEOUT
;
592 add_timer(&pdata
->watchdog
);
594 switch(ipxh
->spx
.cctl
)
596 case (CCTL_SYS
| CCTL_ACK
):
597 if((ipxh
->spx
.sequence
== 0) /* ConReq */
598 && (ipxh
->spx
.ackseq
== 0)
599 && (ipxh
->spx
.dconn
== 0xFFFF))
601 pdata
->state
= SPX_CONNECTED
;
602 pdata
->dest_addr
= ipxh
->ipx
.ipx_source
;
603 pdata
->source_addr
= ipxh
->ipx
.ipx_dest
;
604 pdata
->dest_connid
= ipxh
->spx
.sconn
;
605 pdata
->alloc
= 3 + ntohs(ipxh
->spx
.sequence
);
607 skb_queue_tail(&sk
->receive_queue
, skb
);
608 wake_up_interruptible(sk
->sleep
);
610 else /* WD Request */
611 spx_transmit(sk
, skb
, WDACK
, 0);
614 case CCTL_SYS
: /* ACK */
615 if((ipxh
->spx
.dtype
== 0) /* ConReq ACK */
616 && (ipxh
->spx
.sconn
!= 0xFFFF)
617 && (ipxh
->spx
.dconn
!= 0xFFFF)
618 && (ipxh
->spx
.sequence
== 0)
619 && (ipxh
->spx
.ackseq
== 0)
620 && (pdata
->state
!= SPX_CONNECTED
))
622 pdata
->state
= SPX_CONNECTED
;
623 pdata
->dest_connid
= ipxh
->spx
.sconn
;
625 if(spx_retransmit_chk(pdata
, 0, CONACK
) < 0)
628 skb_queue_tail(&sk
->receive_queue
, skb
);
629 wake_up_interruptible(sk
->sleep
);
633 spx_retransmit_chk(pdata
, ipxh
->spx
.ackseq
, ACK
);
637 /* Informed Disconnect */
638 if(ipxh
->spx
.dtype
== SPX_DTYPE_ECONN
)
641 spx_transmit(sk
, skb
, DISACK
, 0);
642 spx_close_socket(sk
);
648 if(ntohs(ipxh
->spx
.sequence
) == pdata
->rmt_seq
)
650 pdata
->rmt_seq
= ntohs(ipxh
->spx
.sequence
);
651 pdata
->rmt_ack
= ntohs(ipxh
->spx
.ackseq
);
652 if(pdata
->rmt_ack
> 0 || pdata
->rmt_ack
== 0)
653 spx_retransmit_chk(pdata
,pdata
->rmt_ack
, ACK
);
655 skb_queue_tail(&pdata
->rcv_queue
, skb
);
656 wake_up_interruptible(sk
->sleep
);
657 if(ipxh
->spx
.cctl
&CCTL_ACK
)
658 spx_transmit(sk
, NULL
, ACK
, 0);
662 if(ipxh
->spx
.dtype
== SPX_DTYPE_ECACK
)
664 if(pdata
->state
!= SPX_CLOSED
)
665 spx_close_socket(sk
);
670 toss_skb
: /* Catch All */
676 /* Get message/packet data from user-land */
677 static int spx_sendmsg(struct socket
*sock
, struct msghdr
*msg
, int len
,
678 struct scm_cookie
*scm
)
680 struct sock
*sk
= sock
->sk
;
681 int flags
= msg
->msg_flags
;
683 int err
, offset
, size
;
688 return (-ENOTCONN
); /* Socket not bound */
689 if(flags
&~MSG_DONTWAIT
)
692 offset
= ipx_if_offset(sk
->tp_pinfo
.af_spx
.dest_addr
.net
);
693 size
= offset
+ sizeof(struct ipxspxhdr
) + len
;
696 skb
= sock_alloc_send_skb(sk
, size
, 0, flags
&MSG_DONTWAIT
, &err
);
702 skb_reserve(skb
, offset
);
703 skb
->h
.raw
= skb
->nh
.raw
= skb_put(skb
, sizeof(struct ipxspxhdr
));
705 err
= memcpy_fromiovec(skb_put(skb
, len
), msg
->msg_iov
, len
);
712 err
= spx_transmit(sk
, skb
, DATA
, len
);
719 /* Send message/packet data to user-land */
720 static int spx_recvmsg(struct socket
*sock
, struct msghdr
*msg
, int size
,
721 int flags
, struct scm_cookie
*scm
)
724 struct ipxspxhdr
*ispxh
;
725 struct sock
*sk
= sock
->sk
;
726 struct spx_opt
*pdata
= &sk
->tp_pinfo
.af_spx
;
727 struct sockaddr_ipx
*sipx
= (struct sockaddr_ipx
*)msg
->msg_name
;
731 return (-ENOTCONN
); /* Socket not bound */
735 while(skb_queue_empty(&pdata
->rcv_queue
)) /* No data */
738 err
= sock_error(sk
);
742 /* Socket shut down? */
743 if(sk
->shutdown
& RCV_SHUTDOWN
)
747 if(signal_pending(current
))
748 return (-ERESTARTSYS
);
750 /* User doesn't want to wait */
751 if(flags
&MSG_DONTWAIT
)
757 if(skb_peek(&pdata
->rcv_queue
) == NULL
)
758 interruptible_sleep_on(sk
->sleep
);
759 restore_flags(flags
);
763 skb
= skb_dequeue(&pdata
->rcv_queue
);
767 ispxh
= (struct ipxspxhdr
*)skb
->nh
.raw
;
768 copied
= ntohs(ispxh
->ipx
.ipx_pktsize
) - SPX_SYS_PKT_LEN
;
772 msg
->msg_flags
|= MSG_TRUNC
;
775 err
= memcpy_toiovec(msg
->msg_iov
, skb
->nh
.raw
+SPX_SYS_PKT_LEN
, copied
);
779 msg
->msg_namelen
= sizeof(*sipx
);
782 sipx
->sipx_family
= AF_IPX
;
783 sipx
->sipx_port
= ispxh
->ipx
.ipx_source
.sock
;
784 memcpy(sipx
->sipx_node
,ispxh
->ipx
.ipx_source
.node
,IPX_NODE_LEN
);
785 sipx
->sipx_network
= ispxh
->ipx
.ipx_source
.net
;
786 sipx
->sipx_type
= ispxh
->ipx
.ipx_type
;
795 * Functions which just wrap their IPX cousins
798 static int spx_bind(struct socket
*sock
, struct sockaddr
*uaddr
, int addr_len
)
801 err
= ipx_operations
->bind(sock
, uaddr
, addr_len
);
805 static int spx_getname (struct socket
*sock
, struct sockaddr
*uaddr
,
806 int *usockaddr_len
, int peer
)
809 err
= ipx_operations
->getname(sock
, uaddr
, usockaddr_len
, peer
);
813 static int spx_ioctl (struct socket
*sock
, unsigned int cmd
,
817 err
= ipx_operations
->ioctl(sock
, cmd
, arg
);
821 static int spx_setsockopt(struct socket
*sock
, int level
, int optname
,
822 char *optval
, int optlen
)
825 err
= ipx_operations
->setsockopt(sock
, level
, optname
, optval
, optlen
);
829 static int spx_getsockopt(struct socket
*sock
, int level
, int optname
,
830 char *optval
, int *optlen
)
833 err
= ipx_operations
->getsockopt(sock
, level
, optname
, optval
, optlen
);
837 static struct proto_ops
SOCKOPS_WRAPPED(spx_ops
) = {
845 datagram_poll
, /* this does seqpacket too */
857 #include <linux/smp_lock.h>
858 SOCKOPS_WRAP(spx
, PF_IPX
);
861 static struct net_proto_family spx_family_ops
=
868 void spx_proto_init(void)
872 connids
= (__u16
)jiffies
; /* initalize random */
874 error
= ipx_register_spx(&ipx_operations
, &spx_family_ops
);
876 printk(KERN_ERR
"SPX: unable to register with IPX.\n");
878 /* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
880 printk(KERN_INFO
"NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0\n");
884 void spx_proto_finito(void)
886 ipx_unregister_spx();
892 int init_module(void)
898 void cleanup_module(void)
905 #endif /* CONFIG_SPX || CONFIG_SPX_MODULE */