1/*
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
5 *		 Revision:       1.00
6 *		 Revision Date:  February 9, 1993
7 *
8 *	Developers:
9 *      Jay Schulist    <jschlst@samba.org>
10 *	Jim Freeman	<jfree@caldera.com>
11 *
12 *	Changes:
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.
18 *	Eduardo Trapani	:	Added a check for the return value of
19 *				ipx_if_offset that crashed sock_alloc_send_skb.
20 *				Added spx_datagram_poll() so that select()
21 *				works now on SPX sockets.  Added updating
22 *				of the alloc count to follow rmt_seq.
23 *
24 *	This program is free software; you can redistribute it and/or
25 *      modify it under the terms of the GNU General Public License
26 *      as published by the Free Software Foundation; either version
27 *      2 of the License, or (at your option) any later version.
28 *
29 *	None of the authors or maintainers or their employers admit
30 *	liability nor provide warranty for any of this software.
31 *	This material is provided "as is" and at no charge.
32 */
33
34#include <linux/module.h>
35#include <net/ipx.h>
36#include <net/spx.h>
37#include <net/sock.h>
38#include <asm/byteorder.h>
39#include <asm/uaccess.h>
40#include <linux/uio.h>
41#include <linux/unistd.h>
42#include <linux/poll.h>
43
44static struct proto_ops *ipx_operations;
45static struct proto_ops spx_ops;
46static __u16  connids;
47
48/* Functions needed for SPX connection start up */
49static int spx_transmit(struct sock *sk,struct sk_buff *skb,int type,int len);
50static void spx_retransmit(unsigned long data);
51static void spx_watchdog(unsigned long data);
52void spx_rcv(struct sock *sk, int bytes);
53
54extern void ipx_remove_socket(struct sock *sk);
55
56/* Datagram poll:	the same code as datagram_poll() in net/core
57			but the right spx buffers are looked at and
58			there is no question on the type of the socket
59			*/
60static unsigned int spx_datagram_poll(struct file * file, struct socket *sock, poll_table *wait)
61{
62	struct sock *sk = sock->sk;
63	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
64	unsigned int mask;
65
66	poll_wait(file, sk->sleep, wait);
67	mask = 0;
68
69	/* exceptional events? */
70	if (sk->err || !skb_queue_empty(&sk->error_queue))
71		mask |= POLLERR;
72	if (sk->shutdown & RCV_SHUTDOWN)
73		mask |= POLLHUP;
74
75	/* readable? */
76	if (!skb_queue_empty(&pdata->rcv_queue))
77		mask |= POLLIN | POLLRDNORM;
78
79	/* Need to check for termination and startup */
80	if (sk->state==TCP_CLOSE)
81		mask |= POLLHUP;
82	/* connection hasn't started yet? */
83	if (sk->state == TCP_SYN_SENT)
84		return mask;
85
86	/* writable? */
87	if (sock_writeable(sk))
88		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
89	else
90		set_bit(SOCK_ASYNC_NOSPACE,&sk->socket->flags);
91
92	return mask;
93}
94
95/* Create the SPX specific data */
96static int spx_sock_init(struct sock *sk)
97{
98        struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
99
100        pdata->state            = SPX_CLOSED;
101        pdata->sequence         = 0;
102	pdata->acknowledge	= 0;
103        pdata->source_connid    = htons(connids);
104	pdata->rmt_seq		= 0;
105        connids++;
106
107        pdata->owner            = (void *)sk;
108        pdata->sndbuf           = sk->sndbuf;
109
110        pdata->watchdog.function = spx_watchdog;
111        pdata->watchdog.data    = (unsigned long)sk;
112        pdata->wd_interval      = VERIFY_TIMEOUT;
113	pdata->retransmit.function = spx_retransmit;
114	pdata->retransmit.data	= (unsigned long)sk;
115	pdata->retransmits	= 0;
116        pdata->retries          = 0;
117        pdata->max_retries      = RETRY_COUNT;
118
119	skb_queue_head_init(&pdata->rcv_queue);
120	skb_queue_head_init(&pdata->transmit_queue);
121	skb_queue_head_init(&pdata->retransmit_queue);
122
123        return (0);
124}
125
126static int spx_create(struct socket *sock, int protocol)
127{
128	struct sock *sk;
129
130	/*
131	 *	Called on connection receive so cannot be GFP_KERNEL
132	 */
133
134	sk = sk_alloc(PF_IPX, GFP_ATOMIC, 1);
135	if(sk == NULL)
136                return (-ENOMEM);
137
138	switch(sock->type)
139        {
140                case SOCK_SEQPACKET:
141			sock->ops = &spx_ops;
142			break;
143		default:
144			sk_free(sk);
145                        return (-ESOCKTNOSUPPORT);
146        }
147
148	sock_init_data(sock, sk);
149	spx_sock_init(sk);
150	sk->data_ready  = spx_rcv;
151	sk->destruct 	= NULL;
152        sk->no_check 	= 1;
153
154        MOD_INC_USE_COUNT;
155
156	return (0);
157}
158
159
160void spx_close_socket(struct sock *sk)
161{
162	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
163
164	pdata->state	= SPX_CLOSED;
165	sk->state 	= TCP_CLOSE;
166	del_timer(&pdata->retransmit);
167	del_timer(&pdata->watchdog);
168}
169
170void spx_destroy_socket(struct sock *sk)
171{
172	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
173	struct sk_buff *skb;
174
175        ipx_remove_socket(sk);
176        while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
177                kfree_skb(skb);
178	while((skb = skb_dequeue(&pdata->transmit_queue)) != NULL)
179                kfree_skb(skb);
180	while((skb = skb_dequeue(&pdata->retransmit_queue)) != NULL)
181		kfree_skb(skb);
182	while((skb = skb_dequeue(&pdata->rcv_queue)) != NULL)
183                kfree_skb(skb);
184
185        sk_free(sk);
186	MOD_DEC_USE_COUNT;
187}
188
189/* Release an SPX socket */
190static int spx_release(struct socket *sock)
191{
192 	struct sock *sk = sock->sk;
193	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
194
195	if(sk == NULL)
196		return (0);
197	if(!sk->dead)
198                sk->state_change(sk);
199        sk->dead = 1;
200
201	if(pdata->state != SPX_CLOSED)
202	{
203		spx_transmit(sk, NULL, DISCON, 0);
204		spx_close_socket(sk);
205	}
206
207	sock->sk	= NULL;
208	sk->socket 	= NULL;
209	spx_destroy_socket(sk);
210
211        return (0);
212}
213
214/* Move a socket into listening state. */
215static int spx_listen(struct socket *sock, int backlog)
216{
217        struct sock *sk = sock->sk;
218
219        if(sock->state != SS_UNCONNECTED)
220                return (-EINVAL);
221	if(sock->type != SOCK_SEQPACKET)
222		return (-EOPNOTSUPP);
223        if(sk->zapped != 0)
224                return (-EAGAIN);
225
226        sk->max_ack_backlog = backlog;
227        if(sk->state != TCP_LISTEN)
228        {
229                sk->ack_backlog = 0;
230                sk->state = TCP_LISTEN;
231        }
232        sk->socket->flags |= __SO_ACCEPTCON;
233
234        return (0);
235}
236
237/* Accept a pending SPX connection */
238static int spx_accept(struct socket *sock, struct socket *newsock, int flags)
239{
240        struct sock *sk;
241        struct sock *newsk;
242        struct sk_buff *skb;
243	int err;
244
245	if(sock->sk == NULL)
246		return (-EINVAL);
247	sk = sock->sk;
248
249        if((sock->state != SS_UNCONNECTED) || !(sock->flags & __SO_ACCEPTCON))
250                return (-EINVAL);
251        if(sock->type != SOCK_SEQPACKET)
252		return (-EOPNOTSUPP);
253	if(sk->state != TCP_LISTEN)
254                return (-EINVAL);
255
256	cli();
257	do {
258		skb = skb_dequeue(&sk->receive_queue);
259		if(skb == NULL)
260		{
261                	if(flags & O_NONBLOCK)
262			{
263                                sti();
264                                return (-EWOULDBLOCK);
265                        }
266                	interruptible_sleep_on(sk->sleep);
267                	if(signal_pending(current))
268                	{
269                        	sti();
270                        	return (-ERESTARTSYS);
271                	}
272		}
273	} while (skb == NULL);
274
275	newsk 		= skb->sk;
276        newsk->pair 	= NULL;
277	sti();
278
279	err = spx_transmit(newsk, skb, CONACK, 0);   /* Connection ACK */
280	if(err)
281		return (err);
282
283	/* Now attach up the new socket */
284	sock->sk 	= NULL;
285        sk->ack_backlog--;
286        newsock->sk 	= newsk;
287	newsk->state 	= TCP_ESTABLISHED;
288	newsk->protinfo.af_ipx.dest_addr = newsk->tp_pinfo.af_spx.dest_addr;
289
290	return (0);
291}
292
293/* Build a connection to an SPX socket */
294static int spx_connect(struct socket *sock, struct sockaddr *uaddr,
295                int addr_len, int flags)
296{
297	struct sock *sk = sock->sk;
298        struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
299        struct sockaddr_ipx src;
300	struct sk_buff *skb;
301	int size, err;
302
303	size = sizeof(src);
304	err  = ipx_operations->getname(sock, (struct sockaddr *)&src, &size, 0);
305	if(err)
306		return (err);
307
308        pdata->source_addr.net	= src.sipx_network;
309        memcpy(pdata->source_addr.node, src.sipx_node, IPX_NODE_LEN);
310        pdata->source_addr.sock = (unsigned short)src.sipx_port;
311
312	err = ipx_operations->connect(sock, uaddr, addr_len, flags);
313        if(err)
314                return (err);
315
316        pdata->dest_addr = sk->protinfo.af_ipx.dest_addr;
317	pdata->state	 = SPX_CONNECTING;
318	sock->state	 = SS_CONNECTING;
319        sk->state	 = TCP_SYN_SENT;
320
321        /* Send Connection request */
322	err = spx_transmit(sk, NULL, CONREQ, 0);
323        if(err)
324                return (err);
325
326	cli();
327        do {
328                skb = skb_dequeue(&sk->receive_queue);
329                if(skb == NULL)
330                {
331                        if(flags & O_NONBLOCK)
332                        {
333                                sti();
334                                return (-EWOULDBLOCK);
335                        }
336                        interruptible_sleep_on(sk->sleep);
337                        if(signal_pending(current))
338                        {
339                                sti();
340                                return (-ERESTARTSYS);
341                        }
342                }
343        } while (skb == NULL);
344
345        if(pdata->state == SPX_CLOSED)
346        {
347		sti();
348                del_timer(&pdata->watchdog);
349                return (-ETIMEDOUT);
350        }
351
352	sock->state	= SS_CONNECTED;
353	sk->state 	= TCP_ESTABLISHED;
354	kfree_skb(skb);
355	sti();
356
357        return (0);
358}
359
360static inline unsigned long spx_calc_rtt(int tries)
361{
362        if(tries < 1)
363                return (RETRY_TIME);
364        if(tries > 5)
365                return (MAX_RETRY_DELAY);
366        return (tries * HZ);
367}
368
369static int spx_route_skb(struct spx_opt *pdata, struct sk_buff *skb, int type)
370{
371	struct sk_buff *skb2;
372	int err = 0;
373
374	skb = skb_unshare(skb, GFP_ATOMIC);
375	if(skb == NULL)
376		return (-ENOBUFS);
377
378	switch(type)
379	{
380		case (CONREQ):
381		case (DATA):
382			if(!skb_queue_empty(&pdata->retransmit_queue))
383			{
384				skb_queue_tail(&pdata->transmit_queue, skb);
385				return 0;
386			}
387
388		case (TQUEUE):
389			pdata->retransmit.expires = jiffies + spx_calc_rtt(0);
390			add_timer(&pdata->retransmit);
391
392			skb2 = skb_clone(skb, GFP_NOIO);
393	                if(skb2 == NULL)
394        	                return -ENOBUFS;
395        	        skb_queue_tail(&pdata->retransmit_queue, skb2);
396
397		case (ACK):
398		case (CONACK):
399		case (WDREQ):
400		case (WDACK):
401		case (DISCON):
402		case (DISACK):
403		case (RETRAN):
404		default:
405			/* Send data */
406        		err = ipxrtr_route_skb(skb);
407        		if(err)
408                		kfree_skb(skb);
409	}
410
411	return (err);
412}
413
414/* SPX packet transmit engine */
415static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
416{
417        struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
418        struct ipxspxhdr *ipxh;
419	unsigned long flags;
420	int err;
421
422	if(skb == NULL)
423	{
424		int offset  = ipx_if_offset(pdata->dest_addr.net);
425        	int size    = offset + sizeof(struct ipxspxhdr);
426
427        	if (offset < 0) /* ENETUNREACH */
428        		return(-ENETUNREACH);
429
430		save_flags(flags);
431		cli();
432        	skb = sock_alloc_send_skb(sk, size, 0, &err);
433        	if(skb == NULL) {
434			restore_flags(flags);
435                	return (-ENOMEM);
436		}
437        	skb_reserve(skb, offset);
438        	skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
439		restore_flags(flags);
440	}
441
442	/* IPX header */
443	ipxh = (struct ipxspxhdr *)skb->nh.raw;
444	ipxh->ipx.ipx_checksum  = 0xFFFF;
445	ipxh->ipx.ipx_pktsize   = htons(SPX_SYS_PKT_LEN);
446        ipxh->ipx.ipx_tctrl     = 0;
447	ipxh->ipx.ipx_type 	= IPX_TYPE_SPX;
448        ipxh->ipx.ipx_dest      = pdata->dest_addr;
449        ipxh->ipx.ipx_source    = pdata->source_addr;
450
451	/* SPX header */
452        ipxh->spx.dtype         = 0;
453	ipxh->spx.sequence      = htons(pdata->sequence);
454	ipxh->spx.ackseq        = htons(pdata->rmt_seq);
455	ipxh->spx.sconn         = pdata->source_connid;
456        ipxh->spx.dconn         = pdata->dest_connid;
457        ipxh->spx.allocseq      = htons(pdata->alloc);
458
459	/* Reset/Set WD timer */
460        mod_timer(&pdata->watchdog, jiffies+VERIFY_TIMEOUT);
461
462	switch(type)
463	{
464		case (DATA):	/* Data */
465			ipxh->ipx.ipx_pktsize 	= htons(SPX_SYS_PKT_LEN + len);
466			ipxh->spx.cctl 		= (CCTL_ACK | CCTL_EOM);
467                	pdata->sequence++;
468			break;
469
470		case (ACK):	/* ACK */
471			pdata->rmt_seq++;
472		case (WDACK):	/* WD ACK */
473		case (CONACK):	/* Connection ACK */
474			ipxh->spx.cctl 		= CCTL_SYS;
475			ipxh->spx.ackseq 	= htons(pdata->rmt_seq);
476			break;
477
478		case (CONREQ):	/* Connection Request */
479			del_timer(&pdata->watchdog);
480		case (WDREQ):	/* WD Request */
481			pdata->source_connid    = htons(connids++);
482                	pdata->dest_connid      = 0xFFFF;
483                	pdata->alloc 		= 3 + pdata->rmt_seq;
484			ipxh->spx.cctl          = (CCTL_ACK | CCTL_SYS);
485			ipxh->spx.sconn         = pdata->source_connid;
486		        ipxh->spx.dconn         = pdata->dest_connid;
487		        ipxh->spx.allocseq      = htons(pdata->alloc);
488			break;
489
490		case (DISCON):	/* Informed Disconnect */
491			ipxh->spx.cctl 		= CCTL_ACK;
492			ipxh->spx.dtype 	= SPX_DTYPE_ECONN;
493			break;
494
495		case (DISACK):	/* Informed Disconnect ACK */
496			ipxh->spx.cctl  	= 0;
497			ipxh->spx.dtype 	= SPX_DTYPE_ECACK;
498			ipxh->spx.sequence 	= 0;
499			ipxh->spx.ackseq 	= htons(pdata->rmt_seq++);
500			break;
501
502		default:
503			return (-EOPNOTSUPP);
504	}
505
506	/* Send data */
507        return (spx_route_skb(pdata, skb, type));
508}
509
510/* Check the state of the connection and send a WD request if needed. */
511static void spx_watchdog(unsigned long data)
512{
513	struct sock *sk = (struct sock*)data;
514        struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
515
516        del_timer(&pdata->watchdog);
517	if(pdata->state == SPX_CLOSED)
518                return;
519	if(pdata->retries > pdata->max_retries)
520        {
521		spx_close_socket(sk);	/* Unilateral Abort */
522                return;
523        }
524
525        /* Send WD request */
526	spx_transmit(sk, NULL, WDREQ, 0);
527	pdata->retries++;
528
529        return;
530}
531
532static void spx_retransmit(unsigned long data)
533{
534	struct sock *sk = (struct sock*)data;
535        struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
536	struct sk_buff *skb;
537	unsigned long flags;
538	int err;
539
540	del_timer(&pdata->retransmit);
541	if(pdata->state == SPX_CLOSED)
542		return;
543	if(pdata->retransmits > RETRY_COUNT)
544	{
545		spx_close_socket(sk);   /* Unilateral Abort */
546                return;
547        }
548
549	/* Need to leave skb on the queue, aye the fear */
550	save_flags(flags);
551	cli();
552	skb = skb_peek(&pdata->retransmit_queue);
553	if(skb_cloned(skb))
554                skb = skb_copy(skb, GFP_ATOMIC);
555        else
556                skb = skb_clone(skb, GFP_ATOMIC);
557	restore_flags(flags);
558
559	pdata->retransmit.expires = jiffies + spx_calc_rtt(pdata->retransmits);
560	add_timer(&pdata->retransmit);
561
562	err = spx_route_skb(pdata, skb, RETRAN);
563	pdata->retransmits++;
564
565	return;
566}
567
568/* Check packet for retransmission, ConReqAck aware */
569static int spx_retransmit_chk(struct spx_opt *pdata, int ackseq, int type)
570{
571	struct ipxspxhdr *ipxh;
572	struct sk_buff *skb;
573
574	skb = skb_dequeue(&pdata->retransmit_queue);
575	if(!skb)
576		return (-ENOENT);
577
578	/* Check Data/ACK seq */
579	switch(type)
580	{
581		case ACK:	/* Check Sequence, Should == 1 */
582			ipxh = (struct ipxspxhdr *)skb->nh.raw;
583			if(!(ntohs(ipxh->spx.sequence) - htons(ackseq)))
584				break;
585
586		case CONACK:
587			del_timer(&pdata->retransmit);
588			pdata->retransmits = 0;
589			kfree_skb(skb);
590			if(skb_queue_empty(&pdata->retransmit_queue))
591			{
592				skb = skb_dequeue(&pdata->transmit_queue);
593				if(skb != NULL)
594					spx_route_skb(pdata, skb, TQUEUE);
595			}
596			return (0);
597	}
598
599	skb_queue_head(&pdata->retransmit_queue, skb);
600	return (-1);
601}
602
603/* SPX packet receive engine */
604void spx_rcv(struct sock *sk, int bytes)
605{
606	struct sk_buff *skb;
607	struct ipxspxhdr *ipxh;
608	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
609
610	skb = skb_dequeue(&sk->receive_queue);
611	if(skb == NULL)
612		return;
613	ipxh = (struct ipxspxhdr *)skb->nh.raw;
614
615	/* Can't receive on a closed connection */
616        if((pdata->state == SPX_CLOSED) && (ipxh->spx.sequence != 0))
617		goto toss_skb;
618	if(ntohs(ipxh->ipx.ipx_pktsize) < SPX_SYS_PKT_LEN)
619		goto toss_skb;
620        if(ipxh->ipx.ipx_type != IPX_TYPE_SPX)
621		goto toss_skb;
622        if(ntohs(ipxh->spx.ackseq) > pdata->sequence)
623		goto toss_skb;
624
625	/* Reset WD timer on any received packet */
626	del_timer(&pdata->watchdog);
627	pdata->retries = 0;
628	pdata->watchdog.expires = jiffies + ABORT_TIMEOUT;
629        add_timer(&pdata->watchdog);
630
631	switch(ipxh->spx.cctl)
632	{
633		case (CCTL_SYS | CCTL_ACK):
634			if((ipxh->spx.sequence == 0)	/* ConReq */
635				&& (ipxh->spx.ackseq == 0)
636				&& (ipxh->spx.dconn == 0xFFFF))
637			{
638				pdata->state		= SPX_CONNECTED;
639				pdata->dest_addr        = ipxh->ipx.ipx_source;
640				pdata->source_addr      = ipxh->ipx.ipx_dest;
641				pdata->dest_connid      = ipxh->spx.sconn;
642				pdata->alloc = 3 + ntohs(ipxh->spx.sequence);
643
644				skb_queue_tail(&sk->receive_queue, skb);
645				wake_up_interruptible(sk->sleep);
646			}
647			else	/* WD Request */
648				spx_transmit(sk, skb, WDACK, 0);
649			goto finish;
650
651		case CCTL_SYS:	/* ACK */
652			if((ipxh->spx.dtype == 0)       /* ConReq ACK */
653                                && (ipxh->spx.sconn != 0xFFFF)
654                                && (ipxh->spx.dconn != 0xFFFF)
655                                && (ipxh->spx.sequence == 0)
656                                && (ipxh->spx.ackseq == 0)
657                                && (pdata->state != SPX_CONNECTED))
658                        {
659                                pdata->state = SPX_CONNECTED;
660				pdata->dest_connid = ipxh->spx.sconn;
661
662				if(spx_retransmit_chk(pdata, 0, CONACK) < 0)
663					goto toss_skb;
664
665                                skb_queue_tail(&sk->receive_queue, skb);
666                                wake_up_interruptible(sk->sleep);
667                                goto finish;
668                        }
669
670			spx_retransmit_chk(pdata, ipxh->spx.ackseq, ACK);
671			goto toss_skb;
672
673		case (CCTL_ACK):
674			/* Informed Disconnect */
675			if(ipxh->spx.dtype == SPX_DTYPE_ECONN)
676			{
677
678				spx_transmit(sk, skb, DISACK, 0);
679				spx_close_socket(sk);
680				goto finish;
681			}
682			/* Fall through */
683
684		default:
685			if(ntohs(ipxh->spx.sequence) == pdata->rmt_seq)
686			{
687				pdata->rmt_seq = ntohs(ipxh->spx.sequence);
688				pdata->rmt_ack = ntohs(ipxh->spx.ackseq);
689				pdata->alloc   = pdata->rmt_seq + 3;
690				if(pdata->rmt_ack > 0 || pdata->rmt_ack == 0)
691					spx_retransmit_chk(pdata,pdata->rmt_ack, ACK);
692
693				skb_queue_tail(&pdata->rcv_queue, skb);
694				wake_up_interruptible(sk->sleep);
695				if(ipxh->spx.cctl&CCTL_ACK)
696					spx_transmit(sk, NULL, ACK, 0);
697				goto finish;
698			}
699
700			if(ipxh->spx.dtype == SPX_DTYPE_ECACK)
701			{
702				if(pdata->state != SPX_CLOSED)
703					spx_close_socket(sk);
704				goto toss_skb;
705			}
706	}
707
708toss_skb:	/* Catch All */
709	kfree_skb(skb);
710finish:
711        return;
712}
713
714/* Get message/packet data from user-land */
715static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
716			struct scm_cookie *scm)
717{
718	struct sock *sk = sock->sk;
719	int flags = msg->msg_flags;
720	struct sk_buff *skb;
721	int err, offset, size;
722
723	if(len > 534)
724                return (-EMSGSIZE);
725        if(sk->zapped)
726                return (-ENOTCONN); /* Socket not bound */
727	if(flags&~MSG_DONTWAIT)
728                return (-EINVAL);
729
730	offset	= ipx_if_offset(sk->tp_pinfo.af_spx.dest_addr.net);
731        size 	= offset + sizeof(struct ipxspxhdr) + len;
732
733	cli();
734        skb  	= sock_alloc_send_skb(sk, size, flags&MSG_DONTWAIT, &err);
735	sti();
736        if(skb == NULL)
737                return (err);
738
739	skb->sk = sk;
740        skb_reserve(skb, offset);
741	skb->h.raw = skb->nh.raw = skb_put(skb, sizeof(struct ipxspxhdr));
742
743	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
744	if(err)
745        {
746                kfree_skb(skb);
747                return (-EFAULT);
748        }
749
750	err = spx_transmit(sk, skb, DATA, len);
751	if(err)
752		return (-EAGAIN);
753
754        return (len);
755}
756
757/* Send message/packet data to user-land */
758static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
759			int flags, struct scm_cookie *scm)
760{
761	struct sk_buff *skb;
762	struct ipxspxhdr *ispxh;
763	struct sock *sk = sock->sk;
764	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
765	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;
766	int copied, err;
767
768        if(sk->zapped)
769                return (-ENOTCONN); /* Socket not bound */
770
771	lock_sock(sk);
772restart:
773        while(skb_queue_empty(&pdata->rcv_queue))      /* No data */
774        {
775                /* Socket errors? */
776                err = sock_error(sk);
777                if(err)
778			return (err);
779
780                /* Socket shut down? */
781                if(sk->shutdown & RCV_SHUTDOWN)
782			return (-ESHUTDOWN);
783
784                /* handle signals */
785                if(signal_pending(current))
786			return (-ERESTARTSYS);
787
788                /* User doesn't want to wait */
789                if(flags&MSG_DONTWAIT)
790			return (-EAGAIN);
791
792		release_sock(sk);
793        	save_flags(flags);
794        	cli();
795        	if(skb_peek(&pdata->rcv_queue) == NULL)
796                	interruptible_sleep_on(sk->sleep);
797        	restore_flags(flags);
798        	lock_sock(sk);
799        }
800
801        skb = skb_dequeue(&pdata->rcv_queue);
802        if(skb == NULL)
803		goto restart;
804
805	ispxh 	= (struct ipxspxhdr *)skb->nh.raw;
806	copied 	= ntohs(ispxh->ipx.ipx_pktsize) - SPX_SYS_PKT_LEN;
807        if(copied > size)
808	{
809                copied = size;
810                msg->msg_flags |= MSG_TRUNC;
811        }
812
813	err = memcpy_toiovec(msg->msg_iov, skb->nh.raw+SPX_SYS_PKT_LEN, copied);
814        if(err)
815                return (-EFAULT);
816
817	msg->msg_namelen = sizeof(*sipx);
818	if(sipx)
819	{
820		sipx->sipx_family	= AF_IPX;
821                sipx->sipx_port		= ispxh->ipx.ipx_source.sock;
822                memcpy(sipx->sipx_node,ispxh->ipx.ipx_source.node,IPX_NODE_LEN);
823                sipx->sipx_network	= ispxh->ipx.ipx_source.net;
824                sipx->sipx_type 	= ispxh->ipx.ipx_type;
825        }
826	kfree_skb(skb);
827        release_sock(sk);
828
829	return (copied);
830}
831
832/*
833 * Functions which just wrap their IPX cousins
834 */
835
836static int spx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
837{
838        int err;
839        err = ipx_operations->bind(sock, uaddr, addr_len);
840        return (err);
841}
842
843static int spx_getname (struct socket *sock, struct sockaddr *uaddr,
844                         int *usockaddr_len, int peer)
845{
846	int err;
847	err = ipx_operations->getname(sock, uaddr, usockaddr_len, peer);
848	return (err);
849}
850
851static int spx_ioctl (struct socket *sock, unsigned int cmd,
852                         unsigned long arg)
853{
854	int err;
855	err = ipx_operations->ioctl(sock, cmd, arg);
856	return (err);
857}
858
859static int spx_setsockopt(struct socket *sock, int level, int optname,
860                         char *optval, int optlen)
861{
862	int err;
863	err = ipx_operations->setsockopt(sock, level, optname, optval, optlen);
864	return (err);
865}
866
867static int spx_getsockopt(struct socket *sock, int level, int optname,
868                         char *optval, int *optlen)
869{
870	int err;
871	err = ipx_operations->getsockopt(sock, level, optname, optval, optlen);
872	return (err);
873}
874
875static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
876	family:		PF_IPX,
877
878	release:	spx_release,
879	bind:		spx_bind,
880	connect:	spx_connect,
881	socketpair:	sock_no_socketpair,
882	accept:		spx_accept,
883	getname:	spx_getname,
884	poll:		spx_datagram_poll,
885	ioctl:		spx_ioctl,
886	listen:		spx_listen,
887	shutdown:	sock_no_shutdown,
888	setsockopt:	spx_setsockopt,
889	getsockopt:	spx_getsockopt,
890	sendmsg:	spx_sendmsg,
891	recvmsg:	spx_recvmsg,
892	mmap:		sock_no_mmap,
893	sendpage:	sock_no_sendpage,
894};
895
896#include <linux/smp_lock.h>
897SOCKOPS_WRAP(spx, PF_IPX);
898
899static struct net_proto_family spx_family_ops = {
900	family:		PF_IPX,
901	create:		spx_create,
902};
903
904static char banner[] __initdata = KERN_INFO "NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0\n";
905
906static int __init spx_proto_init(void)
907{
908	int error;
909
910	connids = (__u16)jiffies;	/* initalize random */
911
912	error = ipx_register_spx(&ipx_operations, &spx_family_ops);
913        if (error)
914                printk(KERN_ERR "SPX: unable to register with IPX.\n");
915
916	/* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
917
918	printk(banner);
919	return 0;
920}
921module_init(spx_proto_init);
922
923static void __exit spx_proto_finito(void)
924{
925	ipx_unregister_spx();
926	return;
927}
928module_exit(spx_proto_finito);
929