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