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