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