1 /* 2 * Copyright (c) University of British Columbia, 1984 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Laboratory for Computation Vision and the Computer Science Department 8 * of the University of British Columbia. 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)pk_subr.c 7.9 (Berkeley) 01/09/91 13 */ 14 15 #include "param.h" 16 #include "systm.h" 17 #include "mbuf.h" 18 #include "socket.h" 19 #include "protosw.h" 20 #include "socketvar.h" 21 #include "errno.h" 22 #include "time.h" 23 #include "kernel.h" 24 25 #include "../net/if.h" 26 27 #include "x25.h" 28 #include "pk.h" 29 #include "pk_var.h" 30 #include "x25err.h" 31 32 int pk_sendspace = 1024 * 2 + 8; 33 int pk_recvspace = 1024 * 2 + 8; 34 35 /* 36 * Attach X.25 protocol to socket, allocate logical channel descripter 37 * and buffer space, and enter LISTEN state if we are to accept 38 * IN-COMMING CALL packets. 39 * 40 */ 41 42 struct pklcd * 43 pk_attach (so) 44 struct socket *so; 45 { 46 register struct pklcd *lcp; 47 register int error = ENOBUFS; 48 49 MALLOC(lcp, struct pklcd *, sizeof(*lcp), M_PCB, M_NOWAIT); 50 if (lcp) { 51 bzero((caddr_t)lcp, sizeof(*lcp)); 52 if (so) { 53 error = soreserve (so, pk_sendspace, pk_recvspace); 54 lcp -> lcd_so = so; 55 if (so -> so_options & SO_ACCEPTCONN) 56 lcp -> lcd_state = LISTEN; 57 else 58 lcp -> lcd_state = READY; 59 } else 60 sbreserve (&lcp -> lcd_sb, pk_sendspace); 61 } 62 if (so) { 63 so -> so_pcb = (caddr_t) lcp; 64 so -> so_error = error; 65 } 66 return (lcp); 67 } 68 69 /* 70 * Disconnect X.25 protocol from socket. 71 */ 72 73 pk_disconnect (lcp) 74 register struct pklcd *lcp; 75 { 76 register struct socket *so = lcp -> lcd_so; 77 register struct pklcd *l, *p; 78 79 switch (lcp -> lcd_state) { 80 case LISTEN: 81 for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 82 if (p == 0) { 83 if (l != 0) 84 pk_listenhead = l -> lcd_listen; 85 } 86 else 87 if (l != 0) 88 p -> lcd_listen = l -> lcd_listen; 89 pk_close (lcp); 90 break; 91 92 case READY: 93 pk_acct (lcp); 94 pk_close (lcp); 95 break; 96 97 case SENT_CLEAR: 98 case RECEIVED_CLEAR: 99 break; 100 101 default: 102 pk_acct (lcp); 103 if (so) { 104 soisdisconnecting (so); 105 sbflush (&so -> so_rcv); 106 } 107 pk_clear (lcp, 241, 0); /* Normal Disconnect */ 108 109 } 110 } 111 112 /* 113 * Close an X.25 Logical Channel. Discard all space held by the 114 * connection and internal descriptors. Wake up any sleepers. 115 */ 116 117 pk_close (lcp) 118 struct pklcd *lcp; 119 { 120 register struct socket *so = lcp -> lcd_so; 121 122 pk_freelcd (lcp); 123 124 if (so == NULL) 125 return; 126 127 so -> so_pcb = 0; 128 soisdisconnected (so); 129 /* sofree (so); /* gak!!! you can't do that here */ 130 } 131 132 /* 133 * Create a template to be used to send X.25 packets on a logical 134 * channel. It allocates an mbuf and fills in a skeletal packet 135 * depending on its type. This packet is passed to pk_output where 136 * the remainer of the packet is filled in. 137 */ 138 139 struct mbuf * 140 pk_template (lcn, type) 141 int lcn, type; 142 { 143 register struct mbuf *m; 144 register struct x25_packet *xp; 145 146 MGETHDR (m, M_DONTWAIT, MT_HEADER); 147 if (m == 0) 148 panic ("pk_template"); 149 m -> m_act = 0; 150 151 /* 152 * Efficiency hack: leave a four byte gap at the beginning 153 * of the packet level header with the hope that this will 154 * be enough room for the link level to insert its header. 155 */ 156 m -> m_data += max_linkhdr; 157 m -> m_len = PKHEADERLN; 158 159 xp = mtod (m, struct x25_packet *); 160 *(long *)xp = 0; /* ugly, but fast */ 161 /* xp -> q_bit = 0;*/ 162 xp -> fmt_identifier = 1; 163 /* xp -> lc_group_number = 0;*/ 164 165 SET_LCN(xp, lcn); 166 xp -> packet_type = type; 167 168 return (m); 169 } 170 171 /* 172 * This routine restarts all the virtual circuits. Actually, 173 * the virtual circuits are not "restarted" as such. Instead, 174 * any active switched circuit is simply returned to READY 175 * state. 176 */ 177 178 pk_restart (pkp, restart_cause) 179 register struct pkcb *pkp; 180 int restart_cause; 181 { 182 register struct mbuf *m; 183 register struct pklcd *lcp; 184 register int i; 185 186 /* Restart all logical channels. */ 187 if (pkp -> pk_chan == 0) 188 return; 189 for (i = 1; i <= pkp -> pk_maxlcn; ++i) 190 if ((lcp = pkp -> pk_chan[i]) != NULL) { 191 if (lcp -> lcd_so) { 192 lcp -> lcd_so -> so_error = ENETRESET; 193 pk_close (lcp); 194 } else { 195 pk_flush (lcp); 196 lcp -> lcd_state = READY; 197 if (lcp -> lcd_upper) 198 lcp -> lcd_upper(lcp, 0); 199 } 200 } 201 202 if (restart_cause < 0) 203 return; 204 205 pkp -> pk_state = DTE_SENT_RESTART; 206 lcp = pkp -> pk_chan[0]; 207 m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 208 m -> m_len += 2; 209 mtod(m, struct x25_packet *) -> packet_data = 0; /* DTE only */ 210 mtod(m, octet *)[4] = restart_cause; 211 pk_output (lcp); 212 } 213 214 215 /* 216 * This procedure frees up the Logical Channel Descripter. 217 */ 218 219 pk_freelcd (lcp) 220 register struct pklcd *lcp; 221 { 222 if (lcp == NULL) 223 return; 224 225 if (lcp -> lcd_lcn > 0) 226 lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 227 228 pk_flush(lcp); 229 free((caddr_t)lcp, M_PCB); 230 } 231 232 233 /* 234 * Bind a address and protocol value to a socket. The important 235 * part is the protocol value - the first four characters of the 236 * Call User Data field. 237 */ 238 239 pk_bind (lcp, nam) 240 struct pklcd *lcp; 241 struct mbuf *nam; 242 { 243 register struct pkcb *pkp; 244 register struct pklcd *pp; 245 register struct sockaddr_x25 *sa; 246 247 if (nam == NULL) 248 return (EADDRNOTAVAIL); 249 if (lcp -> lcd_ceaddr) /* XXX */ 250 return (EADDRINUSE); 251 if (pk_checksockaddr (nam)) 252 return (EINVAL); 253 sa = mtod (nam, struct sockaddr_x25 *); 254 255 /* 256 * If the user wishes to accept calls only from a particular 257 * net (net != 0), make sure the net is known 258 */ 259 260 if (sa -> x25_net) 261 for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 262 if (pkp == 0) 263 return (ENETUNREACH); 264 if (pkp -> pk_xcp -> xc_addr.x25_net == sa -> x25_net) 265 break; 266 } 267 268 /* 269 * For ISO's sake permit default listeners, but only one such . . . 270 */ 271 for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) { 272 register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr; 273 if ((sa2 -> x25_udlen == sa -> x25_udlen) && 274 (sa2 -> x25_udlen == 0 || 275 (bcmp (sa2 -> x25_udata, sa -> x25_udata, 276 min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0))) 277 return (EADDRINUSE); 278 } 279 lcp -> lcd_laddr = *sa; 280 lcp -> lcd_ceaddr = &lcp -> lcd_laddr; 281 return (0); 282 } 283 284 /* 285 * Include a bound control block in the list of listeners. 286 */ 287 pk_listen (lcp) 288 register struct pklcd *lcp; 289 { 290 register struct pklcd **pp; 291 292 if (lcp -> lcd_ceaddr == 0) 293 return (EDESTADDRREQ); 294 295 lcp -> lcd_state = LISTEN; 296 /* 297 * Add default listener at end, any others at start. 298 */ 299 if (lcp -> lcd_ceaddr -> x25_udlen == 0) { 300 for (pp = &pk_listenhead; *pp; ) 301 pp = &((*pp) -> lcd_listen); 302 *pp = lcp; 303 } else { 304 lcp -> lcd_listen = pk_listenhead; 305 pk_listenhead = lcp; 306 } 307 return (0); 308 } 309 /* 310 * Include a listening control block for the benefit of other protocols. 311 */ 312 pk_protolisten (spi, spilen, callee) 313 int (*callee)(); 314 { 315 register struct pklcd *lcp = pk_attach ((struct socket *)0); 316 register struct mbuf *nam; 317 register struct sockaddr_x25 *sa; 318 int error = ENOBUFS; 319 320 if (lcp) { 321 if (nam = m_getclr(MT_SONAME, M_DONTWAIT)) { 322 sa = mtod(nam, struct sockaddr_x25 *); 323 sa -> x25_family = AF_CCITT; 324 sa -> x25_len = nam -> m_len = sizeof (*sa); 325 sa -> x25_udlen = spilen; 326 sa -> x25_udata[0] = spi; 327 lcp -> lcd_upper = callee; 328 lcp -> lcd_flags = X25_MBS_HOLD; 329 error = pk_bind (lcp, nam) || pk_listen (lcp); 330 (void) m_free (nam); 331 } 332 if (error) 333 pk_freelcd(lcp); 334 } 335 return error; /* Hopefully Zero !*/ 336 } 337 338 /* 339 * Associate a logical channel descriptor with a network. 340 * Fill in the default network specific parameters and then 341 * set any parameters explicitly specified by the user or 342 * by the remote DTE. 343 */ 344 345 pk_assoc (pkp, lcp, sa) 346 register struct pkcb *pkp; 347 register struct pklcd *lcp; 348 register struct sockaddr_x25 *sa; 349 { 350 351 lcp -> lcd_pkp = pkp; 352 lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 353 lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 354 lcp -> lcd_rsn = MODULUS - 1; 355 pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 356 357 if (sa -> x25_opts.op_psize) 358 lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 359 else 360 sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 361 if (sa -> x25_opts.op_wsize) 362 lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 363 else 364 sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 365 sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net; 366 lcp -> lcd_flags = sa -> x25_opts.op_flags; 367 lcp -> lcd_stime = time.tv_sec; 368 } 369 370 pk_connect (lcp, sa) 371 register struct pklcd *lcp; 372 register struct sockaddr_x25 *sa; 373 { 374 register struct pkcb *pkp; 375 376 if (sa -> x25_addr[0] == '\0') 377 return (EDESTADDRREQ); 378 if (lcp -> lcd_pkp == 0) 379 for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 380 if (pkp == 0) 381 return (ENETUNREACH); 382 /* 383 * use first net configured (last in list 384 * headed by pkcbhead) if net is zero 385 */ 386 if (sa -> x25_net == 0 && pkp -> pk_next == 0) 387 break; 388 if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net) 389 break; 390 } 391 392 if (pkp -> pk_state != DTE_READY) 393 return (ENETDOWN); 394 if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 395 return (EMFILE); 396 lcp -> lcd_faddr = *sa; 397 lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 398 pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 399 if (lcp -> lcd_so) 400 soisconnecting (lcp -> lcd_so); 401 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 402 pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 403 return (*pkp -> pk_start)(lcp); 404 } 405 406 /* 407 * Build the rest of the CALL REQUEST packet. Fill in calling 408 * address, facilities fields and the user data field. 409 */ 410 411 pk_callrequest (lcp, sa, xcp) 412 struct pklcd *lcp; 413 register struct sockaddr_x25 *sa; 414 register struct x25config *xcp; 415 { 416 register struct x25_calladdr *a; 417 register struct mbuf *m = lcp -> lcd_template; 418 register struct x25_packet *xp = mtod(m, struct x25_packet *); 419 unsigned posn = 0; 420 octet *cp; 421 422 if (lcp -> lcd_flags & X25_DBIT) 423 xp -> d_bit = 1; 424 a = (struct x25_calladdr *) &xp -> packet_data; 425 a -> calling_addrlen = strlen (xcp -> xc_addr.x25_addr); 426 a -> called_addrlen = strlen (sa -> x25_addr); 427 cp = (octet *) a -> address_field; 428 to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn); 429 to_bcd (&cp, (int)a -> calling_addrlen, xcp -> xc_addr.x25_addr, &posn); 430 if (posn & 0x01) 431 *cp++ &= 0xf0; 432 m -> m_len += cp - (octet *) a; 433 434 if (lcp -> lcd_facilities) { 435 m -> m_next = lcp -> lcd_facilities; 436 lcp -> lcd_facilities = 0; 437 m -> m_pkthdr.len += m -> m_next -> m_len; 438 } else 439 build_facilities (m, sa, (int)xcp -> xc_type); 440 441 m_copyback(m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata); 442 #ifdef ANDREW 443 printf ("call: "); 444 for (cp = mtod (m, octet *), posn = 0; posn < m -> m_len; ++posn) 445 printf ("%x ", *cp++); 446 printf ("\n"); 447 #endif 448 } 449 450 build_facilities (m, sa, type) 451 register struct mbuf *m; 452 struct sockaddr_x25 *sa; 453 { 454 register octet *cp; 455 register octet *fcp; 456 register int revcharge; 457 458 cp = mtod(m, octet *) + m -> m_len; 459 fcp = cp + 1; 460 revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 461 /* 462 * This is specific to Datapac X.25(1976) DTEs. International 463 * calls must have the "hi priority" bit on. 464 */ 465 if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 466 revcharge |= 02; 467 if (revcharge) { 468 *fcp++ = FACILITIES_REVERSE_CHARGE; 469 *fcp++ = revcharge; 470 } 471 switch (type) { 472 case X25_1980: 473 case X25_1984: 474 *fcp++ = FACILITIES_PACKETSIZE; 475 *fcp++ = sa -> x25_opts.op_psize; 476 *fcp++ = sa -> x25_opts.op_psize; 477 478 *fcp++ = FACILITIES_WINDOWSIZE; 479 *fcp++ = sa -> x25_opts.op_wsize; 480 *fcp++ = sa -> x25_opts.op_wsize; 481 } 482 *cp = fcp - cp - 1; 483 m -> m_pkthdr.len = (m -> m_len += *cp + 1); 484 } 485 486 to_bcd (a, len, x, posn) 487 register octet **a; 488 register char *x; 489 register int len; 490 register unsigned *posn; 491 { 492 while (--len >= 0) 493 if ((*posn)++ & 0x01) 494 *(*a)++ |= *x++ & 0x0F; 495 else 496 **a = *x++ << 4; 497 } 498 499 /* 500 * This routine gets the first available logical channel number. The 501 * search is from the highest number to lowest number (DTE). 502 */ 503 504 pk_getlcn (pkp) 505 register struct pkcb *pkp; 506 { 507 register int i; 508 509 if (pkp -> pk_chan == 0) 510 return (0); 511 for (i = pkp -> pk_maxlcn; i > 0; --i) 512 if (pkp -> pk_chan[i] == NULL) 513 break; 514 return (i); 515 516 } 517 518 /* 519 * This procedure sends a CLEAR request packet. The lc state is 520 * set to "SENT_CLEAR". 521 */ 522 523 pk_clear (lcp, diagnostic, abortive) 524 register struct pklcd *lcp; 525 { 526 register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR); 527 528 m -> m_len += 2; 529 mtod(m, struct x25_packet *) -> packet_data = 0; 530 mtod(m, octet *)[4] = diagnostic; 531 if (lcp -> lcd_facilities) { 532 m -> m_next = lcp -> lcd_facilities; 533 m -> m_pkthdr.len += m -> m_next -> m_len; 534 lcp -> lcd_facilities = 0; 535 } 536 if (abortive) 537 lcp -> lcd_template = m; 538 else { 539 struct socket *so = lcp -> lcd_so; 540 struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb; 541 sbappendrecord(sb, m); 542 } 543 pk_output (lcp); 544 545 } 546 547 /* 548 * This procedure sends a RESET request packet. It re-intializes 549 * virtual circuit. 550 */ 551 552 static 553 pk_reset (lcp, diagnostic) 554 register struct pklcd *lcp; 555 { 556 register struct mbuf *m; 557 register struct socket *so = lcp -> lcd_so; 558 559 if (lcp -> lcd_state != DATA_TRANSFER) 560 return; 561 562 if (so) 563 so -> so_error = ECONNRESET; 564 lcp -> lcd_reset_condition = TRUE; 565 566 /* Reset all the control variables for the channel. */ 567 pk_flush (lcp); 568 lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 569 lcp -> lcd_intrconf_pending = FALSE; 570 lcp -> lcd_rsn = MODULUS - 1; 571 lcp -> lcd_ssn = 0; 572 lcp -> lcd_output_window = lcp -> lcd_input_window = 573 lcp -> lcd_last_transmitted_pr = 0; 574 m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 575 m -> m_len += 2; 576 mtod(m, struct x25_packet *) -> packet_data = 0; 577 mtod(m, octet *)[4] = diagnostic; 578 pk_output (lcp); 579 580 } 581 582 /* 583 * This procedure frees all data queued for output or delivery on a 584 * virtual circuit. 585 */ 586 587 pk_flush (lcp) 588 register struct pklcd *lcp; 589 { 590 register struct socket *so; 591 592 if (lcp -> lcd_template) 593 m_freem (lcp -> lcd_template); 594 595 if (lcp -> lcd_cps) { 596 m_freem(lcp -> lcd_cps); 597 lcp -> lcd_cps = 0; 598 } 599 if (so = lcp -> lcd_so) { 600 sbflush (&so -> so_rcv); 601 sbflush (&so -> so_snd); 602 } else 603 sbflush (&lcp -> lcd_sb); 604 } 605 606 607 /* 608 * This procedure handles all local protocol procedure errors. 609 */ 610 611 pk_procerror (error, lcp, errstr, diagnostic) 612 register struct pklcd *lcp; 613 char *errstr; 614 { 615 616 pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 617 618 switch (error) { 619 case CLEAR: 620 if (lcp -> lcd_so) { 621 lcp -> lcd_so -> so_error = ECONNABORTED; 622 soisdisconnecting (lcp -> lcd_so); 623 } 624 pk_clear (lcp, diagnostic, 1); 625 break; 626 627 case RESET: 628 pk_reset (lcp, diagnostic); 629 } 630 } 631 632 /* 633 * This procedure is called during the DATA TRANSFER state to check 634 * and process the P(R) values received in the DATA, RR OR RNR 635 * packets. 636 */ 637 638 pk_ack (lcp, pr) 639 struct pklcd *lcp; 640 unsigned pr; 641 { 642 register struct socket *so = lcp -> lcd_so; 643 644 if (lcp -> lcd_output_window == pr) 645 return (PACKET_OK); 646 if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 647 if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 648 pk_procerror (RESET, lcp, 649 "p(r) flow control error", 2); 650 return (ERROR_PACKET); 651 } 652 } 653 else { 654 if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 655 pk_procerror (RESET, lcp, 656 "p(r) flow control error", 2); 657 return (ERROR_PACKET); 658 } 659 } 660 661 lcp -> lcd_output_window = pr; /* Rotate window. */ 662 if (lcp -> lcd_window_condition == TRUE) 663 lcp -> lcd_window_condition = FALSE; 664 665 if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel)) 666 sowwakeup (so); 667 if (lcp -> lcd_upper) 668 (*lcp -> lcd_upper)(lcp, 0); 669 670 return (PACKET_OK); 671 } 672 673 /* 674 * This procedure decodes the X.25 level 3 packet returning a 675 * code to be used in switchs or arrays. 676 */ 677 678 pk_decode (xp) 679 register struct x25_packet *xp; 680 { 681 register int type; 682 683 if (xp -> fmt_identifier != 1) 684 return (INVALID_PACKET); 685 #ifdef ancient_history 686 /* 687 * Make sure that the logical channel group number is 0. 688 * This restriction may be removed at some later date. 689 */ 690 if (xp -> lc_group_number != 0) 691 return (INVALID_PACKET); 692 #endif 693 /* 694 * Test for data packet first. 695 */ 696 if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 697 return (DATA); 698 699 /* 700 * Test if flow control packet (RR or RNR). 701 */ 702 if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 703 if (!(xp -> packet_type & RR_PACKET_DESIGNATOR)) 704 return (RR); 705 else 706 return (RNR); 707 708 /* 709 * Determine the rest of the packet types. 710 */ 711 switch (xp -> packet_type) { 712 case X25_CALL: 713 type = CALL; 714 break; 715 716 case X25_CALL_ACCEPTED: 717 type = CALL_ACCEPTED; 718 break; 719 720 case X25_CLEAR: 721 type = CLEAR; 722 break; 723 724 case X25_CLEAR_CONFIRM: 725 type = CLEAR_CONF; 726 break; 727 728 case X25_INTERRUPT: 729 type = INTERRUPT; 730 break; 731 732 case X25_INTERRUPT_CONFIRM: 733 type = INTERRUPT_CONF; 734 break; 735 736 case X25_RESET: 737 type = RESET; 738 break; 739 740 case X25_RESET_CONFIRM: 741 type = RESET_CONF; 742 break; 743 744 case X25_RESTART: 745 type = RESTART; 746 break; 747 748 case X25_RESTART_CONFIRM: 749 type = RESTART_CONF; 750 break; 751 752 default: 753 type = INVALID_PACKET; 754 } 755 return (type); 756 } 757 758 /* 759 * A restart packet has been received. Print out the reason 760 * for the restart. 761 */ 762 763 pk_restartcause (pkp, xp) 764 struct pkcb *pkp; 765 register struct x25_packet *xp; 766 { 767 register struct x25config *xcp = pkp -> pk_xcp; 768 register int lcn = LCN(xp); 769 770 switch (xp -> packet_data) { 771 case X25_RESTART_LOCAL_PROCEDURE_ERROR: 772 pk_message (lcn, xcp, "restart: local procedure error"); 773 break; 774 775 case X25_RESTART_NETWORK_CONGESTION: 776 pk_message (lcn, xcp, "restart: network congestion"); 777 break; 778 779 case X25_RESTART_NETWORK_OPERATIONAL: 780 pk_message (lcn, xcp, "restart: network operational"); 781 break; 782 783 default: 784 pk_message (lcn, xcp, "restart: unknown cause"); 785 } 786 } 787 788 #define MAXRESETCAUSE 7 789 790 int Reset_cause[] = { 791 EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 792 }; 793 794 /* 795 * A reset packet has arrived. Return the cause to the user. 796 */ 797 798 pk_resetcause (pkp, xp) 799 struct pkcb *pkp; 800 register struct x25_packet *xp; 801 { 802 register struct pklcd *lcp = 803 pkp -> pk_chan[LCN(xp)]; 804 register int code = xp -> packet_data; 805 806 if (code > MAXRESETCAUSE) 807 code = 7; /* EXRNCG */ 808 809 lcp -> lcd_so -> so_error = Reset_cause[code]; 810 } 811 812 #define MAXCLEARCAUSE 25 813 814 int Clear_cause[] = { 815 EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 816 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 817 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 818 }; 819 820 /* 821 * A clear packet has arrived. Return the cause to the user. 822 */ 823 824 pk_clearcause (pkp, xp) 825 struct pkcb *pkp; 826 register struct x25_packet *xp; 827 { 828 register struct pklcd *lcp = 829 pkp -> pk_chan[LCN(xp)]; 830 register int code = xp -> packet_data; 831 832 if (code > MAXCLEARCAUSE) 833 code = 5; /* EXRNCG */ 834 lcp -> lcd_so -> so_error = Clear_cause[code]; 835 } 836 837 char * 838 format_ntn (xcp) 839 register struct x25config *xcp; 840 { 841 842 return (xcp -> xc_addr.x25_addr); 843 } 844 845 /* VARARGS1 */ 846 pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 847 struct x25config *xcp; 848 char *fmt; 849 { 850 851 if (lcn) 852 if (pkcbhead -> pk_next) 853 printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 854 else 855 printf ("X.25: lcn %d: ", lcn); 856 else 857 if (pkcbhead -> pk_next) 858 printf ("X.25(%s): ", format_ntn (xcp)); 859 else 860 printf ("X.25: "); 861 862 printf (fmt, a1, a2, a3, a4, a5, a6); 863 printf ("\n"); 864 } 865 866 pk_ifattach(ia, lloutput, llnext) 867 register struct x25_ifaddr *ia; 868 int (*lloutput)(); 869 caddr_t llnext; 870 { 871 /* this is here because you can't include both pk_var and hd_var */ 872 /* this will probably be replace by a streams gluing mechanism */ 873 ia -> ia_pkcb.pk_lloutput = lloutput; 874 ia -> ia_pkcb.pk_llnext = llnext; 875 } 876 877 pk_fragment(lcp, m0, qbit, mbit, wait) 878 struct mbuf *m0; 879 register struct pklcd *lcp; 880 { 881 register struct mbuf *m = m0; 882 register struct x25_packet *xp; 883 register struct sockbuf *sb; 884 struct mbuf *head = 0, *next, **mp = &head, *m_split(); 885 int totlen, psize = 1 << (lcp -> lcd_packetsize); 886 887 if (m == 0) 888 return; 889 if (m -> m_flags & M_PKTHDR == 0) 890 panic("pk_fragment"); 891 totlen = m -> m_pkthdr.len; 892 m -> m_act = 0; 893 sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 894 do { 895 if (totlen > psize) { 896 if ((next = m_split(m, psize, wait)) == 0) 897 goto abort; 898 totlen -= psize; 899 } else 900 next = 0; 901 M_PREPEND(m, PKHEADERLN, wait); 902 if (m == 0) 903 goto abort; 904 *mp = m; 905 mp = & m -> m_act; 906 *mp = 0; 907 xp = mtod(m, struct x25_packet *); 908 0[(char *)xp] = 0; 909 if (qbit) 910 xp -> q_bit = 1; 911 if (lcp -> lcd_flags & X25_DBIT) 912 xp -> d_bit = 1; 913 xp -> fmt_identifier = 1; 914 xp -> packet_type = X25_DATA; 915 SET_LCN(xp, lcp -> lcd_lcn); 916 if (next || (mbit && (totlen == psize || 917 (lcp -> lcd_flags & X25_DBIT)))) 918 MBIT(xp) = 1; 919 } while (m = next); 920 for (m = head; m; m = next) { 921 next = m -> m_act; 922 m -> m_act = 0; 923 sbappendrecord(sb, m); 924 } 925 return 0; 926 abort: 927 if (wait) 928 panic("pk_fragment null mbuf after wait"); 929 if (next) 930 m_freem(next); 931 for (m = head; m; m = next) { 932 next = m -> m_act; 933 m_freem(m); 934 } 935 return ENOBUFS; 936 } 937 938 struct mbuf * 939 m_split(m0, len0, wait) 940 register struct mbuf *m0; 941 int len0; 942 { 943 register struct mbuf *m, *n; 944 unsigned len = len0; 945 946 for (m = m0; m && len > m -> m_len; m = m -> m_next) 947 len -= m -> m_len; 948 if (m == 0) 949 return (0); 950 if (m0 -> m_flags & M_PKTHDR) { 951 MGETHDR(n, wait, m0 -> m_type); 952 if (n == 0) 953 return (0); 954 n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif; 955 n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0; 956 m0 -> m_pkthdr.len = len0; 957 if (m -> m_flags & M_EXT) 958 goto extpacket; 959 if (len > MHLEN) { 960 /* m can't be the lead packet */ 961 MH_ALIGN(n, 0); 962 n -> m_next = m_split(m, len, wait); 963 if (n -> m_next == 0) { 964 (void) m_free(n); 965 return (0); 966 } else 967 return (n); 968 } else 969 MH_ALIGN(n, len); 970 } else if (len == m -> m_len) { 971 n = m -> m_next; 972 m -> m_next = 0; 973 return (n); 974 } 975 extpacket: 976 len = m -> m_len - len; /* remainder to be copied */ 977 m -> m_len -= len; /* now equals original len */ 978 if (m -> m_flags & M_EXT) { 979 n -> m_flags |= M_EXT; 980 n -> m_ext = m -> m_ext; 981 mclrefcnt[mtocl(m -> m_ext.ext_buf)]++; 982 n -> m_data = m -> m_data + m -> m_len; 983 } else { 984 MGET(n, wait, m -> m_type); 985 if (n == 0) { 986 m -> m_len += len; 987 return (0); 988 } 989 M_ALIGN(n, len); 990 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len); 991 } 992 n -> m_len = len; 993 n -> m_next = m -> m_next; 994 m -> m_next = 0; 995 return (n); 996 } 997