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