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 */ 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 */ 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 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 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 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 */ 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. */ 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 */ 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 */ 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 */ 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 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 */ 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. */ 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 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 932 static void __exit spx_proto_finito(void) 933 { 934 ipx_unregister_spx(); 935 return; 936 } 937 module_exit(spx_proto_finito); 938
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.