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 
44 static struct proto_ops *ipx_operations;
45 static struct proto_ops spx_ops;
46 static __u16  connids;
47 
48 /* Functions needed for SPX connection start up */
49 static int spx_transmit(struct sock *sk,struct sk_buff *skb,int type,int len);
50 static void spx_retransmit(unsigned long data);
51 static void spx_watchdog(unsigned long data);
52 void spx_rcv(struct sock *sk, int bytes);
53 
54 extern 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 			*/
spx_datagram_poll(struct file * file,struct socket * sock,poll_table * wait)60 static 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 */
spx_sock_init(struct sock * sk)96 static 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 
spx_create(struct socket * sock,int protocol)126 static 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 
spx_close_socket(struct sock * sk)160 void 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 
spx_destroy_socket(struct sock * sk)170 void 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 */
spx_release(struct socket * sock)190 static 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. */
spx_listen(struct socket * sock,int backlog)215 static 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 */
spx_accept(struct socket * sock,struct socket * newsock,int flags)238 static 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 */
spx_connect(struct socket * sock,struct sockaddr * uaddr,int addr_len,int flags)294 static 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 
360 /*
361  * Calculate the timeout for a packet. Thankfully SPX has a large
362  * fudge factor (3/4 secs) and does not pay much attention to RTT.
363  * As we simply have a default retry time of 1*HZ and a max retry
364  * time of 5*HZ. Between those values we increase the timeout based
365  * on the number of retransmit tries.
366  *
367  * FixMe: This is quite fake, but will work for now. (JS)
368  */
spx_calc_rtt(int tries)369 static inline unsigned long spx_calc_rtt(int tries)
370 {
371         if(tries < 1)
372                 return (RETRY_TIME);
373         if(tries > 5)
374                 return (MAX_RETRY_DELAY);
375         return (tries * HZ);
376 }
377 
spx_route_skb(struct spx_opt * pdata,struct sk_buff * skb,int type)378 static int spx_route_skb(struct spx_opt *pdata, struct sk_buff *skb, int type)
379 {
380 	struct sk_buff *skb2;
381 	int err = 0;
382 
383 	skb = skb_unshare(skb, GFP_ATOMIC);
384 	if(skb == NULL)
385 		return (-ENOBUFS);
386 
387 	switch(type)
388 	{
389 		case (CONREQ):
390 		case (DATA):
391 			if(!skb_queue_empty(&pdata->retransmit_queue))
392 			{
393 				skb_queue_tail(&pdata->transmit_queue, skb);
394 				return 0;
395 			}
396 
397 		case (TQUEUE):
398 			pdata->retransmit.expires = jiffies + spx_calc_rtt(0);
399 			add_timer(&pdata->retransmit);
400 
401 			skb2 = skb_clone(skb, GFP_NOIO);
402 	                if(skb2 == NULL)
403         	                return -ENOBUFS;
404         	        skb_queue_tail(&pdata->retransmit_queue, skb2);
405 
406 		case (ACK):
407 		case (CONACK):
408 		case (WDREQ):
409 		case (WDACK):
410 		case (DISCON):
411 		case (DISACK):
412 		case (RETRAN):
413 		default:
414 			/* Send data */
415         		err = ipxrtr_route_skb(skb);
416         		if(err)
417                 		kfree_skb(skb);
418 	}
419 
420 	return (err);
421 }
422 
423 /* SPX packet transmit engine */
spx_transmit(struct sock * sk,struct sk_buff * skb,int type,int len)424 static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
425 {
426         struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
427         struct ipxspxhdr *ipxh;
428 	unsigned long flags;
429 	int err;
430 
431 	if(skb == NULL)
432 	{
433 		int offset  = ipx_if_offset(pdata->dest_addr.net);
434         	int size    = offset + sizeof(struct ipxspxhdr);
435 
436         	if (offset < 0) /* ENETUNREACH */
437         		return(-ENETUNREACH);
438 
439 		save_flags(flags);
440 		cli();
441         	skb = sock_alloc_send_skb(sk, size, 0, &err);
442         	if(skb == NULL) {
443 			restore_flags(flags);
444                 	return (-ENOMEM);
445 		}
446         	skb_reserve(skb, offset);
447         	skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
448 		restore_flags(flags);
449 	}
450 
451 	/* IPX header */
452 	ipxh = (struct ipxspxhdr *)skb->nh.raw;
453 	ipxh->ipx.ipx_checksum  = 0xFFFF;
454 	ipxh->ipx.ipx_pktsize   = htons(SPX_SYS_PKT_LEN);
455         ipxh->ipx.ipx_tctrl     = 0;
456 	ipxh->ipx.ipx_type 	= IPX_TYPE_SPX;
457         ipxh->ipx.ipx_dest      = pdata->dest_addr;
458         ipxh->ipx.ipx_source    = pdata->source_addr;
459 
460 	/* SPX header */
461         ipxh->spx.dtype         = 0;
462 	ipxh->spx.sequence      = htons(pdata->sequence);
463 	ipxh->spx.ackseq        = htons(pdata->rmt_seq);
464 	ipxh->spx.sconn         = pdata->source_connid;
465         ipxh->spx.dconn         = pdata->dest_connid;
466         ipxh->spx.allocseq      = htons(pdata->alloc);
467 
468 	/* Reset/Set WD timer */
469         mod_timer(&pdata->watchdog, jiffies+VERIFY_TIMEOUT);
470 
471 	switch(type)
472 	{
473 		case (DATA):	/* Data */
474 			ipxh->ipx.ipx_pktsize 	= htons(SPX_SYS_PKT_LEN + len);
475 			ipxh->spx.cctl 		= (CCTL_ACK | CCTL_EOM);
476                 	pdata->sequence++;
477 			break;
478 
479 		case (ACK):	/* ACK */
480 			pdata->rmt_seq++;
481 		case (WDACK):	/* WD ACK */
482 		case (CONACK):	/* Connection ACK */
483 			ipxh->spx.cctl 		= CCTL_SYS;
484 			ipxh->spx.ackseq 	= htons(pdata->rmt_seq);
485 			break;
486 
487 		case (CONREQ):	/* Connection Request */
488 			del_timer(&pdata->watchdog);
489 		case (WDREQ):	/* WD Request */
490 			pdata->source_connid    = htons(connids++);
491                 	pdata->dest_connid      = 0xFFFF;
492                 	pdata->alloc 		= 3 + pdata->rmt_seq;
493 			ipxh->spx.cctl          = (CCTL_ACK | CCTL_SYS);
494 			ipxh->spx.sconn         = pdata->source_connid;
495 		        ipxh->spx.dconn         = pdata->dest_connid;
496 		        ipxh->spx.allocseq      = htons(pdata->alloc);
497 			break;
498 
499 		case (DISCON):	/* Informed Disconnect */
500 			ipxh->spx.cctl 		= CCTL_ACK;
501 			ipxh->spx.dtype 	= SPX_DTYPE_ECONN;
502 			break;
503 
504 		case (DISACK):	/* Informed Disconnect ACK */
505 			ipxh->spx.cctl  	= 0;
506 			ipxh->spx.dtype 	= SPX_DTYPE_ECACK;
507 			ipxh->spx.sequence 	= 0;
508 			ipxh->spx.ackseq 	= htons(pdata->rmt_seq++);
509 			break;
510 
511 		default:
512 			return (-EOPNOTSUPP);
513 	}
514 
515 	/* Send data */
516         return (spx_route_skb(pdata, skb, type));
517 }
518 
519 /* Check the state of the connection and send a WD request if needed. */
spx_watchdog(unsigned long data)520 static void spx_watchdog(unsigned long data)
521 {
522 	struct sock *sk = (struct sock*)data;
523         struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
524 
525         del_timer(&pdata->watchdog);
526 	if(pdata->state == SPX_CLOSED)
527                 return;
528 	if(pdata->retries > pdata->max_retries)
529         {
530 		spx_close_socket(sk);	/* Unilateral Abort */
531                 return;
532         }
533 
534         /* Send WD request */
535 	spx_transmit(sk, NULL, WDREQ, 0);
536 	pdata->retries++;
537 
538         return;
539 }
540 
spx_retransmit(unsigned long data)541 static void spx_retransmit(unsigned long data)
542 {
543 	struct sock *sk = (struct sock*)data;
544         struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
545 	struct sk_buff *skb;
546 	unsigned long flags;
547 	int err;
548 
549 	del_timer(&pdata->retransmit);
550 	if(pdata->state == SPX_CLOSED)
551 		return;
552 	if(pdata->retransmits > RETRY_COUNT)
553 	{
554 		spx_close_socket(sk);   /* Unilateral Abort */
555                 return;
556         }
557 
558 	/* Need to leave skb on the queue, aye the fear */
559 	save_flags(flags);
560 	cli();
561 	skb = skb_peek(&pdata->retransmit_queue);
562 	if(skb_cloned(skb))
563                 skb = skb_copy(skb, GFP_ATOMIC);
564         else
565                 skb = skb_clone(skb, GFP_ATOMIC);
566 	restore_flags(flags);
567 
568 	pdata->retransmit.expires = jiffies + spx_calc_rtt(pdata->retransmits);
569 	add_timer(&pdata->retransmit);
570 
571 	err = spx_route_skb(pdata, skb, RETRAN);
572 	pdata->retransmits++;
573 
574 	return;
575 }
576 
577 /* Check packet for retransmission, ConReqAck aware */
spx_retransmit_chk(struct spx_opt * pdata,int ackseq,int type)578 static int spx_retransmit_chk(struct spx_opt *pdata, int ackseq, int type)
579 {
580 	struct ipxspxhdr *ipxh;
581 	struct sk_buff *skb;
582 
583 	skb = skb_dequeue(&pdata->retransmit_queue);
584 	if(!skb)
585 		return (-ENOENT);
586 
587 	/* Check Data/ACK seq */
588 	switch(type)
589 	{
590 		case ACK:	/* Check Sequence, Should == 1 */
591 			ipxh = (struct ipxspxhdr *)skb->nh.raw;
592 			if(!(ntohs(ipxh->spx.sequence) - htons(ackseq)))
593 				break;
594 
595 		case CONACK:
596 			del_timer(&pdata->retransmit);
597 			pdata->retransmits = 0;
598 			kfree_skb(skb);
599 			if(skb_queue_empty(&pdata->retransmit_queue))
600 			{
601 				skb = skb_dequeue(&pdata->transmit_queue);
602 				if(skb != NULL)
603 					spx_route_skb(pdata, skb, TQUEUE);
604 			}
605 			return (0);
606 	}
607 
608 	skb_queue_head(&pdata->retransmit_queue, skb);
609 	return (-1);
610 }
611 
612 /* SPX packet receive engine */
spx_rcv(struct sock * sk,int bytes)613 void spx_rcv(struct sock *sk, int bytes)
614 {
615 	struct sk_buff *skb;
616 	struct ipxspxhdr *ipxh;
617 	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
618 
619 	skb = skb_dequeue(&sk->receive_queue);
620 	if(skb == NULL)
621 		return;
622 	ipxh = (struct ipxspxhdr *)skb->nh.raw;
623 
624 	/* Can't receive on a closed connection */
625         if((pdata->state == SPX_CLOSED) && (ipxh->spx.sequence != 0))
626 		goto toss_skb;
627 	if(ntohs(ipxh->ipx.ipx_pktsize) < SPX_SYS_PKT_LEN)
628 		goto toss_skb;
629         if(ipxh->ipx.ipx_type != IPX_TYPE_SPX)
630 		goto toss_skb;
631         if(ntohs(ipxh->spx.ackseq) > pdata->sequence)
632 		goto toss_skb;
633 
634 	/* Reset WD timer on any received packet */
635 	del_timer(&pdata->watchdog);
636 	pdata->retries = 0;
637 	pdata->watchdog.expires = jiffies + ABORT_TIMEOUT;
638         add_timer(&pdata->watchdog);
639 
640 	switch(ipxh->spx.cctl)
641 	{
642 		case (CCTL_SYS | CCTL_ACK):
643 			if((ipxh->spx.sequence == 0)	/* ConReq */
644 				&& (ipxh->spx.ackseq == 0)
645 				&& (ipxh->spx.dconn == 0xFFFF))
646 			{
647 				pdata->state		= SPX_CONNECTED;
648 				pdata->dest_addr        = ipxh->ipx.ipx_source;
649 				pdata->source_addr      = ipxh->ipx.ipx_dest;
650 				pdata->dest_connid      = ipxh->spx.sconn;
651 				pdata->alloc = 3 + ntohs(ipxh->spx.sequence);
652 
653 				skb_queue_tail(&sk->receive_queue, skb);
654 				wake_up_interruptible(sk->sleep);
655 			}
656 			else	/* WD Request */
657 				spx_transmit(sk, skb, WDACK, 0);
658 			goto finish;
659 
660 		case CCTL_SYS:	/* ACK */
661 			if((ipxh->spx.dtype == 0)       /* ConReq ACK */
662                                 && (ipxh->spx.sconn != 0xFFFF)
663                                 && (ipxh->spx.dconn != 0xFFFF)
664                                 && (ipxh->spx.sequence == 0)
665                                 && (ipxh->spx.ackseq == 0)
666                                 && (pdata->state != SPX_CONNECTED))
667                         {
668                                 pdata->state = SPX_CONNECTED;
669 				pdata->dest_connid = ipxh->spx.sconn;
670 
671 				if(spx_retransmit_chk(pdata, 0, CONACK) < 0)
672 					goto toss_skb;
673 
674                                 skb_queue_tail(&sk->receive_queue, skb);
675                                 wake_up_interruptible(sk->sleep);
676                                 goto finish;
677                         }
678 
679 			spx_retransmit_chk(pdata, ipxh->spx.ackseq, ACK);
680 			goto toss_skb;
681 
682 		case (CCTL_ACK):
683 			/* Informed Disconnect */
684 			if(ipxh->spx.dtype == SPX_DTYPE_ECONN)
685 			{
686 
687 				spx_transmit(sk, skb, DISACK, 0);
688 				spx_close_socket(sk);
689 				goto finish;
690 			}
691 			/* Fall through */
692 
693 		default:
694 			if(ntohs(ipxh->spx.sequence) == pdata->rmt_seq)
695 			{
696 				pdata->rmt_seq = ntohs(ipxh->spx.sequence);
697 				pdata->rmt_ack = ntohs(ipxh->spx.ackseq);
698 				pdata->alloc   = pdata->rmt_seq + 3;
699 				if(pdata->rmt_ack > 0 || pdata->rmt_ack == 0)
700 					spx_retransmit_chk(pdata,pdata->rmt_ack, ACK);
701 
702 				skb_queue_tail(&pdata->rcv_queue, skb);
703 				wake_up_interruptible(sk->sleep);
704 				if(ipxh->spx.cctl&CCTL_ACK)
705 					spx_transmit(sk, NULL, ACK, 0);
706 				goto finish;
707 			}
708 
709 			if(ipxh->spx.dtype == SPX_DTYPE_ECACK)
710 			{
711 				if(pdata->state != SPX_CLOSED)
712 					spx_close_socket(sk);
713 				goto toss_skb;
714 			}
715 	}
716 
717 toss_skb:	/* Catch All */
718 	kfree_skb(skb);
719 finish:
720         return;
721 }
722 
723 /* Get message/packet data from user-land */
spx_sendmsg(struct socket * sock,struct msghdr * msg,int len,struct scm_cookie * scm)724 static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
725 			struct scm_cookie *scm)
726 {
727 	struct sock *sk = sock->sk;
728 	int flags = msg->msg_flags;
729 	struct sk_buff *skb;
730 	int err, offset, size;
731 
732 	if(len > 534)
733                 return (-EMSGSIZE);
734         if(sk->zapped)
735                 return (-ENOTCONN); /* Socket not bound */
736 	if(flags&~MSG_DONTWAIT)
737                 return (-EINVAL);
738 
739 	offset	= ipx_if_offset(sk->tp_pinfo.af_spx.dest_addr.net);
740         size 	= offset + sizeof(struct ipxspxhdr) + len;
741 
742 	cli();
743         skb  	= sock_alloc_send_skb(sk, size, flags&MSG_DONTWAIT, &err);
744 	sti();
745         if(skb == NULL)
746                 return (err);
747 
748 	skb->sk = sk;
749         skb_reserve(skb, offset);
750 	skb->h.raw = skb->nh.raw = skb_put(skb, sizeof(struct ipxspxhdr));
751 
752 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
753 	if(err)
754         {
755                 kfree_skb(skb);
756                 return (-EFAULT);
757         }
758 
759 	err = spx_transmit(sk, skb, DATA, len);
760 	if(err)
761 		return (-EAGAIN);
762 
763         return (len);
764 }
765 
766 /* Send message/packet data to user-land */
spx_recvmsg(struct socket * sock,struct msghdr * msg,int size,int flags,struct scm_cookie * scm)767 static int spx_recvmsg(struct socket *sock, struct msghdr *msg, int size,
768 			int flags, struct scm_cookie *scm)
769 {
770 	struct sk_buff *skb;
771 	struct ipxspxhdr *ispxh;
772 	struct sock *sk = sock->sk;
773 	struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
774 	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;
775 	int copied, err;
776 
777         if(sk->zapped)
778                 return (-ENOTCONN); /* Socket not bound */
779 
780 	lock_sock(sk);
781 restart:
782         while(skb_queue_empty(&pdata->rcv_queue))      /* No data */
783         {
784                 /* Socket errors? */
785                 err = sock_error(sk);
786                 if(err)
787 			return (err);
788 
789                 /* Socket shut down? */
790                 if(sk->shutdown & RCV_SHUTDOWN)
791 			return (-ESHUTDOWN);
792 
793                 /* handle signals */
794                 if(signal_pending(current))
795 			return (-ERESTARTSYS);
796 
797                 /* User doesn't want to wait */
798                 if(flags&MSG_DONTWAIT)
799 			return (-EAGAIN);
800 
801 		release_sock(sk);
802         	save_flags(flags);
803         	cli();
804         	if(skb_peek(&pdata->rcv_queue) == NULL)
805                 	interruptible_sleep_on(sk->sleep);
806         	restore_flags(flags);
807         	lock_sock(sk);
808         }
809 
810         skb = skb_dequeue(&pdata->rcv_queue);
811         if(skb == NULL)
812 		goto restart;
813 
814 	ispxh 	= (struct ipxspxhdr *)skb->nh.raw;
815 	copied 	= ntohs(ispxh->ipx.ipx_pktsize) - SPX_SYS_PKT_LEN;
816         if(copied > size)
817 	{
818                 copied = size;
819                 msg->msg_flags |= MSG_TRUNC;
820         }
821 
822 	err = memcpy_toiovec(msg->msg_iov, skb->nh.raw+SPX_SYS_PKT_LEN, copied);
823         if(err)
824                 return (-EFAULT);
825 
826 	msg->msg_namelen = sizeof(*sipx);
827 	if(sipx)
828 	{
829 		sipx->sipx_family	= AF_IPX;
830                 sipx->sipx_port		= ispxh->ipx.ipx_source.sock;
831                 memcpy(sipx->sipx_node,ispxh->ipx.ipx_source.node,IPX_NODE_LEN);
832                 sipx->sipx_network	= ispxh->ipx.ipx_source.net;
833                 sipx->sipx_type 	= ispxh->ipx.ipx_type;
834         }
835 	kfree_skb(skb);
836         release_sock(sk);
837 
838 	return (copied);
839 }
840 
841 /*
842  * Functions which just wrap their IPX cousins
843  */
844 
spx_bind(struct socket * sock,struct sockaddr * uaddr,int addr_len)845 static int spx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
846 {
847         int err;
848         err = ipx_operations->bind(sock, uaddr, addr_len);
849         return (err);
850 }
851 
spx_getname(struct socket * sock,struct sockaddr * uaddr,int * usockaddr_len,int peer)852 static int spx_getname (struct socket *sock, struct sockaddr *uaddr,
853                          int *usockaddr_len, int peer)
854 {
855 	int err;
856 	err = ipx_operations->getname(sock, uaddr, usockaddr_len, peer);
857 	return (err);
858 }
859 
spx_ioctl(struct socket * sock,unsigned int cmd,unsigned long arg)860 static int spx_ioctl (struct socket *sock, unsigned int cmd,
861                          unsigned long arg)
862 {
863 	int err;
864 	err = ipx_operations->ioctl(sock, cmd, arg);
865 	return (err);
866 }
867 
spx_setsockopt(struct socket * sock,int level,int optname,char * optval,int optlen)868 static int spx_setsockopt(struct socket *sock, int level, int optname,
869                          char *optval, int optlen)
870 {
871 	int err;
872 	err = ipx_operations->setsockopt(sock, level, optname, optval, optlen);
873 	return (err);
874 }
875 
spx_getsockopt(struct socket * sock,int level,int optname,char * optval,int * optlen)876 static int spx_getsockopt(struct socket *sock, int level, int optname,
877                          char *optval, int *optlen)
878 {
879 	int err;
880 	err = ipx_operations->getsockopt(sock, level, optname, optval, optlen);
881 	return (err);
882 }
883 
884 static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
885 	family:		PF_IPX,
886 
887 	release:	spx_release,
888 	bind:		spx_bind,
889 	connect:	spx_connect,
890 	socketpair:	sock_no_socketpair,
891 	accept:		spx_accept,
892 	getname:	spx_getname,
893 	poll:		spx_datagram_poll,
894 	ioctl:		spx_ioctl,
895 	listen:		spx_listen,
896 	shutdown:	sock_no_shutdown,
897 	setsockopt:	spx_setsockopt,
898 	getsockopt:	spx_getsockopt,
899 	sendmsg:	spx_sendmsg,
900 	recvmsg:	spx_recvmsg,
901 	mmap:		sock_no_mmap,
902 	sendpage:	sock_no_sendpage,
903 };
904 
905 #include <linux/smp_lock.h>
906 SOCKOPS_WRAP(spx, PF_IPX);
907 
908 static struct net_proto_family spx_family_ops = {
909 	family:		PF_IPX,
910 	create:		spx_create,
911 };
912 
913 static char banner[] __initdata = KERN_INFO "NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0\n";
914 
spx_proto_init(void)915 static int __init spx_proto_init(void)
916 {
917 	int error;
918 
919 	connids = (__u16)jiffies;	/* initalize random */
920 
921 	error = ipx_register_spx(&ipx_operations, &spx_family_ops);
922         if (error)
923                 printk(KERN_ERR "SPX: unable to register with IPX.\n");
924 
925 	/* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
926 
927 	printk(banner);
928 	return 0;
929 }
930 module_init(spx_proto_init);
931 
spx_proto_finito(void)932 static void __exit spx_proto_finito(void)
933 {
934 	ipx_unregister_spx();
935 	return;
936 }
937 module_exit(spx_proto_finito);
938