* better
[mascara-docs.git] / i386 / linux-2.3.21 / net / ipx / af_spx.c
blobb9110c3ab2ee4980c1cd08b0b1663779f3939187
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
8 * Developers:
9 * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
10 * Jim Freeman <jfree@caldera.com>
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.
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>
32 #include <net/ipx.h>
33 #include <net/spx.h>
34 #include <net/sock.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;
42 static __u16 connids;
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;
58 pdata->sequence = 0;
59 pdata->acknowledge = 0;
60 pdata->source_connid = htons(connids);
61 pdata->rmt_seq = 0;
62 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;
73 pdata->retries = 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);
80 return (0);
83 static int spx_create(struct socket *sock, int protocol)
85 struct sock *sk;
88 * Called on connection receive so cannot be GFP_KERNEL
91 sk = sk_alloc(PF_IPX, GFP_ATOMIC, 1);
92 if(sk == NULL)
93 return (-ENOMEM);
95 switch(sock->type)
97 case SOCK_SEQPACKET:
98 sock->ops = &spx_ops;
99 break;
100 default:
101 sk_free(sk);
102 return (-ESOCKTNOSUPPORT);
105 sock_init_data(sock, sk);
106 spx_sock_init(sk);
107 sk->data_ready = spx_rcv;
108 sk->destruct = NULL;
109 sk->no_check = 1;
111 MOD_INC_USE_COUNT;
113 return (0);
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;
130 struct sk_buff *skb;
132 ipx_remove_socket(sk);
133 while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
134 kfree_skb(skb);
135 while((skb = skb_dequeue(&pdata->transmit_queue)) != NULL)
136 kfree_skb(skb);
137 while((skb = skb_dequeue(&pdata->retransmit_queue)) != NULL)
138 kfree_skb(skb);
139 while((skb = skb_dequeue(&pdata->rcv_queue)) != NULL)
140 kfree_skb(skb);
142 sk_free(sk);
143 MOD_DEC_USE_COUNT;
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;
152 if(sk == NULL)
153 return (0);
154 if(!sk->dead)
155 sk->state_change(sk);
156 sk->dead = 1;
158 if(pdata->state != SPX_CLOSED)
160 spx_transmit(sk, NULL, DISCON, 0);
161 spx_close_socket(sk);
164 sock->sk = NULL;
165 sk->socket = NULL;
166 spx_destroy_socket(sk);
168 return (0);
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)
177 return (-EINVAL);
178 if(sock->type != SOCK_SEQPACKET)
179 return (-EOPNOTSUPP);
180 if(sk->zapped != 0)
181 return (-EAGAIN);
183 sk->max_ack_backlog = backlog;
184 if(sk->state != TCP_LISTEN)
186 sk->ack_backlog = 0;
187 sk->state = TCP_LISTEN;
189 sk->socket->flags |= SO_ACCEPTCON;
191 return (0);
194 /* Accept a pending SPX connection */
195 static int spx_accept(struct socket *sock, struct socket *newsock, int flags)
197 struct sock *sk;
198 struct sock *newsk;
199 struct sk_buff *skb;
200 int err;
202 if(sock->sk == NULL)
203 return (-EINVAL);
204 sk = sock->sk;
206 if((sock->state != SS_UNCONNECTED) || !(sock->flags & SO_ACCEPTCON))
207 return (-EINVAL);
208 if(sock->type != SOCK_SEQPACKET)
209 return (-EOPNOTSUPP);
210 if(sk->state != TCP_LISTEN)
211 return (-EINVAL);
213 cli();
214 do {
215 skb = skb_dequeue(&sk->receive_queue);
216 if(skb == NULL)
218 if(flags & O_NONBLOCK)
220 sti();
221 return (-EWOULDBLOCK);
223 interruptible_sleep_on(sk->sleep);
224 if(signal_pending(current))
226 sti();
227 return (-ERESTARTSYS);
230 } while (skb == NULL);
232 newsk = skb->sk;
233 newsk->pair = NULL;
234 sti();
236 err = spx_transmit(newsk, skb, CONACK, 0); /* Connection ACK */
237 if(err)
238 return (err);
240 /* Now attach up the new socket */
241 sock->sk = NULL;
242 sk->ack_backlog--;
243 newsock->sk = newsk;
244 newsk->state = TCP_ESTABLISHED;
245 newsk->protinfo.af_ipx.dest_addr = newsk->tp_pinfo.af_spx.dest_addr;
247 return (0);
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;
257 struct sk_buff *skb;
258 int size, err;
260 size = sizeof(src);
261 err = ipx_operations->getname(sock, (struct sockaddr *)&src, &size, 0);
262 if(err)
263 return (err);
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);
270 if(err)
271 return (err);
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);
280 if(err)
281 return (err);
283 cli();
284 do {
285 skb = skb_dequeue(&sk->receive_queue);
286 if(skb == NULL)
288 if(flags & O_NONBLOCK)
290 sti();
291 return (-EWOULDBLOCK);
293 interruptible_sleep_on(sk->sleep);
294 if(signal_pending(current))
296 sti();
297 return (-ERESTARTSYS);
300 } while (skb == NULL);
302 if(pdata->state == SPX_CLOSED)
304 sti();
305 del_timer(&pdata->watchdog);
306 return (-ETIMEDOUT);
309 sock->state = SS_CONNECTED;
310 sk->state = TCP_ESTABLISHED;
311 kfree_skb(skb);
312 sti();
314 return (0);
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)
328 if(tries < 1)
329 return (RETRY_TIME);
330 if(tries > 5)
331 return (MAX_RETRY_DELAY);
332 return (tries * HZ);
335 static int spx_route_skb(struct spx_opt *pdata, struct sk_buff *skb, int type)
337 struct sk_buff *skb2;
338 int err = 0;
340 skb = skb_unshare(skb, GFP_ATOMIC);
341 if(skb == NULL)
342 return (-ENOBUFS);
344 switch(type)
346 case (CONREQ):
347 case (DATA):
348 if(!skb_queue_empty(&pdata->retransmit_queue))
350 skb_queue_tail(&pdata->transmit_queue, skb);
351 return 0;
354 case (TQUEUE):
355 pdata->retransmit.expires = jiffies + spx_calc_rtt(0);
356 add_timer(&pdata->retransmit);
358 skb2 = skb_clone(skb, GFP_BUFFER);
359 if(skb2 == NULL)
360 return -ENOBUFS;
361 skb_queue_tail(&pdata->retransmit_queue, skb2);
363 case (ACK):
364 case (CONACK):
365 case (WDREQ):
366 case (WDACK):
367 case (DISCON):
368 case (DISACK):
369 case (RETRAN):
370 default:
371 /* Send data */
372 err = ipxrtr_route_skb(skb);
373 if(err)
374 kfree_skb(skb);
377 return (err);
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;
385 unsigned long flags;
386 int err;
388 if(skb == NULL)
390 int offset = ipx_if_offset(pdata->dest_addr.net);
391 int size = offset + sizeof(struct ipxspxhdr);
393 save_flags(flags);
394 cli();
395 skb = sock_alloc_send_skb(sk, size, 1, 0, &err);
396 if(skb == NULL)
397 return (-ENOMEM);
398 skb_reserve(skb, offset);
399 skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
400 restore_flags(flags);
403 /* IPX header */
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;
412 /* SPX header */
413 ipxh->spx.dtype = 0;
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);
425 switch(type)
427 case (DATA): /* Data */
428 ipxh->ipx.ipx_pktsize = htons(SPX_SYS_PKT_LEN + len);
429 ipxh->spx.cctl = (CCTL_ACK | CCTL_EOM);
430 pdata->sequence++;
431 break;
433 case (ACK): /* ACK */
434 pdata->rmt_seq++;
435 case (WDACK): /* WD ACK */
436 case (CONACK): /* Connection ACK */
437 ipxh->spx.cctl = CCTL_SYS;
438 ipxh->spx.ackseq = htons(pdata->rmt_seq);
439 break;
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);
451 break;
453 case (DISCON): /* Informed Disconnect */
454 ipxh->spx.cctl = CCTL_ACK;
455 ipxh->spx.dtype = SPX_DTYPE_ECONN;
456 break;
458 case (DISACK): /* Informed Disconnect ACK */
459 ipxh->spx.cctl = 0;
460 ipxh->spx.dtype = SPX_DTYPE_ECACK;
461 ipxh->spx.sequence = 0;
462 ipxh->spx.ackseq = htons(pdata->rmt_seq++);
463 break;
465 default:
466 return (-EOPNOTSUPP);
469 /* Send data */
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)
481 return;
482 if(pdata->retries > pdata->max_retries)
484 spx_close_socket(sk); /* Unilateral Abort */
485 return;
488 /* Send WD request */
489 spx_transmit(sk, NULL, WDREQ, 0);
490 pdata->retries++;
492 return;
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;
499 struct sk_buff *skb;
500 unsigned long flags;
501 int err;
503 del_timer(&pdata->retransmit);
504 if(pdata->state == SPX_CLOSED)
505 return;
506 if(pdata->retransmits > RETRY_COUNT)
508 spx_close_socket(sk); /* Unilateral Abort */
509 return;
512 /* Need to leave skb on the queue, aye the fear */
513 save_flags(flags);
514 cli();
515 skb = skb_peek(&pdata->retransmit_queue);
516 if(skb_cloned(skb))
517 skb = skb_copy(skb, GFP_ATOMIC);
518 else
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++;
528 return;
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;
535 struct sk_buff *skb;
537 skb = skb_dequeue(&pdata->retransmit_queue);
538 if(!skb)
539 return (-ENOENT);
541 /* Check Data/ACK seq */
542 switch(type)
544 case ACK: /* Check Sequence, Should == 1 */
545 ipxh = (struct ipxspxhdr *)skb->nh.raw;
546 if(!(ntohs(ipxh->spx.sequence) - htons(ackseq)))
547 break;
549 case CONACK:
550 del_timer(&pdata->retransmit);
551 pdata->retransmits = 0;
552 kfree_skb(skb);
553 if(skb_queue_empty(&pdata->retransmit_queue))
555 skb = skb_dequeue(&pdata->transmit_queue);
556 if(skb != NULL)
557 spx_route_skb(pdata, skb, TQUEUE);
559 return (0);
562 skb_queue_head(&pdata->retransmit_queue, skb);
563 return (-1);
566 /* SPX packet receive engine */
567 void spx_rcv(struct sock *sk, int bytes)
569 struct sk_buff *skb;
570 struct ipxspxhdr *ipxh;
571 struct spx_opt *pdata = &sk->tp_pinfo.af_spx;
573 skb = skb_dequeue(&sk->receive_queue);
574 if(skb == NULL)
575 return;
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))
580 goto toss_skb;
581 if(ntohs(ipxh->ipx.ipx_pktsize) < SPX_SYS_PKT_LEN)
582 goto toss_skb;
583 if(ipxh->ipx.ipx_type != IPX_TYPE_SPX)
584 goto toss_skb;
585 if(ntohs(ipxh->spx.ackseq) > pdata->sequence)
586 goto toss_skb;
588 /* Reset WD timer on any received packet */
589 del_timer(&pdata->watchdog);
590 pdata->retries = 0;
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);
612 goto finish;
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)
626 goto toss_skb;
628 skb_queue_tail(&sk->receive_queue, skb);
629 wake_up_interruptible(sk->sleep);
630 goto finish;
633 spx_retransmit_chk(pdata, ipxh->spx.ackseq, ACK);
634 goto toss_skb;
636 case (CCTL_ACK):
637 /* Informed Disconnect */
638 if(ipxh->spx.dtype == SPX_DTYPE_ECONN)
641 spx_transmit(sk, skb, DISACK, 0);
642 spx_close_socket(sk);
643 goto finish;
645 /* Fall through */
647 default:
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);
659 goto finish;
662 if(ipxh->spx.dtype == SPX_DTYPE_ECACK)
664 if(pdata->state != SPX_CLOSED)
665 spx_close_socket(sk);
666 goto toss_skb;
670 toss_skb: /* Catch All */
671 kfree_skb(skb);
672 finish:
673 return;
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;
682 struct sk_buff *skb;
683 int err, offset, size;
685 if(len > 534)
686 return (-EMSGSIZE);
687 if(sk->zapped)
688 return (-ENOTCONN); /* Socket not bound */
689 if(flags&~MSG_DONTWAIT)
690 return (-EINVAL);
692 offset = ipx_if_offset(sk->tp_pinfo.af_spx.dest_addr.net);
693 size = offset + sizeof(struct ipxspxhdr) + len;
695 cli();
696 skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
697 if(skb == NULL)
698 return (err);
699 sti();
701 skb->sk = sk;
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);
706 if(err)
708 kfree_skb(skb);
709 return (-EFAULT);
712 err = spx_transmit(sk, skb, DATA, len);
713 if(err)
714 return (-EAGAIN);
716 return (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)
723 struct sk_buff *skb;
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;
728 int copied, err;
730 if(sk->zapped)
731 return (-ENOTCONN); /* Socket not bound */
733 lock_sock(sk);
734 restart:
735 while(skb_queue_empty(&pdata->rcv_queue)) /* No data */
737 /* Socket errors? */
738 err = sock_error(sk);
739 if(err)
740 return (err);
742 /* Socket shut down? */
743 if(sk->shutdown & RCV_SHUTDOWN)
744 return (-ESHUTDOWN);
746 /* handle signals */
747 if(signal_pending(current))
748 return (-ERESTARTSYS);
750 /* User doesn't want to wait */
751 if(flags&MSG_DONTWAIT)
752 return (-EAGAIN);
754 release_sock(sk);
755 save_flags(flags);
756 cli();
757 if(skb_peek(&pdata->rcv_queue) == NULL)
758 interruptible_sleep_on(sk->sleep);
759 restore_flags(flags);
760 lock_sock(sk);
763 skb = skb_dequeue(&pdata->rcv_queue);
764 if(skb == NULL)
765 goto restart;
767 ispxh = (struct ipxspxhdr *)skb->nh.raw;
768 copied = ntohs(ispxh->ipx.ipx_pktsize) - SPX_SYS_PKT_LEN;
769 if(copied > size)
771 copied = size;
772 msg->msg_flags |= MSG_TRUNC;
775 err = memcpy_toiovec(msg->msg_iov, skb->nh.raw+SPX_SYS_PKT_LEN, copied);
776 if(err)
777 return (-EFAULT);
779 msg->msg_namelen = sizeof(*sipx);
780 if(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;
788 kfree_skb(skb);
789 release_sock(sk);
791 return (copied);
795 * Functions which just wrap their IPX cousins
798 static int spx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
800 int err;
801 err = ipx_operations->bind(sock, uaddr, addr_len);
802 return (err);
805 static int spx_getname (struct socket *sock, struct sockaddr *uaddr,
806 int *usockaddr_len, int peer)
808 int err;
809 err = ipx_operations->getname(sock, uaddr, usockaddr_len, peer);
810 return (err);
813 static int spx_ioctl (struct socket *sock, unsigned int cmd,
814 unsigned long arg)
816 int err;
817 err = ipx_operations->ioctl(sock, cmd, arg);
818 return (err);
821 static int spx_setsockopt(struct socket *sock, int level, int optname,
822 char *optval, int optlen)
824 int err;
825 err = ipx_operations->setsockopt(sock, level, optname, optval, optlen);
826 return (err);
829 static int spx_getsockopt(struct socket *sock, int level, int optname,
830 char *optval, int *optlen)
832 int err;
833 err = ipx_operations->getsockopt(sock, level, optname, optval, optlen);
834 return (err);
837 static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = {
838 PF_IPX,
839 spx_release,
840 spx_bind,
841 spx_connect,
842 sock_no_socketpair,
843 spx_accept,
844 spx_getname,
845 datagram_poll, /* this does seqpacket too */
846 spx_ioctl,
847 spx_listen,
848 sock_no_shutdown,
849 spx_setsockopt,
850 spx_getsockopt,
851 sock_no_fcntl,
852 spx_sendmsg,
853 spx_recvmsg,
854 sock_no_mmap
857 #include <linux/smp_lock.h>
858 SOCKOPS_WRAP(spx, PF_IPX);
861 static struct net_proto_family spx_family_ops=
863 PF_IPX,
864 spx_create
868 void spx_proto_init(void)
870 int error;
872 connids = (__u16)jiffies; /* initalize random */
874 error = ipx_register_spx(&ipx_operations, &spx_family_ops);
875 if (error)
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");
881 return;
884 void spx_proto_finito(void)
886 ipx_unregister_spx();
887 return;
890 #ifdef MODULE
892 int init_module(void)
894 spx_proto_init();
895 return 0;
898 void cleanup_module(void)
900 spx_proto_finito();
901 return;
904 #endif /* MODULE */
905 #endif /* CONFIG_SPX || CONFIG_SPX_MODULE */