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_input.c 7.2 (Berkeley) 05/11/90 13 */ 14 15 #include "../h/param.h" 16 #include "../h/systm.h" 17 #include "../h/mbuf.h" 18 #include "../h/socket.h" 19 #include "../h/protosw.h" 20 #include "../h/socketvar.h" 21 #include "../h/errno.h" 22 23 #include "../net/if.h" 24 25 #include "../netccitt/x25.h" 26 #include "../netccitt/pk.h" 27 #include "../netccitt/pk_var.h" 28 29 struct pkcb * 30 pk_newlink (xcp) 31 struct x25config *xcp; 32 { 33 register struct pkcb *pkp; 34 register struct mbuf *m; 35 register struct pklcd *lcp; 36 register struct protosw *pp; 37 register unsigned size; 38 39 if (xcp -> xc_ntnlen <= 0 || xcp -> xc_ntnlen > sizeof (xcp -> xc_ntn) * 2) 40 return ((struct pkcb *)0); 41 #ifdef BSD4_3 42 pp = pffindproto (AF_CCITT, (int)xcp -> xc_lproto, 0); 43 #else 44 pp = pffindproto (AF_CCITT, (int)xcp -> xc_lproto); 45 #endif 46 if (pp == 0 || pp -> pr_output == 0) { 47 pk_message (0, xcp, "link level protosw error"); 48 return ((struct pkcb *)0); 49 } 50 51 /* 52 * Allocate a network control block structure 53 */ 54 55 size = sizeof (struct pkcb) + xcp->xc_maxlcn * sizeof (struct pklcd *); 56 #ifdef sun 57 if (xcp -> xc_maxlcn < 1 || size > mclbytes) { 58 #else 59 if (xcp -> xc_maxlcn < 1 || size > CLBYTES) { 60 #endif 61 pk_message (0, xcp, "invalid maxlcn"); 62 return ((struct pkcb *)0); 63 } 64 m = m_get (M_DONTWAIT, MT_PCB); 65 if (m == 0) 66 return ((struct pkcb *)0); 67 if (size > MLEN) { 68 #ifdef sun 69 if (mclget (m) == 0) { 70 m_freem (m); 71 return ((struct pkcb *)0); 72 } 73 #else 74 #ifdef BSD4_3 75 MCLGET (m); 76 if (m -> m_len != CLBYTES) { 77 (void) m_free (m); 78 return ((struct pkcb *)0); 79 } 80 #else 81 register struct mbuf *p; 82 83 MCLGET (p, 1); 84 if (p == 0) { 85 m_freem (m); 86 return ((struct pkcb *)0); 87 } 88 m -> m_off = (int)p - (int)m; 89 #endif 90 #endif 91 } 92 pkp = mtod (m, struct pkcb *); 93 bzero ((caddr_t)pkp, size); 94 95 /* 96 * Allocate a logical channel descriptor for lcn 0 97 */ 98 99 m = m_getclr (M_DONTWAIT, MT_PCB); 100 if (m == 0) { 101 m_freem (dtom (pkp)); 102 return ((struct pkcb *)0); 103 } 104 lcp = mtod (m, struct pklcd *); 105 lcp -> lcd_state = READY; 106 lcp -> lcd_pkp = pkp; 107 pkp -> pk_chan[0] = lcp; 108 109 pkp -> pk_output = pp -> pr_output; 110 pkp -> pk_xcp = xcp; 111 pkp -> pk_state = DTE_WAITING; 112 pkp -> pk_maxlcn = xcp -> xc_maxlcn; 113 pkp -> pk_next = pkcbhead; 114 pkcbhead = pkp; 115 116 /* 117 * set defaults 118 */ 119 120 if (xcp -> xc_pwsize == 0) 121 xcp -> xc_pwsize = DEFAULT_WINDOW_SIZE; 122 if (xcp -> xc_psize == 0) 123 xcp -> xc_psize = X25_PS128; 124 return (pkp); 125 } 126 127 /* 128 * This procedure is called by the link level whenever the link 129 * becomes operational, is reset, or when the link goes down. 130 */ 131 132 pk_ctlinput (code, xcp) 133 struct x25config *xcp; 134 { 135 register struct pkcb *pkp; 136 137 for (pkp = pkcbhead; pkp; pkp = pkp -> pk_next) 138 if (pkp -> pk_xcp == xcp) 139 break; 140 141 if (pkp == 0 && (pkp = pk_newlink (xcp)) == 0) 142 return (EINVAL); 143 144 switch (code) { 145 case PRC_LINKUP: 146 if (pkp -> pk_state == DTE_WAITING) 147 pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); 148 break; 149 150 case PRC_LINKDOWN: 151 pk_restart (pkp, -1); /* Clear all active circuits */ 152 pkp -> pk_state = DTE_WAITING; 153 break; 154 155 case PRC_LINKRESET: 156 pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); 157 break; 158 159 } 160 return (0); 161 } 162 163 /* 164 * X.25 PACKET INPUT 165 * 166 * This procedure is called by a link level procedure whenever 167 * an information frame is received. It decodes the packet and 168 * demultiplexes based on the logical channel number. 169 * 170 */ 171 172 pk_input (m, xcp) 173 register struct mbuf *m; 174 struct x25config *xcp; 175 { 176 register struct x25_packet *xp; 177 register struct pklcd *lcp; 178 register struct socket *so = 0; 179 register struct pkcb *pkp; 180 int ptype, lcn, lcdstate = LISTEN; 181 static struct x25config *lastxcp; 182 static struct pkcb *lastpkp; 183 184 if (xcp == lastxcp) 185 pkp = lastpkp; 186 else { 187 for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 188 if (pkp == 0) { 189 pk_message (0, xcp, "pk_input: unknown network"); 190 m_freem (m); 191 return; 192 } 193 if (pkp -> pk_xcp == xcp) 194 break; 195 } 196 lastxcp = xcp; 197 lastpkp = pkp; 198 } 199 200 xp = mtod (m, struct x25_packet *); 201 ptype = pk_decode (xp); 202 lcn = xp -> logical_channel_number; 203 lcp = pkp -> pk_chan[lcn]; 204 205 /* 206 * If the DTE is in Restart state, then it will ignore data, 207 * interrupt, call setup and clearing, flow control and reset 208 * packets. 209 */ 210 if (lcn < 0 || lcn > pkp -> pk_maxlcn) { 211 pk_message (lcn, pkp -> pk_xcp, "illegal lcn"); 212 m_freem (m); 213 return; 214 } 215 216 pk_trace (pkp -> pk_xcp, xp, "P-In"); 217 218 if (pkp -> pk_state != DTE_READY && ptype != RESTART && ptype != RESTART_CONF) { 219 m_freem (m); 220 return; 221 } 222 if (lcp) { 223 so = lcp -> lcd_so; 224 lcdstate = lcp -> lcd_state; 225 } else { 226 if (ptype == CLEAR) { /* idle line probe (Datapac specific) */ 227 /* send response on lcd 0's output queue */ 228 lcp -> lcd_template = pk_template (lcn, X25_CLEAR_CONFIRM); 229 pk_output (lcp); 230 m_freem (m); 231 return; 232 } 233 if (ptype != CALL) 234 ptype = INVALID_PACKET; 235 } 236 237 if (lcn == 0 && ptype != RESTART && ptype != RESTART_CONF) { 238 pk_message (0, pkp -> pk_xcp, "illegal ptype (%s) on lcn 0", 239 pk_name[ptype / MAXSTATES]); 240 m_freem (m); 241 return; 242 } 243 244 switch (ptype + lcdstate) { 245 /* 246 * Incoming Call packet received. 247 */ 248 case CALL + LISTEN: 249 incoming_call (pkp, xp, m -> m_len); 250 break; 251 252 /* 253 * Call collision: Just throw this "incoming call" away since 254 * the DCE will ignore it anyway. 255 */ 256 case CALL + SENT_CALL: 257 pk_message ((int)xp -> logical_channel_number, pkp -> pk_xcp, 258 "incoming call collision"); 259 break; 260 261 /* 262 * Call confirmation packet received. This usually means our 263 * previous connect request is now complete. 264 */ 265 case CALL_ACCEPTED + SENT_CALL: 266 call_accepted (lcp, xp, m -> m_len); 267 break; 268 269 /* 270 * This condition can only happen if the previous state was 271 * SENT_CALL. Just ignore the packet, eventually a clear 272 * confirmation should arrive. 273 */ 274 case CALL_ACCEPTED + SENT_CLEAR: 275 break; 276 277 /* 278 * Clear packet received. This requires a complete tear down 279 * of the virtual circuit. Free buffers and control blocks. 280 * and send a clear confirmation. 281 */ 282 case CLEAR + READY: 283 case CLEAR + RECEIVED_CALL: 284 case CLEAR + SENT_CALL: 285 case CLEAR + DATA_TRANSFER: 286 lcp -> lcd_state = RECEIVED_CLEAR; 287 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR_CONFIRM); 288 pk_output (lcp); 289 pk_clearcause (pkp, xp); 290 pk_close (lcp); 291 break; 292 293 /* 294 * Clear collision: Treat this clear packet as a confirmation. 295 */ 296 case CLEAR + SENT_CLEAR: 297 pk_close (lcp); 298 break; 299 300 /* 301 * Clear confirmation received. This usually means the virtual 302 * circuit is now completely removed. 303 */ 304 case CLEAR_CONF + SENT_CLEAR: 305 pk_close (lcp); 306 break; 307 308 /* 309 * A clear confirmation on an unassigned logical channel - just 310 * ignore it. Note: All other packets on an unassigned channel 311 * results in a clear. 312 */ 313 case CLEAR_CONF + READY: 314 break; 315 316 /* 317 * Data packet received. Pass on to next level. Move the Q and M 318 * bits into the data portion for the next level. 319 */ 320 case DATA + DATA_TRANSFER: 321 if (lcp -> lcd_reset_condition) { 322 ptype = DELETE_PACKET; 323 break; 324 } 325 326 /* 327 * Process the P(S) flow control information in this Data packet. 328 * Check that the packets arrive in the correct sequence and that 329 * they are within the "lcd_input_window". Input window rotation is 330 * initiated by the receive interface. 331 */ 332 333 if (PS(xp) != ((lcp -> lcd_rsn + 1) % MODULUS) || 334 PS(xp) == ((lcp -> lcd_input_window + lcp->lcd_windowsize) % MODULUS)) { 335 m_freem (m); 336 pk_procerror (RESET, lcp, "p(s) flow control error"); 337 break; 338 } 339 lcp -> lcd_rsn = PS(xp); 340 341 if (pk_ack (lcp, PR(xp)) != PACKET_OK) { 342 m_freem (m); 343 break; 344 } 345 346 m -> m_off += PKHEADERLN; 347 m -> m_len -= PKHEADERLN; 348 if (lcp -> lcd_flags & X25_MQBIT) { 349 octet *t; 350 351 m -> m_off -= 1; 352 m -> m_len += 1; 353 t = mtod (m, octet *); 354 *t = 0x00; 355 if (xp -> q_bit) 356 *t |= 0x80; 357 if (MBIT(xp)) 358 *t |= 0x40; 359 } 360 361 /* 362 * Discard Q-BIT packets if the application 363 * doesn't want to be informed of M and Q bit status 364 */ 365 if (xp -> q_bit && (lcp -> lcd_flags & X25_MQBIT) == 0) { 366 m_freem (m); 367 lcp -> lcd_rxcnt++; 368 /* 369 * NB. This is dangerous: sending a RR here can 370 * cause sequence number errors if a previous data 371 * packet has not yet been passed up to the application 372 * (RR's are normally generated via PRU_RCVD). 373 */ 374 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RR); 375 pk_output (lcp); 376 } else { 377 #ifdef BSD4_3 378 sbappendrecord (&so -> so_rcv, m); 379 #else 380 sbappend (&so -> so_rcv, m); 381 #endif 382 sorwakeup (so); 383 } 384 break; 385 386 /* 387 * Interrupt packet received. 388 */ 389 case INTERRUPT + DATA_TRANSFER: 390 if (lcp -> lcd_reset_condition) 391 break; 392 lcp -> lcd_intrdata = xp -> packet_data; 393 sohasoutofband (so); 394 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM); 395 pk_output (lcp); 396 break; 397 398 /* 399 * Interrupt confirmation packet received. 400 */ 401 case INTERRUPT_CONF + DATA_TRANSFER: 402 if (lcp -> lcd_reset_condition) 403 break; 404 if (lcp -> lcd_intrconf_pending == TRUE) 405 lcp -> lcd_intrconf_pending = FALSE; 406 else 407 pk_procerror (RESET, lcp, "unexpected packet"); 408 break; 409 410 /* 411 * Receiver ready received. Rotate the output window and output 412 * any data packets waiting transmission. 413 */ 414 case RR + DATA_TRANSFER: 415 if (lcp -> lcd_reset_condition) 416 break; 417 if (pk_ack (lcp, PR(xp)) != PACKET_OK) 418 break; 419 if (lcp -> lcd_rnr_condition == TRUE) 420 lcp -> lcd_rnr_condition = FALSE; 421 pk_output (lcp); 422 break; 423 424 /* 425 * Receiver Not Ready received. Packets up to the P(R) can be 426 * be sent. Condition is cleared with a RR. 427 */ 428 case RNR + DATA_TRANSFER: 429 if (lcp -> lcd_reset_condition) 430 break; 431 if (pk_ack (lcp, PR(xp)) != PACKET_OK) 432 break; 433 lcp -> lcd_rnr_condition = TRUE; 434 break; 435 436 /* 437 * Reset packet received. Set state to FLOW_OPEN. The Input and 438 * Output window edges ar set to zero. Both the send and receive 439 * numbers are reset. A confirmation is returned. 440 */ 441 case RESET + DATA_TRANSFER: 442 if (lcp -> lcd_reset_condition) 443 /* Reset collision. Just ignore packet. */ 444 break; 445 446 pk_resetcause (pkp, xp); 447 sbflush (&so -> so_snd); 448 sbflush (&so -> so_rcv); 449 450 wakeup ((caddr_t) & so -> so_timeo); 451 sorwakeup (so); 452 sowwakeup (so); 453 454 lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 455 lcp -> lcd_intrconf_pending = FALSE; 456 lcp -> lcd_output_window = lcp -> lcd_input_window = 457 lcp -> lcd_last_transmitted_pr = 0; 458 lcp -> lcd_ssn = 0; 459 lcp -> lcd_rsn = MODULUS - 1; 460 461 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM); 462 pk_output (lcp); 463 break; 464 465 /* 466 * Reset confirmation received. 467 */ 468 case RESET_CONF + DATA_TRANSFER: 469 if (lcp -> lcd_reset_condition) { 470 lcp -> lcd_reset_condition = FALSE; 471 pk_output (lcp); 472 } 473 else 474 pk_procerror (RESET, lcp, "unexpected packet"); 475 break; 476 477 case DATA + SENT_CLEAR: 478 ptype = DELETE_PACKET; 479 case RR + SENT_CLEAR: 480 case RNR + SENT_CLEAR: 481 case INTERRUPT + SENT_CLEAR: 482 case INTERRUPT_CONF + SENT_CLEAR: 483 case RESET + SENT_CLEAR: 484 case RESET_CONF + SENT_CLEAR: 485 /* Just ignore packet if we have sent a CLEAR already. 486 */ 487 break; 488 489 /* 490 * Restart sets all the permanent virtual circuits to the "Data 491 * Transfer" stae and all the switched virtual circuits to the 492 * "Ready" state. 493 */ 494 case RESTART + READY: 495 switch (pkp -> pk_state) { 496 case DTE_SENT_RESTART: 497 /* Restart collision. */ 498 pkp -> pk_state = DTE_READY; 499 pk_message (0, pkp -> pk_xcp, 500 "Packet level operational"); 501 break; 502 503 default: 504 pk_restart (pkp, -1); 505 pk_restartcause (pkp, xp); 506 pkp -> pk_chan[0] -> lcd_template = pk_template (0, 507 X25_RESTART_CONFIRM); 508 pk_output (pkp -> pk_chan[0]); 509 } 510 break; 511 512 /* 513 * Restart confirmation received. All logical channels are set 514 * to READY. 515 */ 516 case RESTART_CONF + READY: 517 switch (pkp -> pk_state) { 518 case DTE_SENT_RESTART: 519 pkp -> pk_state = DTE_READY; 520 pk_message (0, pkp -> pk_xcp, 521 "Packet level operational"); 522 break; 523 524 default: 525 /* Restart local procedure error. */ 526 pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR); 527 pkp -> pk_state = DTE_SENT_RESTART; 528 } 529 break; 530 531 default: 532 if (lcp) { 533 pk_procerror (CLEAR, lcp, "unknown packet error"); 534 pk_message (lcn, pkp -> pk_xcp, 535 "\"%s\" unexpected in \"%s\" state", 536 pk_name[ptype/MAXSTATES], pk_state[lcdstate]); 537 } 538 else /* Packets arrived on an unassigned channel. 539 */ 540 pk_message ((int)xp->logical_channel_number, pkp -> pk_xcp, 541 "packet arrived on unassigned lcn"); 542 break; 543 } 544 if (ptype != DATA) 545 m_freem (m); 546 } 547 548 549 /* 550 * This routine handles incoming call packets. It matches the protocol 551 * field on the Call User Data field (usually the first four bytes) with 552 * sockets awaiting connections. 553 */ 554 555 static 556 incoming_call (pkp, xp, len) 557 struct pkcb *pkp; 558 struct x25_packet *xp; 559 { 560 register struct pklcd *lcp, *l; 561 register struct sockaddr_x25 *sa; 562 register struct x25_calladdr *a; 563 register struct socket *so; 564 struct mbuf *m; 565 register int l1, l2; 566 char *e, *errstr = "server unavailable"; 567 octet *u; 568 int lcn = xp -> logical_channel_number; 569 570 /* First, copy the data from the incoming call packet to a X25_socket 571 descriptor. */ 572 573 a = (struct x25_calladdr *) &xp -> packet_data; 574 l1 = a -> calling_addrlen; 575 l2 = a -> called_addrlen; 576 if ((m = m_getclr (M_DONTWAIT, MT_HEADER)) == 0) 577 return; 578 sa = mtod (m, struct sockaddr_x25 *); 579 u = (octet *) (a -> address_field + l2 / 2); 580 e = sa -> x25_addr; 581 if (l2 & 0x01) { 582 *e++ = *u++ & 0x0f; 583 l1--; 584 } 585 from_bcd (e, &u, l1); 586 if (l1 & 0x01) 587 u++; 588 589 parse_facilities (u, sa); 590 u += *u + 1; 591 sa -> x25_udlen = min (16, ((octet *)xp) + len - u); 592 if (sa -> x25_udlen < 0) 593 sa -> x25_udlen = 0; 594 bcopy ((caddr_t)u, sa -> x25_udata, (unsigned)sa -> x25_udlen); 595 596 /* 597 * Now, loop through the listen sockets looking for a match on the 598 * PID. That is the first four octets of the user data field. This 599 * is the closest thing to a port number for X.25 packets. What it 600 * does provide is away of multiplexing services at the user level. 601 */ 602 603 for (l = pk_listenhead; l; l = l -> lcd_listen) { 604 struct sockaddr_x25 *sxp = l -> lcd_ceaddr; 605 606 if (bcmp (sxp -> x25_udata, sa -> x25_udata, sxp->x25_udlen)) 607 continue; 608 if (sxp -> x25_net && sxp -> x25_net != pkp->pk_xcp->xc_net) 609 continue; 610 /* 611 * don't accept incoming collect calls unless 612 * the server sets the reverse charging option. 613 */ 614 if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 && 615 sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) { 616 errstr = "incoming collect call refused"; 617 break; 618 } 619 so = sonewconn (l -> lcd_so); 620 if (so == NULL) { 621 /* 622 * Insufficient space or too many unaccepted 623 * connections. Just throw the call away. 624 */ 625 errstr = "server malfunction"; 626 break; 627 } 628 lcp = (struct pklcd *) so -> so_pcb; 629 lcp -> lcd_lcn = lcn; 630 lcp -> lcd_state = RECEIVED_CALL; 631 lcp -> lcd_craddr = sa; 632 sa -> x25_opts.op_flags |= sxp -> x25_opts.op_flags & 633 ~X25_REVERSE_CHARGE; 634 pk_assoc (pkp, lcp, sa); 635 lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED); 636 pk_output (lcp); 637 soisconnected (so); 638 return; 639 } 640 641 /* 642 * If the call fails for whatever reason, we still need to build a 643 * skeleton LCD in order to be able to properly receive the CLEAR 644 * CONFIRMATION. 645 */ 646 #ifdef WATERLOO /* be explicit */ 647 if (l == 0 && bcmp(sa->x25_udata, "ean", 3) == 0) 648 pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s", 649 sa->x25_addr, sa->x25_udata[3] & 0xff, errstr); 650 else if (l == 0 && bcmp(sa->x25_udata, "\1\0\0\0", 4) == 0) 651 pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s", 652 sa->x25_addr, errstr); 653 else 654 #endif 655 pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s", 656 sa -> x25_addr, sa -> x25_udata[0] & 0xff, 657 sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff, 658 sa -> x25_udata[3] & 0xff, errstr); 659 if ((m = m_getclr (M_DONTWAIT, MT_HEADER)) == 0) { 660 (void) m_free (dtom (sa)); 661 return; 662 } 663 lcp = mtod (m, struct pklcd *); 664 lcp -> lcd_lcn = lcn; 665 lcp -> lcd_state = RECEIVED_CALL; 666 pk_assoc (pkp, lcp, sa); 667 (void) m_free (dtom (sa)); 668 pk_clear (lcp); 669 } 670 671 static 672 call_accepted (lcp, xp, len) 673 struct pklcd *lcp; 674 struct x25_packet *xp; 675 { 676 register struct x25_calladdr *ap; 677 register octet *fcp; 678 679 lcp -> lcd_state = DATA_TRANSFER; 680 soisconnected (lcp -> lcd_so); 681 if (len > 3) { 682 ap = (struct x25_calladdr *) &xp -> packet_data; 683 fcp = (octet *) ap -> address_field + (ap -> calling_addrlen + 684 ap -> called_addrlen + 1) / 2; 685 if (fcp + *fcp <= ((octet *)xp) + len) 686 parse_facilities (fcp, lcp -> lcd_ceaddr); 687 } 688 pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr); 689 } 690 691 static 692 parse_facilities (fcp, sa) 693 register octet *fcp; 694 register struct sockaddr_x25 *sa; 695 { 696 register octet *maxfcp; 697 698 maxfcp = fcp + *fcp; 699 fcp++; 700 while (fcp < maxfcp) { 701 /* 702 * Ignore national DCE or DTE facilities 703 */ 704 if (*fcp == 0 || *fcp == 0xff) 705 break; 706 switch (*fcp) { 707 case FACILITIES_WINDOWSIZE: 708 sa -> x25_opts.op_wsize = fcp[1]; 709 fcp += 3; 710 break; 711 712 case FACILITIES_PACKETSIZE: 713 sa -> x25_opts.op_psize = fcp[1]; 714 fcp += 3; 715 break; 716 717 case FACILITIES_THROUGHPUT: 718 sa -> x25_opts.op_speed = fcp[1]; 719 fcp += 2; 720 break; 721 722 case FACILITIES_REVERSE_CHARGE: 723 if (fcp[1] & 01) 724 sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE; 725 /* 726 * Datapac specific: for a X.25(1976) DTE, bit 2 727 * indicates a "hi priority" (eg. international) call. 728 */ 729 if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0) 730 sa -> x25_opts.op_psize = X25_PS128; 731 fcp += 2; 732 break; 733 734 default: 735 /*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/ 736 switch ((*fcp & 0xc0) >> 6) { 737 case 0: /* class A */ 738 fcp += 2; 739 break; 740 741 case 1: 742 fcp += 3; 743 break; 744 745 case 2: 746 fcp += 4; 747 break; 748 749 case 3: 750 fcp++; 751 fcp += *fcp; 752 } 753 } 754 } 755 } 756 757 from_bcd (a, x, len) 758 register char *a; 759 register octet **x; 760 register int len; 761 { 762 register int posn = 0; 763 764 while (--len >= 0) { 765 if (posn++ & 0x01) 766 *a = *(*x)++ & 0x0f; 767 else 768 *a = (**x >> 4) & 0x0F; 769 *a++ |= 0x30; 770 } 771 } 772