|
|
1.1 ! root 1: /* ! 2: * Copyright (c) University of British Columbia, 1984 ! 3: * Copyright (c) 1991 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: * Redistribution and use in source and binary forms, with or without ! 11: * modification, are permitted provided that the following conditions ! 12: * are met: ! 13: * 1. Redistributions of source code must retain the above copyright ! 14: * notice, this list of conditions and the following disclaimer. ! 15: * 2. Redistributions in binary form must reproduce the above copyright ! 16: * notice, this list of conditions and the following disclaimer in the ! 17: * documentation and/or other materials provided with the distribution. ! 18: * 3. All advertising materials mentioning features or use of this software ! 19: * must display the following acknowledgement: ! 20: * This product includes software developed by the University of ! 21: * California, Berkeley and its contributors. ! 22: * 4. Neither the name of the University nor the names of its contributors ! 23: * may be used to endorse or promote products derived from this software ! 24: * without specific prior written permission. ! 25: * ! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 36: * SUCH DAMAGE. ! 37: * ! 38: * @(#)pk_input.c 7.13 (Berkeley) 6/6/91 ! 39: */ ! 40: ! 41: #include "param.h" ! 42: #include "systm.h" ! 43: #include "mbuf.h" ! 44: #include "socket.h" ! 45: #include "protosw.h" ! 46: #include "socketvar.h" ! 47: #include "errno.h" ! 48: ! 49: #include "../net/if.h" ! 50: ! 51: #include "x25.h" ! 52: #include "pk.h" ! 53: #include "pk_var.h" ! 54: ! 55: struct pkcb * ! 56: pk_newlink (ia, llnext) ! 57: struct x25_ifaddr *ia; ! 58: caddr_t llnext; ! 59: { ! 60: register struct x25config *xcp = &ia->ia_xc; ! 61: register struct pkcb *pkp; ! 62: register struct pklcd *lcp; ! 63: register struct protosw *pp; ! 64: unsigned size; ! 65: ! 66: pp = pffindproto (AF_CCITT, (int)xcp -> xc_lproto, 0); ! 67: if (pp == 0 || pp -> pr_output == 0) { ! 68: pk_message (0, xcp, "link level protosw error"); ! 69: return ((struct pkcb *)0); ! 70: } ! 71: /* ! 72: * Allocate a network control block structure ! 73: */ ! 74: size = sizeof (struct pkcb); ! 75: pkp = (struct pkcb *)malloc(size, M_PCB, M_WAITOK); ! 76: if (pkp == 0) ! 77: return ((struct pkcb *)0); ! 78: bzero ((caddr_t)pkp, size); ! 79: pkp -> pk_lloutput = pp -> pr_output; ! 80: pkp -> pk_xcp = xcp; ! 81: pkp -> pk_ia = ia; ! 82: pkp -> pk_state = DTE_WAITING; ! 83: pkp -> pk_next = pkcbhead; ! 84: pkp -> pk_llnext = llnext; ! 85: pkcbhead = pkp; ! 86: ! 87: /* ! 88: * set defaults ! 89: */ ! 90: ! 91: if (xcp -> xc_pwsize == 0) ! 92: xcp -> xc_pwsize = DEFAULT_WINDOW_SIZE; ! 93: if (xcp -> xc_psize == 0) ! 94: xcp -> xc_psize = X25_PS128; ! 95: /* ! 96: * Allocate logical channel descriptor vector ! 97: */ ! 98: ! 99: (void)pk_resize(pkp); ! 100: return (pkp); ! 101: } ! 102: ! 103: pk_resize (pkp) ! 104: register struct pkcb *pkp; ! 105: { ! 106: struct pklcd *dev_lcp = 0; ! 107: struct x25config *xcp = pkp -> pk_xcp; ! 108: if (pkp -> pk_chan && ! 109: (pkp -> pk_maxlcn != xcp -> xc_maxlcn)) { ! 110: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); ! 111: dev_lcp = pkp -> pk_chan[0]; ! 112: free ((caddr_t)pkp -> pk_chan, M_IFADDR); ! 113: pkp -> pk_chan = 0; ! 114: } ! 115: if (pkp -> pk_chan == 0) { ! 116: unsigned size; ! 117: pkp -> pk_maxlcn = xcp -> xc_maxlcn; ! 118: size = (pkp -> pk_maxlcn + 1) * sizeof (struct pklcd *); ! 119: pkp -> pk_chan = ! 120: (struct pklcd **) malloc (size, M_IFADDR, M_WAITOK); ! 121: if (pkp -> pk_chan) { ! 122: bzero ((caddr_t)pkp -> pk_chan, size); ! 123: /* ! 124: * Allocate a logical channel descriptor for lcn 0 ! 125: */ ! 126: if (dev_lcp == 0 && ! 127: (dev_lcp = pk_attach ((struct socket *)0)) == 0) ! 128: return (ENOBUFS); ! 129: dev_lcp -> lcd_state = READY; ! 130: dev_lcp -> lcd_pkp = pkp; ! 131: pkp -> pk_chan[0] = dev_lcp; ! 132: } else { ! 133: if (dev_lcp) ! 134: pk_close (dev_lcp); ! 135: return (ENOBUFS); ! 136: } ! 137: } ! 138: return 0; ! 139: } ! 140: ! 141: /* ! 142: * This procedure is called by the link level whenever the link ! 143: * becomes operational, is reset, or when the link goes down. ! 144: */ ! 145: ! 146: pk_ctlinput (code, pkp) ! 147: register struct pkcb *pkp; ! 148: { ! 149: ! 150: ! 151: switch (code) { ! 152: case PRC_LINKUP: ! 153: if (pkp -> pk_state == DTE_WAITING) ! 154: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); ! 155: break; ! 156: ! 157: case PRC_LINKDOWN: ! 158: pk_restart (pkp, -1); /* Clear all active circuits */ ! 159: pkp -> pk_state = DTE_WAITING; ! 160: break; ! 161: ! 162: case PRC_LINKRESET: ! 163: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); ! 164: break; ! 165: ! 166: } ! 167: return (0); ! 168: } ! 169: struct ifqueue pkintrq; ! 170: /* ! 171: * This routine is called if there are semi-smart devices that do HDLC ! 172: * in hardware and want to queue the packet and call level 3 directly ! 173: */ ! 174: pkintr () ! 175: { ! 176: register struct mbuf *m; ! 177: register struct ifaddr *ifa; ! 178: register struct ifnet *ifp; ! 179: register int s; ! 180: ! 181: for (;;) { ! 182: s = splimp (); ! 183: IF_DEQUEUE (&pkintrq, m); ! 184: splx (s); ! 185: if (m == 0) ! 186: break; ! 187: if (m->m_len < PKHEADERLN) { ! 188: printf ("pkintr: packet too short (len=%d)\n", ! 189: m->m_len); ! 190: m_freem (m); ! 191: continue; ! 192: } ! 193: pk_input(m); ! 194: } ! 195: } ! 196: struct mbuf *pk_bad_packet; ! 197: struct mbuf_cache pk_input_cache = {0 }; ! 198: /* ! 199: * X.25 PACKET INPUT ! 200: * ! 201: * This procedure is called by a link level procedure whenever ! 202: * an information frame is received. It decodes the packet and ! 203: * demultiplexes based on the logical channel number. ! 204: * ! 205: * We change the original conventions of the UBC code here -- ! 206: * since there may be multiple pkcb's for 802.2 class 2 ! 207: * for a given interface, we must be informed which one it is; ! 208: * so we overwrite the pkthdr.rcvif; it can be recovered if necessary. ! 209: * ! 210: */ ! 211: ! 212: pk_input (m) ! 213: register struct mbuf *m; ! 214: { ! 215: register struct x25_packet *xp; ! 216: register struct pklcd *lcp; ! 217: register struct socket *so = 0; ! 218: register struct pkcb *pkp; ! 219: int ptype, lcn, lcdstate = LISTEN; ! 220: ! 221: if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) ! 222: mbuf_cache(&pk_input_cache, m); ! 223: if ((m->m_flags & M_PKTHDR) == 0) ! 224: panic("pkintr"); ! 225: if ((pkp = (struct pkcb *)m->m_pkthdr.rcvif) == 0) ! 226: return; ! 227: xp = mtod (m, struct x25_packet *); ! 228: ptype = pk_decode (xp); ! 229: lcn = LCN(xp); ! 230: lcp = pkp -> pk_chan[lcn]; ! 231: ! 232: /* ! 233: * If the DTE is in Restart state, then it will ignore data, ! 234: * interrupt, call setup and clearing, flow control and reset ! 235: * packets. ! 236: */ ! 237: if (lcn < 0 || lcn > pkp -> pk_maxlcn) { ! 238: pk_message (lcn, pkp -> pk_xcp, "illegal lcn"); ! 239: m_freem (m); ! 240: return; ! 241: } ! 242: ! 243: pk_trace (pkp -> pk_xcp, m, "P-In"); ! 244: ! 245: if (pkp -> pk_state != DTE_READY && ptype != RESTART && ptype != RESTART_CONF) { ! 246: m_freem (m); ! 247: return; ! 248: } ! 249: if (lcp) { ! 250: so = lcp -> lcd_so; ! 251: lcdstate = lcp -> lcd_state; ! 252: } else { ! 253: if (ptype == CLEAR) { /* idle line probe (Datapac specific) */ ! 254: /* send response on lcd 0's output queue */ ! 255: lcp = pkp -> pk_chan[0]; ! 256: lcp -> lcd_template = pk_template (lcn, X25_CLEAR_CONFIRM); ! 257: pk_output (lcp); ! 258: m_freem (m); ! 259: return; ! 260: } ! 261: if (ptype != CALL) ! 262: ptype = INVALID_PACKET; ! 263: } ! 264: ! 265: if (lcn == 0 && ptype != RESTART && ptype != RESTART_CONF) { ! 266: pk_message (0, pkp -> pk_xcp, "illegal ptype (%d, %s) on lcn 0", ! 267: ptype, pk_name[ptype / MAXSTATES]); ! 268: if (pk_bad_packet) ! 269: m_freem (pk_bad_packet); ! 270: pk_bad_packet = m; ! 271: return; ! 272: } ! 273: ! 274: switch (ptype + lcdstate) { ! 275: /* ! 276: * Incoming Call packet received. ! 277: */ ! 278: case CALL + LISTEN: ! 279: pk_incoming_call (pkp, m); ! 280: break; ! 281: ! 282: /* ! 283: * Call collision: Just throw this "incoming call" away since ! 284: * the DCE will ignore it anyway. ! 285: */ ! 286: case CALL + SENT_CALL: ! 287: pk_message ((int)lcn, pkp -> pk_xcp, ! 288: "incoming call collision"); ! 289: break; ! 290: ! 291: /* ! 292: * Call confirmation packet received. This usually means our ! 293: * previous connect request is now complete. ! 294: */ ! 295: case CALL_ACCEPTED + SENT_CALL: ! 296: MCHTYPE(m, MT_CONTROL); ! 297: pk_call_accepted (lcp, m); ! 298: break; ! 299: ! 300: /* ! 301: * This condition can only happen if the previous state was ! 302: * SENT_CALL. Just ignore the packet, eventually a clear ! 303: * confirmation should arrive. ! 304: */ ! 305: case CALL_ACCEPTED + SENT_CLEAR: ! 306: break; ! 307: ! 308: /* ! 309: * Clear packet received. This requires a complete tear down ! 310: * of the virtual circuit. Free buffers and control blocks. ! 311: * and send a clear confirmation. ! 312: */ ! 313: case CLEAR + READY: ! 314: case CLEAR + RECEIVED_CALL: ! 315: case CLEAR + SENT_CALL: ! 316: case CLEAR + DATA_TRANSFER: ! 317: lcp -> lcd_state = RECEIVED_CLEAR; ! 318: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR_CONFIRM); ! 319: pk_output (lcp); ! 320: pk_clearcause (pkp, xp); ! 321: if (lcp -> lcd_upper) { ! 322: MCHTYPE(m, MT_CONTROL); ! 323: lcp -> lcd_upper (lcp, m); ! 324: } ! 325: pk_close (lcp); ! 326: lcp = 0; ! 327: break; ! 328: ! 329: /* ! 330: * Clear collision: Treat this clear packet as a confirmation. ! 331: */ ! 332: case CLEAR + SENT_CLEAR: ! 333: pk_close (lcp); ! 334: break; ! 335: ! 336: /* ! 337: * Clear confirmation received. This usually means the virtual ! 338: * circuit is now completely removed. ! 339: */ ! 340: case CLEAR_CONF + SENT_CLEAR: ! 341: pk_close (lcp); ! 342: break; ! 343: ! 344: /* ! 345: * A clear confirmation on an unassigned logical channel - just ! 346: * ignore it. Note: All other packets on an unassigned channel ! 347: * results in a clear. ! 348: */ ! 349: case CLEAR_CONF + READY: ! 350: case CLEAR_CONF + LISTEN: ! 351: break; ! 352: ! 353: /* ! 354: * Data packet received. Pass on to next level. Move the Q and M ! 355: * bits into the data portion for the next level. ! 356: */ ! 357: case DATA + DATA_TRANSFER: ! 358: if (lcp -> lcd_reset_condition) { ! 359: ptype = DELETE_PACKET; ! 360: break; ! 361: } ! 362: ! 363: /* ! 364: * Process the P(S) flow control information in this Data packet. ! 365: * Check that the packets arrive in the correct sequence and that ! 366: * they are within the "lcd_input_window". Input window rotation is ! 367: * initiated by the receive interface. ! 368: */ ! 369: ! 370: if (PS(xp) != ((lcp -> lcd_rsn + 1) % MODULUS) || ! 371: PS(xp) == ((lcp -> lcd_input_window + lcp->lcd_windowsize) % MODULUS)) { ! 372: m_freem (m); ! 373: pk_procerror (RESET, lcp, "p(s) flow control error", 1); ! 374: break; ! 375: } ! 376: lcp -> lcd_rsn = PS(xp); ! 377: ! 378: if (pk_ack (lcp, PR(xp)) != PACKET_OK) { ! 379: m_freem (m); ! 380: break; ! 381: } ! 382: m -> m_data += PKHEADERLN; ! 383: m -> m_len -= PKHEADERLN; ! 384: m -> m_pkthdr.len -= PKHEADERLN; ! 385: ! 386: lcp -> lcd_rxcnt++; ! 387: if (lcp -> lcd_flags & X25_MBS_HOLD) { ! 388: register struct mbuf *n = lcp -> lcd_cps; ! 389: int mbit = MBIT(xp); ! 390: octet q_and_d_bits; ! 391: ! 392: if (n) { ! 393: n -> m_pkthdr.len += m -> m_pkthdr.len; ! 394: while (n -> m_next) ! 395: n = n -> m_next; ! 396: n -> m_next = m; ! 397: m = lcp -> lcd_cps; ! 398: ! 399: if (lcp -> lcd_cpsmax && ! 400: n -> m_pkthdr.len > lcp -> lcd_cpsmax) { ! 401: pk_procerror (RESET, lcp, ! 402: "C.P.S. overflow", 128); ! 403: return; ! 404: } ! 405: q_and_d_bits = 0xc0 & *(octet *)xp; ! 406: xp = (struct x25_packet *) ! 407: (mtod(m, octet *) - PKHEADERLN); ! 408: *(octet *)xp |= q_and_d_bits; ! 409: } ! 410: if (mbit) { ! 411: lcp -> lcd_cps = m; ! 412: pk_flowcontrol(lcp, 0, 1); ! 413: return; ! 414: } ! 415: lcp -> lcd_cps = 0; ! 416: } ! 417: if (so == 0) ! 418: break; ! 419: if (lcp -> lcd_flags & X25_MQBIT) { ! 420: octet t = (xp -> q_bit) ? t = 0x80 : 0; ! 421: ! 422: if (MBIT(xp)) ! 423: t |= 0x40; ! 424: m -> m_data -= 1; ! 425: m -> m_len += 1; ! 426: m -> m_pkthdr.len += 1; ! 427: *mtod(m, octet *) = t; ! 428: } ! 429: ! 430: /* ! 431: * Discard Q-BIT packets if the application ! 432: * doesn't want to be informed of M and Q bit status ! 433: */ ! 434: if (xp -> q_bit && (lcp -> lcd_flags & X25_MQBIT) == 0) { ! 435: m_freem (m); ! 436: /* ! 437: * NB. This is dangerous: sending a RR here can ! 438: * cause sequence number errors if a previous data ! 439: * packet has not yet been passed up to the application ! 440: * (RR's are normally generated via PRU_RCVD). ! 441: */ ! 442: pk_flowcontrol(lcp, 0, 1); ! 443: } else { ! 444: sbappendrecord (&so -> so_rcv, m); ! 445: sorwakeup (so); ! 446: } ! 447: break; ! 448: ! 449: /* ! 450: * Interrupt packet received. ! 451: */ ! 452: case INTERRUPT + DATA_TRANSFER: ! 453: if (lcp -> lcd_reset_condition) ! 454: break; ! 455: lcp -> lcd_intrdata = xp -> packet_data; ! 456: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM); ! 457: pk_output (lcp); ! 458: m -> m_data += PKHEADERLN; ! 459: m -> m_len -= PKHEADERLN; ! 460: m -> m_pkthdr.len -= PKHEADERLN; ! 461: MCHTYPE(m, MT_OOBDATA); ! 462: if (so) { ! 463: if (so -> so_options & SO_OOBINLINE) ! 464: sbinsertoob (&so -> so_rcv, m); ! 465: else ! 466: m_freem (m); ! 467: sohasoutofband (so); ! 468: } ! 469: break; ! 470: ! 471: /* ! 472: * Interrupt confirmation packet received. ! 473: */ ! 474: case INTERRUPT_CONF + DATA_TRANSFER: ! 475: if (lcp -> lcd_reset_condition) ! 476: break; ! 477: if (lcp -> lcd_intrconf_pending == TRUE) ! 478: lcp -> lcd_intrconf_pending = FALSE; ! 479: else ! 480: pk_procerror (RESET, lcp, "unexpected packet", 43); ! 481: break; ! 482: ! 483: /* ! 484: * Receiver ready received. Rotate the output window and output ! 485: * any data packets waiting transmission. ! 486: */ ! 487: case RR + DATA_TRANSFER: ! 488: if (lcp -> lcd_reset_condition || ! 489: pk_ack (lcp, PR(xp)) != PACKET_OK) { ! 490: ptype = DELETE_PACKET; ! 491: break; ! 492: } ! 493: if (lcp -> lcd_rnr_condition == TRUE) ! 494: lcp -> lcd_rnr_condition = FALSE; ! 495: pk_output (lcp); ! 496: break; ! 497: ! 498: /* ! 499: * Receiver Not Ready received. Packets up to the P(R) can be ! 500: * be sent. Condition is cleared with a RR. ! 501: */ ! 502: case RNR + DATA_TRANSFER: ! 503: if (lcp -> lcd_reset_condition || ! 504: pk_ack (lcp, PR(xp)) != PACKET_OK) { ! 505: ptype = DELETE_PACKET; ! 506: break; ! 507: } ! 508: lcp -> lcd_rnr_condition = TRUE; ! 509: break; ! 510: ! 511: /* ! 512: * Reset packet received. Set state to FLOW_OPEN. The Input and ! 513: * Output window edges ar set to zero. Both the send and receive ! 514: * numbers are reset. A confirmation is returned. ! 515: */ ! 516: case RESET + DATA_TRANSFER: ! 517: if (lcp -> lcd_reset_condition) ! 518: /* Reset collision. Just ignore packet. */ ! 519: break; ! 520: ! 521: pk_resetcause (pkp, xp); ! 522: lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = ! 523: lcp -> lcd_intrconf_pending = FALSE; ! 524: lcp -> lcd_output_window = lcp -> lcd_input_window = ! 525: lcp -> lcd_last_transmitted_pr = 0; ! 526: lcp -> lcd_ssn = 0; ! 527: lcp -> lcd_rsn = MODULUS - 1; ! 528: ! 529: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM); ! 530: pk_output (lcp); ! 531: ! 532: pk_flush(lcp); ! 533: if (so == 0) ! 534: break; ! 535: wakeup ((caddr_t) & so -> so_timeo); ! 536: sorwakeup (so); ! 537: sowwakeup (so); ! 538: break; ! 539: ! 540: /* ! 541: * Reset confirmation received. ! 542: */ ! 543: case RESET_CONF + DATA_TRANSFER: ! 544: if (lcp -> lcd_reset_condition) { ! 545: lcp -> lcd_reset_condition = FALSE; ! 546: pk_output (lcp); ! 547: } ! 548: else ! 549: pk_procerror (RESET, lcp, "unexpected packet", 32); ! 550: break; ! 551: ! 552: case DATA + SENT_CLEAR: ! 553: ptype = DELETE_PACKET; ! 554: case RR + SENT_CLEAR: ! 555: case RNR + SENT_CLEAR: ! 556: case INTERRUPT + SENT_CLEAR: ! 557: case INTERRUPT_CONF + SENT_CLEAR: ! 558: case RESET + SENT_CLEAR: ! 559: case RESET_CONF + SENT_CLEAR: ! 560: /* Just ignore p if we have sent a CLEAR already. ! 561: */ ! 562: break; ! 563: ! 564: /* ! 565: * Restart sets all the permanent virtual circuits to the "Data ! 566: * Transfer" stae and all the switched virtual circuits to the ! 567: * "Ready" state. ! 568: */ ! 569: case RESTART + READY: ! 570: switch (pkp -> pk_state) { ! 571: case DTE_SENT_RESTART: ! 572: /* Restart collision. */ ! 573: pkp -> pk_state = DTE_READY; ! 574: pk_message (0, pkp -> pk_xcp, ! 575: "Packet level operational"); ! 576: break; ! 577: ! 578: default: ! 579: pk_restart (pkp, -1); ! 580: pk_restartcause (pkp, xp); ! 581: pkp -> pk_chan[0] -> lcd_template = pk_template (0, ! 582: X25_RESTART_CONFIRM); ! 583: pk_output (pkp -> pk_chan[0]); ! 584: } ! 585: break; ! 586: ! 587: /* ! 588: * Restart confirmation received. All logical channels are set ! 589: * to READY. ! 590: */ ! 591: case RESTART_CONF + READY: ! 592: switch (pkp -> pk_state) { ! 593: case DTE_SENT_RESTART: ! 594: pkp -> pk_state = DTE_READY; ! 595: pk_message (0, pkp -> pk_xcp, ! 596: "Packet level operational"); ! 597: break; ! 598: ! 599: default: ! 600: /* Restart local procedure error. */ ! 601: pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR); ! 602: pkp -> pk_state = DTE_SENT_RESTART; ! 603: } ! 604: break; ! 605: ! 606: default: ! 607: if (lcp) { ! 608: pk_procerror (CLEAR, lcp, "unknown packet error", 33); ! 609: pk_message (lcn, pkp -> pk_xcp, ! 610: "\"%s\" unexpected in \"%s\" state", ! 611: pk_name[ptype/MAXSTATES], pk_state[lcdstate]); ! 612: } else ! 613: pk_message (lcn, pkp -> pk_xcp, ! 614: "packet arrived on unassigned lcn"); ! 615: break; ! 616: } ! 617: if (so == 0 && lcp && lcp -> lcd_upper && lcdstate == DATA_TRANSFER) { ! 618: if (ptype != DATA && ptype != INTERRUPT) ! 619: MCHTYPE(m, MT_CONTROL); ! 620: lcp -> lcd_upper (lcp, m); ! 621: } else if (ptype != DATA && ptype != INTERRUPT) ! 622: m_freem (m); ! 623: } ! 624: ! 625: static ! 626: prune_dnic(from, to, dnicname, xcp) ! 627: char *from, *to, *dnicname; ! 628: register struct x25config *xcp; ! 629: { ! 630: register char *cp1 = from, *cp2 = from; ! 631: if (xcp->xc_prepnd0 && *cp1 == '0') { ! 632: from = ++cp1; ! 633: goto copyrest; ! 634: } ! 635: if (xcp->xc_nodnic) { ! 636: for (cp1 = dnicname; *cp2 = *cp1++;) ! 637: cp2++; ! 638: cp1 = from; ! 639: } ! 640: copyrest: ! 641: for (cp1 = dnicname; *cp2 = *cp1++;) ! 642: cp2++; ! 643: } ! 644: /* static */ ! 645: pk_simple_bsd (from, to, lower, len) ! 646: register octet *from, *to; ! 647: register len, lower; ! 648: { ! 649: register int c; ! 650: while (--len >= 0) { ! 651: c = *from; ! 652: if (lower & 0x01) ! 653: *from++; ! 654: else ! 655: c >>= 4; ! 656: c &= 0x0f; c |= 0x30; *to++ = c; lower++; ! 657: } ! 658: *to = 0; ! 659: } ! 660: ! 661: /*static octet * */ ! 662: pk_from_bcd (a, iscalling, sa, xcp) ! 663: register struct x25_calladdr *a; ! 664: register struct sockaddr_x25 *sa; ! 665: register struct x25config *xcp; ! 666: { ! 667: octet buf[MAXADDRLN+1]; ! 668: octet *cp; ! 669: unsigned count; ! 670: ! 671: bzero ((caddr_t)sa, sizeof (*sa)); ! 672: sa -> x25_len = sizeof (*sa); ! 673: sa -> x25_family = AF_CCITT; ! 674: if (iscalling) { ! 675: cp = a -> address_field + (a -> called_addrlen / 2); ! 676: count = a -> calling_addrlen; ! 677: pk_simple_bsd (cp, buf, a -> called_addrlen, count); ! 678: } else { ! 679: count = a -> called_addrlen; ! 680: pk_simple_bsd (a -> address_field, buf, 0, count); ! 681: } ! 682: if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp ->xc_prepnd0)) { ! 683: octet dnicname[sizeof(long) * NBBY/3 + 2]; ! 684: ! 685: sprintf (dnicname, "%d", xcp -> xc_addr.x25_net); ! 686: prune_dnic (buf, sa -> x25_addr, dnicname, xcp); ! 687: } else ! 688: bcopy ((caddr_t)buf, (caddr_t)sa -> x25_addr, count + 1); ! 689: } ! 690: ! 691: static ! 692: save_extra(m0, fp, so) ! 693: struct mbuf *m0; ! 694: octet *fp; ! 695: struct socket *so; ! 696: { ! 697: register struct mbuf *m; ! 698: struct cmsghdr cmsghdr; ! 699: if (m = m_copym (m, 0, (int)M_COPYALL)) { ! 700: int off = fp - mtod (m0, octet *); ! 701: int len = m->m_pkthdr.len - off + sizeof (cmsghdr); ! 702: cmsghdr.cmsg_len = len; ! 703: cmsghdr.cmsg_level = AF_CCITT; ! 704: cmsghdr.cmsg_type = PK_FACILITIES; ! 705: m_adj (m, off); ! 706: M_PREPEND (m, sizeof(cmsghdr), M_DONTWAIT); ! 707: if (m == 0) ! 708: return; ! 709: bcopy ((caddr_t)&cmsghdr, mtod (m, caddr_t), sizeof (cmsghdr)); ! 710: MCHTYPE(m, MT_CONTROL); ! 711: sbappendrecord(&so -> so_rcv, m); ! 712: } ! 713: } ! 714: ! 715: /* ! 716: * This routine handles incoming call packets. It matches the protocol ! 717: * field on the Call User Data field (usually the first four bytes) with ! 718: * sockets awaiting connections. ! 719: */ ! 720: ! 721: pk_incoming_call (pkp, m0) ! 722: struct mbuf *m0; ! 723: struct pkcb *pkp; ! 724: { ! 725: register struct pklcd *lcp = 0, *l; ! 726: register struct sockaddr_x25 *sa; ! 727: register struct x25_calladdr *a; ! 728: register struct socket *so = 0; ! 729: struct x25_packet *xp = mtod(m0, struct x25_packet *); ! 730: struct mbuf *m; ! 731: struct x25config *xcp = pkp -> pk_xcp; ! 732: int len = m0->m_pkthdr.len; ! 733: unsigned udlen; ! 734: char *errstr = "server unavailable"; ! 735: octet *u, *facp; ! 736: int lcn = LCN(xp); ! 737: ! 738: /* First, copy the data from the incoming call packet to a X25 address ! 739: descriptor. It is to be regretted that you have ! 740: to parse the facilities into a sockaddr to determine ! 741: if reverse charging is being requested */ ! 742: if ((m = m_get (M_DONTWAIT, MT_SONAME)) == 0) ! 743: return; ! 744: sa = mtod (m, struct sockaddr_x25 *); ! 745: a = (struct x25_calladdr *) &xp -> packet_data; ! 746: facp = u = (octet *) (a -> address_field + ! 747: ((a -> called_addrlen + a -> calling_addrlen + 1) / 2)); ! 748: u += *u + 1; ! 749: udlen = min (16, ((octet *)xp) + len - u); ! 750: if (udlen < 0) ! 751: udlen = 0; ! 752: pk_from_bcd (a, 1, sa, pkp -> pk_xcp); /* get calling address */ ! 753: pk_parse_facilities (u, sa); ! 754: bcopy ((caddr_t)u, sa -> x25_udata, udlen); ! 755: sa -> x25_udlen = udlen; ! 756: ! 757: /* ! 758: * Now, loop through the listen sockets looking for a match on the ! 759: * PID. That is the first four octets of the user data field. This ! 760: * is the closest thing to a port number for X.25 packets. What it ! 761: * does provide is away of multiplexing services at the user level. ! 762: */ ! 763: ! 764: for (l = pk_listenhead; l; l = l -> lcd_listen) { ! 765: struct sockaddr_x25 *sxp = l -> lcd_ceaddr; ! 766: ! 767: if (bcmp (sxp -> x25_udata, u, sxp->x25_udlen)) ! 768: continue; ! 769: if (sxp -> x25_net && ! 770: sxp -> x25_net != xcp -> xc_addr.x25_net) ! 771: continue; ! 772: /* ! 773: * don't accept incoming calls with the D-Bit on ! 774: * unless the server agrees ! 775: */ ! 776: if (xp -> d_bit && !(sxp -> x25_opts.op_flags & X25_DBIT)) { ! 777: errstr = "incoming D-Bit mismatch"; ! 778: break; ! 779: } ! 780: /* ! 781: * don't accept incoming collect calls unless ! 782: * the server sets the reverse charging option. ! 783: */ ! 784: if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 && ! 785: sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) { ! 786: errstr = "incoming collect call refused"; ! 787: break; ! 788: } ! 789: if (l -> lcd_so) { ! 790: if (so = sonewconn (l -> lcd_so, SS_ISCONNECTED)) ! 791: lcp = (struct pklcd *) so -> so_pcb; ! 792: } else ! 793: lcp = pk_attach((struct socket *) 0); ! 794: if (lcp == 0) { ! 795: /* ! 796: * Insufficient space or too many unaccepted ! 797: * connections. Just throw the call away. ! 798: */ ! 799: errstr = "server malfunction"; ! 800: break; ! 801: } ! 802: lcp -> lcd_upper = l -> lcd_upper; ! 803: lcp -> lcd_upnext = l -> lcd_upnext; ! 804: lcp -> lcd_lcn = lcn; ! 805: lcp -> lcd_state = RECEIVED_CALL; ! 806: sa -> x25_opts.op_flags |= (sxp -> x25_opts.op_flags & ! 807: ~X25_REVERSE_CHARGE) | l -> lcd_flags; ! 808: pk_assoc (pkp, lcp, sa); ! 809: lcp -> lcd_faddr = *sa; ! 810: lcp -> lcd_laddr.x25_udlen = sxp -> x25_udlen; ! 811: lcp -> lcd_craddr = &lcp->lcd_faddr; ! 812: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED); ! 813: if (lcp -> lcd_flags & X25_DBIT) { ! 814: if (xp -> d_bit) ! 815: mtod(lcp -> lcd_template, ! 816: struct x25_packet *) -> d_bit = 1; ! 817: else ! 818: lcp -> lcd_flags &= ~X25_DBIT; ! 819: } ! 820: if (so) { ! 821: pk_output (lcp); ! 822: soisconnected (so); ! 823: if (so -> so_options & SO_OOBINLINE) ! 824: save_extra(m0, facp, so); ! 825: } else if (lcp -> lcd_upper) { ! 826: (*lcp -> lcd_upper) (lcp, m0); ! 827: } ! 828: (void) m_free (m); ! 829: return; ! 830: } ! 831: ! 832: /* ! 833: * If the call fails for whatever reason, we still need to build a ! 834: * skeleton LCD in order to be able to properly receive the CLEAR ! 835: * CONFIRMATION. ! 836: */ ! 837: #ifdef WATERLOO /* be explicit */ ! 838: if (l == 0 && bcmp(sa->x25_udata, "ean", 3) == 0) ! 839: pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s", ! 840: sa->x25_addr, sa->x25_udata[3] & 0xff, errstr); ! 841: else if (l == 0 && bcmp(sa->x25_udata, "\1\0\0\0", 4) == 0) ! 842: pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s", ! 843: sa->x25_addr, errstr); ! 844: else ! 845: #endif ! 846: pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s", ! 847: sa -> x25_addr, sa -> x25_udata[0] & 0xff, ! 848: sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff, ! 849: sa -> x25_udata[3] & 0xff, errstr); ! 850: if ((lcp = pk_attach((struct socket *)0)) == 0) { ! 851: (void) m_free (m); ! 852: return; ! 853: } ! 854: lcp -> lcd_lcn = lcn; ! 855: lcp -> lcd_state = RECEIVED_CALL; ! 856: pk_assoc (pkp, lcp, sa); ! 857: (void) m_free (m); ! 858: pk_clear (lcp, 0, 1); ! 859: } ! 860: ! 861: pk_call_accepted (lcp, m) ! 862: struct pklcd *lcp; ! 863: struct mbuf *m; ! 864: { ! 865: register struct x25_calladdr *ap; ! 866: register octet *fcp; ! 867: struct x25_packet *xp = mtod (m, struct x25_packet *); ! 868: int len = m -> m_len; ! 869: ! 870: lcp -> lcd_state = DATA_TRANSFER; ! 871: if (lcp -> lcd_so) ! 872: soisconnected (lcp -> lcd_so); ! 873: if ((lcp -> lcd_flags & X25_DBIT) && (xp -> d_bit == 0)) ! 874: lcp -> lcd_flags &= ~X25_DBIT; ! 875: if (len > 3) { ! 876: ap = (struct x25_calladdr *) &xp -> packet_data; ! 877: fcp = (octet *) ap -> address_field + (ap -> calling_addrlen + ! 878: ap -> called_addrlen + 1) / 2; ! 879: if (fcp + *fcp <= ((octet *)xp) + len) ! 880: pk_parse_facilities (fcp, lcp -> lcd_ceaddr); ! 881: } ! 882: pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr); ! 883: if (lcp -> lcd_so == 0 && lcp -> lcd_upper) ! 884: lcp -> lcd_upper(lcp, m); ! 885: } ! 886: ! 887: pk_parse_facilities (fcp, sa) ! 888: register octet *fcp; ! 889: register struct sockaddr_x25 *sa; ! 890: { ! 891: register octet *maxfcp; ! 892: ! 893: maxfcp = fcp + *fcp; ! 894: fcp++; ! 895: while (fcp < maxfcp) { ! 896: /* ! 897: * Ignore national DCE or DTE facilities ! 898: */ ! 899: if (*fcp == 0 || *fcp == 0xff) ! 900: break; ! 901: switch (*fcp) { ! 902: case FACILITIES_WINDOWSIZE: ! 903: sa -> x25_opts.op_wsize = fcp[1]; ! 904: fcp += 3; ! 905: break; ! 906: ! 907: case FACILITIES_PACKETSIZE: ! 908: sa -> x25_opts.op_psize = fcp[1]; ! 909: fcp += 3; ! 910: break; ! 911: ! 912: case FACILITIES_THROUGHPUT: ! 913: sa -> x25_opts.op_speed = fcp[1]; ! 914: fcp += 2; ! 915: break; ! 916: ! 917: case FACILITIES_REVERSE_CHARGE: ! 918: if (fcp[1] & 01) ! 919: sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE; ! 920: /* ! 921: * Datapac specific: for a X.25(1976) DTE, bit 2 ! 922: * indicates a "hi priority" (eg. international) call. ! 923: */ ! 924: if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0) ! 925: sa -> x25_opts.op_psize = X25_PS128; ! 926: fcp += 2; ! 927: break; ! 928: ! 929: default: ! 930: /*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/ ! 931: switch ((*fcp & 0xc0) >> 6) { ! 932: case 0: /* class A */ ! 933: fcp += 2; ! 934: break; ! 935: ! 936: case 1: ! 937: fcp += 3; ! 938: break; ! 939: ! 940: case 2: ! 941: fcp += 4; ! 942: break; ! 943: ! 944: case 3: ! 945: fcp++; ! 946: fcp += *fcp; ! 947: } ! 948: } ! 949: } ! 950: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.