1*41709Ssklower /* 2*41709Ssklower * Copyright (c) University of British Columbia, 1984 3*41709Ssklower * Copyright (c) 1990 The Regents of the University of California. 4*41709Ssklower * All rights reserved. 5*41709Ssklower * 6*41709Ssklower * This code is derived from software contributed to Berkeley by 7*41709Ssklower * the Laboratory for Computation Vision and the Computer Science Department 8*41709Ssklower * of the University of British Columbia. 9*41709Ssklower * 10*41709Ssklower * %sccs.include.redist.c% 11*41709Ssklower * 12*41709Ssklower * @(#)pk_input.c 7.2 (Berkeley) 05/11/90 13*41709Ssklower */ 1441591Ssklower 1541591Ssklower #include "../h/param.h" 1641591Ssklower #include "../h/systm.h" 1741591Ssklower #include "../h/mbuf.h" 1841591Ssklower #include "../h/socket.h" 1941591Ssklower #include "../h/protosw.h" 2041591Ssklower #include "../h/socketvar.h" 2141591Ssklower #include "../h/errno.h" 2241591Ssklower 2341591Ssklower #include "../net/if.h" 2441591Ssklower 2541591Ssklower #include "../netccitt/x25.h" 2641591Ssklower #include "../netccitt/pk.h" 2741591Ssklower #include "../netccitt/pk_var.h" 2841591Ssklower 2941591Ssklower struct pkcb * 3041591Ssklower pk_newlink (xcp) 3141591Ssklower struct x25config *xcp; 3241591Ssklower { 3341591Ssklower register struct pkcb *pkp; 3441591Ssklower register struct mbuf *m; 3541591Ssklower register struct pklcd *lcp; 3641591Ssklower register struct protosw *pp; 3741591Ssklower register unsigned size; 3841591Ssklower 3941591Ssklower if (xcp -> xc_ntnlen <= 0 || xcp -> xc_ntnlen > sizeof (xcp -> xc_ntn) * 2) 4041591Ssklower return ((struct pkcb *)0); 4141591Ssklower #ifdef BSD4_3 4241591Ssklower pp = pffindproto (AF_CCITT, (int)xcp -> xc_lproto, 0); 4341591Ssklower #else 4441591Ssklower pp = pffindproto (AF_CCITT, (int)xcp -> xc_lproto); 4541591Ssklower #endif 4641591Ssklower if (pp == 0 || pp -> pr_output == 0) { 4741591Ssklower pk_message (0, xcp, "link level protosw error"); 4841591Ssklower return ((struct pkcb *)0); 4941591Ssklower } 5041591Ssklower 5141591Ssklower /* 5241591Ssklower * Allocate a network control block structure 5341591Ssklower */ 5441591Ssklower 5541591Ssklower size = sizeof (struct pkcb) + xcp->xc_maxlcn * sizeof (struct pklcd *); 5641591Ssklower #ifdef sun 5741591Ssklower if (xcp -> xc_maxlcn < 1 || size > mclbytes) { 5841591Ssklower #else 5941591Ssklower if (xcp -> xc_maxlcn < 1 || size > CLBYTES) { 6041591Ssklower #endif 6141591Ssklower pk_message (0, xcp, "invalid maxlcn"); 6241591Ssklower return ((struct pkcb *)0); 6341591Ssklower } 6441591Ssklower m = m_get (M_DONTWAIT, MT_PCB); 6541591Ssklower if (m == 0) 6641591Ssklower return ((struct pkcb *)0); 6741591Ssklower if (size > MLEN) { 6841591Ssklower #ifdef sun 6941591Ssklower if (mclget (m) == 0) { 7041591Ssklower m_freem (m); 7141591Ssklower return ((struct pkcb *)0); 7241591Ssklower } 7341591Ssklower #else 7441591Ssklower #ifdef BSD4_3 7541591Ssklower MCLGET (m); 7641591Ssklower if (m -> m_len != CLBYTES) { 7741591Ssklower (void) m_free (m); 7841591Ssklower return ((struct pkcb *)0); 7941591Ssklower } 8041591Ssklower #else 8141591Ssklower register struct mbuf *p; 8241591Ssklower 8341591Ssklower MCLGET (p, 1); 8441591Ssklower if (p == 0) { 8541591Ssklower m_freem (m); 8641591Ssklower return ((struct pkcb *)0); 8741591Ssklower } 8841591Ssklower m -> m_off = (int)p - (int)m; 8941591Ssklower #endif 9041591Ssklower #endif 9141591Ssklower } 9241591Ssklower pkp = mtod (m, struct pkcb *); 9341591Ssklower bzero ((caddr_t)pkp, size); 9441591Ssklower 9541591Ssklower /* 9641591Ssklower * Allocate a logical channel descriptor for lcn 0 9741591Ssklower */ 9841591Ssklower 9941591Ssklower m = m_getclr (M_DONTWAIT, MT_PCB); 10041591Ssklower if (m == 0) { 10141591Ssklower m_freem (dtom (pkp)); 10241591Ssklower return ((struct pkcb *)0); 10341591Ssklower } 10441591Ssklower lcp = mtod (m, struct pklcd *); 10541591Ssklower lcp -> lcd_state = READY; 10641591Ssklower lcp -> lcd_pkp = pkp; 10741591Ssklower pkp -> pk_chan[0] = lcp; 10841591Ssklower 10941591Ssklower pkp -> pk_output = pp -> pr_output; 11041591Ssklower pkp -> pk_xcp = xcp; 11141591Ssklower pkp -> pk_state = DTE_WAITING; 11241591Ssklower pkp -> pk_maxlcn = xcp -> xc_maxlcn; 11341591Ssklower pkp -> pk_next = pkcbhead; 11441591Ssklower pkcbhead = pkp; 11541591Ssklower 11641591Ssklower /* 11741591Ssklower * set defaults 11841591Ssklower */ 11941591Ssklower 12041591Ssklower if (xcp -> xc_pwsize == 0) 12141591Ssklower xcp -> xc_pwsize = DEFAULT_WINDOW_SIZE; 12241591Ssklower if (xcp -> xc_psize == 0) 12341591Ssklower xcp -> xc_psize = X25_PS128; 12441591Ssklower return (pkp); 12541591Ssklower } 12641591Ssklower 12741591Ssklower /* 12841591Ssklower * This procedure is called by the link level whenever the link 12941591Ssklower * becomes operational, is reset, or when the link goes down. 13041591Ssklower */ 13141591Ssklower 13241591Ssklower pk_ctlinput (code, xcp) 13341591Ssklower struct x25config *xcp; 13441591Ssklower { 13541591Ssklower register struct pkcb *pkp; 13641591Ssklower 13741591Ssklower for (pkp = pkcbhead; pkp; pkp = pkp -> pk_next) 13841591Ssklower if (pkp -> pk_xcp == xcp) 13941591Ssklower break; 14041591Ssklower 14141591Ssklower if (pkp == 0 && (pkp = pk_newlink (xcp)) == 0) 14241591Ssklower return (EINVAL); 14341591Ssklower 14441591Ssklower switch (code) { 14541591Ssklower case PRC_LINKUP: 14641591Ssklower if (pkp -> pk_state == DTE_WAITING) 14741591Ssklower pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); 14841591Ssklower break; 14941591Ssklower 15041591Ssklower case PRC_LINKDOWN: 15141591Ssklower pk_restart (pkp, -1); /* Clear all active circuits */ 15241591Ssklower pkp -> pk_state = DTE_WAITING; 15341591Ssklower break; 15441591Ssklower 15541591Ssklower case PRC_LINKRESET: 15641591Ssklower pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION); 15741591Ssklower break; 15841591Ssklower 15941591Ssklower } 16041591Ssklower return (0); 16141591Ssklower } 16241591Ssklower 16341591Ssklower /* 16441591Ssklower * X.25 PACKET INPUT 16541591Ssklower * 16641591Ssklower * This procedure is called by a link level procedure whenever 16741591Ssklower * an information frame is received. It decodes the packet and 16841591Ssklower * demultiplexes based on the logical channel number. 16941591Ssklower * 17041591Ssklower */ 17141591Ssklower 17241591Ssklower pk_input (m, xcp) 17341591Ssklower register struct mbuf *m; 17441591Ssklower struct x25config *xcp; 17541591Ssklower { 17641591Ssklower register struct x25_packet *xp; 17741591Ssklower register struct pklcd *lcp; 17841591Ssklower register struct socket *so = 0; 17941591Ssklower register struct pkcb *pkp; 18041591Ssklower int ptype, lcn, lcdstate = LISTEN; 18141591Ssklower static struct x25config *lastxcp; 18241591Ssklower static struct pkcb *lastpkp; 18341591Ssklower 18441591Ssklower if (xcp == lastxcp) 18541591Ssklower pkp = lastpkp; 18641591Ssklower else { 18741591Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 18841591Ssklower if (pkp == 0) { 18941591Ssklower pk_message (0, xcp, "pk_input: unknown network"); 19041591Ssklower m_freem (m); 19141591Ssklower return; 19241591Ssklower } 19341591Ssklower if (pkp -> pk_xcp == xcp) 19441591Ssklower break; 19541591Ssklower } 19641591Ssklower lastxcp = xcp; 19741591Ssklower lastpkp = pkp; 19841591Ssklower } 19941591Ssklower 20041591Ssklower xp = mtod (m, struct x25_packet *); 20141591Ssklower ptype = pk_decode (xp); 20241591Ssklower lcn = xp -> logical_channel_number; 20341591Ssklower lcp = pkp -> pk_chan[lcn]; 20441591Ssklower 20541591Ssklower /* 20641591Ssklower * If the DTE is in Restart state, then it will ignore data, 20741591Ssklower * interrupt, call setup and clearing, flow control and reset 20841591Ssklower * packets. 20941591Ssklower */ 21041591Ssklower if (lcn < 0 || lcn > pkp -> pk_maxlcn) { 21141591Ssklower pk_message (lcn, pkp -> pk_xcp, "illegal lcn"); 21241591Ssklower m_freem (m); 21341591Ssklower return; 21441591Ssklower } 21541591Ssklower 21641591Ssklower pk_trace (pkp -> pk_xcp, xp, "P-In"); 21741591Ssklower 21841591Ssklower if (pkp -> pk_state != DTE_READY && ptype != RESTART && ptype != RESTART_CONF) { 21941591Ssklower m_freem (m); 22041591Ssklower return; 22141591Ssklower } 22241591Ssklower if (lcp) { 22341591Ssklower so = lcp -> lcd_so; 22441591Ssklower lcdstate = lcp -> lcd_state; 22541591Ssklower } else { 22641591Ssklower if (ptype == CLEAR) { /* idle line probe (Datapac specific) */ 22741591Ssklower /* send response on lcd 0's output queue */ 22841591Ssklower lcp -> lcd_template = pk_template (lcn, X25_CLEAR_CONFIRM); 22941591Ssklower pk_output (lcp); 23041591Ssklower m_freem (m); 23141591Ssklower return; 23241591Ssklower } 23341591Ssklower if (ptype != CALL) 23441591Ssklower ptype = INVALID_PACKET; 23541591Ssklower } 23641591Ssklower 23741591Ssklower if (lcn == 0 && ptype != RESTART && ptype != RESTART_CONF) { 23841591Ssklower pk_message (0, pkp -> pk_xcp, "illegal ptype (%s) on lcn 0", 23941591Ssklower pk_name[ptype / MAXSTATES]); 24041591Ssklower m_freem (m); 24141591Ssklower return; 24241591Ssklower } 24341591Ssklower 24441591Ssklower switch (ptype + lcdstate) { 24541591Ssklower /* 24641591Ssklower * Incoming Call packet received. 24741591Ssklower */ 24841591Ssklower case CALL + LISTEN: 24941591Ssklower incoming_call (pkp, xp, m -> m_len); 25041591Ssklower break; 25141591Ssklower 25241591Ssklower /* 25341591Ssklower * Call collision: Just throw this "incoming call" away since 25441591Ssklower * the DCE will ignore it anyway. 25541591Ssklower */ 25641591Ssklower case CALL + SENT_CALL: 25741591Ssklower pk_message ((int)xp -> logical_channel_number, pkp -> pk_xcp, 25841591Ssklower "incoming call collision"); 25941591Ssklower break; 26041591Ssklower 26141591Ssklower /* 26241591Ssklower * Call confirmation packet received. This usually means our 26341591Ssklower * previous connect request is now complete. 26441591Ssklower */ 26541591Ssklower case CALL_ACCEPTED + SENT_CALL: 26641591Ssklower call_accepted (lcp, xp, m -> m_len); 26741591Ssklower break; 26841591Ssklower 26941591Ssklower /* 27041591Ssklower * This condition can only happen if the previous state was 27141591Ssklower * SENT_CALL. Just ignore the packet, eventually a clear 27241591Ssklower * confirmation should arrive. 27341591Ssklower */ 27441591Ssklower case CALL_ACCEPTED + SENT_CLEAR: 27541591Ssklower break; 27641591Ssklower 27741591Ssklower /* 27841591Ssklower * Clear packet received. This requires a complete tear down 27941591Ssklower * of the virtual circuit. Free buffers and control blocks. 28041591Ssklower * and send a clear confirmation. 28141591Ssklower */ 28241591Ssklower case CLEAR + READY: 28341591Ssklower case CLEAR + RECEIVED_CALL: 28441591Ssklower case CLEAR + SENT_CALL: 28541591Ssklower case CLEAR + DATA_TRANSFER: 28641591Ssklower lcp -> lcd_state = RECEIVED_CLEAR; 28741591Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR_CONFIRM); 28841591Ssklower pk_output (lcp); 28941591Ssklower pk_clearcause (pkp, xp); 29041591Ssklower pk_close (lcp); 29141591Ssklower break; 29241591Ssklower 29341591Ssklower /* 29441591Ssklower * Clear collision: Treat this clear packet as a confirmation. 29541591Ssklower */ 29641591Ssklower case CLEAR + SENT_CLEAR: 29741591Ssklower pk_close (lcp); 29841591Ssklower break; 29941591Ssklower 30041591Ssklower /* 30141591Ssklower * Clear confirmation received. This usually means the virtual 30241591Ssklower * circuit is now completely removed. 30341591Ssklower */ 30441591Ssklower case CLEAR_CONF + SENT_CLEAR: 30541591Ssklower pk_close (lcp); 30641591Ssklower break; 30741591Ssklower 30841591Ssklower /* 30941591Ssklower * A clear confirmation on an unassigned logical channel - just 31041591Ssklower * ignore it. Note: All other packets on an unassigned channel 31141591Ssklower * results in a clear. 31241591Ssklower */ 31341591Ssklower case CLEAR_CONF + READY: 31441591Ssklower break; 31541591Ssklower 31641591Ssklower /* 31741591Ssklower * Data packet received. Pass on to next level. Move the Q and M 31841591Ssklower * bits into the data portion for the next level. 31941591Ssklower */ 32041591Ssklower case DATA + DATA_TRANSFER: 32141591Ssklower if (lcp -> lcd_reset_condition) { 32241591Ssklower ptype = DELETE_PACKET; 32341591Ssklower break; 32441591Ssklower } 32541591Ssklower 32641591Ssklower /* 32741591Ssklower * Process the P(S) flow control information in this Data packet. 32841591Ssklower * Check that the packets arrive in the correct sequence and that 32941591Ssklower * they are within the "lcd_input_window". Input window rotation is 33041591Ssklower * initiated by the receive interface. 33141591Ssklower */ 33241591Ssklower 33341591Ssklower if (PS(xp) != ((lcp -> lcd_rsn + 1) % MODULUS) || 33441591Ssklower PS(xp) == ((lcp -> lcd_input_window + lcp->lcd_windowsize) % MODULUS)) { 33541591Ssklower m_freem (m); 33641591Ssklower pk_procerror (RESET, lcp, "p(s) flow control error"); 33741591Ssklower break; 33841591Ssklower } 33941591Ssklower lcp -> lcd_rsn = PS(xp); 34041591Ssklower 34141591Ssklower if (pk_ack (lcp, PR(xp)) != PACKET_OK) { 34241591Ssklower m_freem (m); 34341591Ssklower break; 34441591Ssklower } 34541591Ssklower 34641591Ssklower m -> m_off += PKHEADERLN; 34741591Ssklower m -> m_len -= PKHEADERLN; 34841591Ssklower if (lcp -> lcd_flags & X25_MQBIT) { 34941591Ssklower octet *t; 35041591Ssklower 35141591Ssklower m -> m_off -= 1; 35241591Ssklower m -> m_len += 1; 35341591Ssklower t = mtod (m, octet *); 35441591Ssklower *t = 0x00; 35541591Ssklower if (xp -> q_bit) 35641591Ssklower *t |= 0x80; 35741591Ssklower if (MBIT(xp)) 35841591Ssklower *t |= 0x40; 35941591Ssklower } 36041591Ssklower 36141591Ssklower /* 36241591Ssklower * Discard Q-BIT packets if the application 36341591Ssklower * doesn't want to be informed of M and Q bit status 36441591Ssklower */ 36541591Ssklower if (xp -> q_bit && (lcp -> lcd_flags & X25_MQBIT) == 0) { 36641591Ssklower m_freem (m); 36741591Ssklower lcp -> lcd_rxcnt++; 36841591Ssklower /* 36941591Ssklower * NB. This is dangerous: sending a RR here can 37041591Ssklower * cause sequence number errors if a previous data 37141591Ssklower * packet has not yet been passed up to the application 37241591Ssklower * (RR's are normally generated via PRU_RCVD). 37341591Ssklower */ 37441591Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RR); 37541591Ssklower pk_output (lcp); 37641591Ssklower } else { 37741591Ssklower #ifdef BSD4_3 37841591Ssklower sbappendrecord (&so -> so_rcv, m); 37941591Ssklower #else 38041591Ssklower sbappend (&so -> so_rcv, m); 38141591Ssklower #endif 38241591Ssklower sorwakeup (so); 38341591Ssklower } 38441591Ssklower break; 38541591Ssklower 38641591Ssklower /* 38741591Ssklower * Interrupt packet received. 38841591Ssklower */ 38941591Ssklower case INTERRUPT + DATA_TRANSFER: 39041591Ssklower if (lcp -> lcd_reset_condition) 39141591Ssklower break; 39241591Ssklower lcp -> lcd_intrdata = xp -> packet_data; 39341591Ssklower sohasoutofband (so); 39441591Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM); 39541591Ssklower pk_output (lcp); 39641591Ssklower break; 39741591Ssklower 39841591Ssklower /* 39941591Ssklower * Interrupt confirmation packet received. 40041591Ssklower */ 40141591Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 40241591Ssklower if (lcp -> lcd_reset_condition) 40341591Ssklower break; 40441591Ssklower if (lcp -> lcd_intrconf_pending == TRUE) 40541591Ssklower lcp -> lcd_intrconf_pending = FALSE; 40641591Ssklower else 40741591Ssklower pk_procerror (RESET, lcp, "unexpected packet"); 40841591Ssklower break; 40941591Ssklower 41041591Ssklower /* 41141591Ssklower * Receiver ready received. Rotate the output window and output 41241591Ssklower * any data packets waiting transmission. 41341591Ssklower */ 41441591Ssklower case RR + DATA_TRANSFER: 41541591Ssklower if (lcp -> lcd_reset_condition) 41641591Ssklower break; 41741591Ssklower if (pk_ack (lcp, PR(xp)) != PACKET_OK) 41841591Ssklower break; 41941591Ssklower if (lcp -> lcd_rnr_condition == TRUE) 42041591Ssklower lcp -> lcd_rnr_condition = FALSE; 42141591Ssklower pk_output (lcp); 42241591Ssklower break; 42341591Ssklower 42441591Ssklower /* 42541591Ssklower * Receiver Not Ready received. Packets up to the P(R) can be 42641591Ssklower * be sent. Condition is cleared with a RR. 42741591Ssklower */ 42841591Ssklower case RNR + DATA_TRANSFER: 42941591Ssklower if (lcp -> lcd_reset_condition) 43041591Ssklower break; 43141591Ssklower if (pk_ack (lcp, PR(xp)) != PACKET_OK) 43241591Ssklower break; 43341591Ssklower lcp -> lcd_rnr_condition = TRUE; 43441591Ssklower break; 43541591Ssklower 43641591Ssklower /* 43741591Ssklower * Reset packet received. Set state to FLOW_OPEN. The Input and 43841591Ssklower * Output window edges ar set to zero. Both the send and receive 43941591Ssklower * numbers are reset. A confirmation is returned. 44041591Ssklower */ 44141591Ssklower case RESET + DATA_TRANSFER: 44241591Ssklower if (lcp -> lcd_reset_condition) 44341591Ssklower /* Reset collision. Just ignore packet. */ 44441591Ssklower break; 44541591Ssklower 44641591Ssklower pk_resetcause (pkp, xp); 44741591Ssklower sbflush (&so -> so_snd); 44841591Ssklower sbflush (&so -> so_rcv); 44941591Ssklower 45041591Ssklower wakeup ((caddr_t) & so -> so_timeo); 45141591Ssklower sorwakeup (so); 45241591Ssklower sowwakeup (so); 45341591Ssklower 45441591Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 45541591Ssklower lcp -> lcd_intrconf_pending = FALSE; 45641591Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 45741591Ssklower lcp -> lcd_last_transmitted_pr = 0; 45841591Ssklower lcp -> lcd_ssn = 0; 45941591Ssklower lcp -> lcd_rsn = MODULUS - 1; 46041591Ssklower 46141591Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM); 46241591Ssklower pk_output (lcp); 46341591Ssklower break; 46441591Ssklower 46541591Ssklower /* 46641591Ssklower * Reset confirmation received. 46741591Ssklower */ 46841591Ssklower case RESET_CONF + DATA_TRANSFER: 46941591Ssklower if (lcp -> lcd_reset_condition) { 47041591Ssklower lcp -> lcd_reset_condition = FALSE; 47141591Ssklower pk_output (lcp); 47241591Ssklower } 47341591Ssklower else 47441591Ssklower pk_procerror (RESET, lcp, "unexpected packet"); 47541591Ssklower break; 47641591Ssklower 47741591Ssklower case DATA + SENT_CLEAR: 47841591Ssklower ptype = DELETE_PACKET; 47941591Ssklower case RR + SENT_CLEAR: 48041591Ssklower case RNR + SENT_CLEAR: 48141591Ssklower case INTERRUPT + SENT_CLEAR: 48241591Ssklower case INTERRUPT_CONF + SENT_CLEAR: 48341591Ssklower case RESET + SENT_CLEAR: 48441591Ssklower case RESET_CONF + SENT_CLEAR: 48541591Ssklower /* Just ignore packet if we have sent a CLEAR already. 48641591Ssklower */ 48741591Ssklower break; 48841591Ssklower 48941591Ssklower /* 49041591Ssklower * Restart sets all the permanent virtual circuits to the "Data 49141591Ssklower * Transfer" stae and all the switched virtual circuits to the 49241591Ssklower * "Ready" state. 49341591Ssklower */ 49441591Ssklower case RESTART + READY: 49541591Ssklower switch (pkp -> pk_state) { 49641591Ssklower case DTE_SENT_RESTART: 49741591Ssklower /* Restart collision. */ 49841591Ssklower pkp -> pk_state = DTE_READY; 49941591Ssklower pk_message (0, pkp -> pk_xcp, 50041591Ssklower "Packet level operational"); 50141591Ssklower break; 50241591Ssklower 50341591Ssklower default: 50441591Ssklower pk_restart (pkp, -1); 50541591Ssklower pk_restartcause (pkp, xp); 50641591Ssklower pkp -> pk_chan[0] -> lcd_template = pk_template (0, 50741591Ssklower X25_RESTART_CONFIRM); 50841591Ssklower pk_output (pkp -> pk_chan[0]); 50941591Ssklower } 51041591Ssklower break; 51141591Ssklower 51241591Ssklower /* 51341591Ssklower * Restart confirmation received. All logical channels are set 51441591Ssklower * to READY. 51541591Ssklower */ 51641591Ssklower case RESTART_CONF + READY: 51741591Ssklower switch (pkp -> pk_state) { 51841591Ssklower case DTE_SENT_RESTART: 51941591Ssklower pkp -> pk_state = DTE_READY; 52041591Ssklower pk_message (0, pkp -> pk_xcp, 52141591Ssklower "Packet level operational"); 52241591Ssklower break; 52341591Ssklower 52441591Ssklower default: 52541591Ssklower /* Restart local procedure error. */ 52641591Ssklower pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR); 52741591Ssklower pkp -> pk_state = DTE_SENT_RESTART; 52841591Ssklower } 52941591Ssklower break; 53041591Ssklower 53141591Ssklower default: 53241591Ssklower if (lcp) { 53341591Ssklower pk_procerror (CLEAR, lcp, "unknown packet error"); 53441591Ssklower pk_message (lcn, pkp -> pk_xcp, 53541591Ssklower "\"%s\" unexpected in \"%s\" state", 53641591Ssklower pk_name[ptype/MAXSTATES], pk_state[lcdstate]); 53741591Ssklower } 53841591Ssklower else /* Packets arrived on an unassigned channel. 53941591Ssklower */ 54041591Ssklower pk_message ((int)xp->logical_channel_number, pkp -> pk_xcp, 54141591Ssklower "packet arrived on unassigned lcn"); 54241591Ssklower break; 54341591Ssklower } 54441591Ssklower if (ptype != DATA) 54541591Ssklower m_freem (m); 54641591Ssklower } 54741591Ssklower 54841591Ssklower 54941591Ssklower /* 55041591Ssklower * This routine handles incoming call packets. It matches the protocol 55141591Ssklower * field on the Call User Data field (usually the first four bytes) with 55241591Ssklower * sockets awaiting connections. 55341591Ssklower */ 55441591Ssklower 55541591Ssklower static 55641591Ssklower incoming_call (pkp, xp, len) 55741591Ssklower struct pkcb *pkp; 55841591Ssklower struct x25_packet *xp; 55941591Ssklower { 56041591Ssklower register struct pklcd *lcp, *l; 56141591Ssklower register struct sockaddr_x25 *sa; 56241591Ssklower register struct x25_calladdr *a; 56341591Ssklower register struct socket *so; 56441591Ssklower struct mbuf *m; 56541591Ssklower register int l1, l2; 56641591Ssklower char *e, *errstr = "server unavailable"; 56741591Ssklower octet *u; 56841591Ssklower int lcn = xp -> logical_channel_number; 56941591Ssklower 57041591Ssklower /* First, copy the data from the incoming call packet to a X25_socket 57141591Ssklower descriptor. */ 57241591Ssklower 57341591Ssklower a = (struct x25_calladdr *) &xp -> packet_data; 57441591Ssklower l1 = a -> calling_addrlen; 57541591Ssklower l2 = a -> called_addrlen; 57641591Ssklower if ((m = m_getclr (M_DONTWAIT, MT_HEADER)) == 0) 57741591Ssklower return; 57841591Ssklower sa = mtod (m, struct sockaddr_x25 *); 57941591Ssklower u = (octet *) (a -> address_field + l2 / 2); 58041591Ssklower e = sa -> x25_addr; 58141591Ssklower if (l2 & 0x01) { 58241591Ssklower *e++ = *u++ & 0x0f; 58341591Ssklower l1--; 58441591Ssklower } 58541591Ssklower from_bcd (e, &u, l1); 58641591Ssklower if (l1 & 0x01) 58741591Ssklower u++; 58841591Ssklower 58941591Ssklower parse_facilities (u, sa); 59041591Ssklower u += *u + 1; 59141591Ssklower sa -> x25_udlen = min (16, ((octet *)xp) + len - u); 59241591Ssklower if (sa -> x25_udlen < 0) 59341591Ssklower sa -> x25_udlen = 0; 59441591Ssklower bcopy ((caddr_t)u, sa -> x25_udata, (unsigned)sa -> x25_udlen); 59541591Ssklower 59641591Ssklower /* 59741591Ssklower * Now, loop through the listen sockets looking for a match on the 59841591Ssklower * PID. That is the first four octets of the user data field. This 59941591Ssklower * is the closest thing to a port number for X.25 packets. What it 60041591Ssklower * does provide is away of multiplexing services at the user level. 60141591Ssklower */ 60241591Ssklower 60341591Ssklower for (l = pk_listenhead; l; l = l -> lcd_listen) { 60441591Ssklower struct sockaddr_x25 *sxp = l -> lcd_ceaddr; 60541591Ssklower 60641591Ssklower if (bcmp (sxp -> x25_udata, sa -> x25_udata, sxp->x25_udlen)) 60741591Ssklower continue; 60841591Ssklower if (sxp -> x25_net && sxp -> x25_net != pkp->pk_xcp->xc_net) 60941591Ssklower continue; 61041591Ssklower /* 61141591Ssklower * don't accept incoming collect calls unless 61241591Ssklower * the server sets the reverse charging option. 61341591Ssklower */ 61441591Ssklower if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 && 61541591Ssklower sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) { 61641591Ssklower errstr = "incoming collect call refused"; 61741591Ssklower break; 61841591Ssklower } 61941591Ssklower so = sonewconn (l -> lcd_so); 62041591Ssklower if (so == NULL) { 62141591Ssklower /* 62241591Ssklower * Insufficient space or too many unaccepted 62341591Ssklower * connections. Just throw the call away. 62441591Ssklower */ 62541591Ssklower errstr = "server malfunction"; 62641591Ssklower break; 62741591Ssklower } 62841591Ssklower lcp = (struct pklcd *) so -> so_pcb; 62941591Ssklower lcp -> lcd_lcn = lcn; 63041591Ssklower lcp -> lcd_state = RECEIVED_CALL; 63141591Ssklower lcp -> lcd_craddr = sa; 63241591Ssklower sa -> x25_opts.op_flags |= sxp -> x25_opts.op_flags & 63341591Ssklower ~X25_REVERSE_CHARGE; 63441591Ssklower pk_assoc (pkp, lcp, sa); 63541591Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED); 63641591Ssklower pk_output (lcp); 63741591Ssklower soisconnected (so); 63841591Ssklower return; 63941591Ssklower } 64041591Ssklower 64141591Ssklower /* 64241591Ssklower * If the call fails for whatever reason, we still need to build a 64341591Ssklower * skeleton LCD in order to be able to properly receive the CLEAR 64441591Ssklower * CONFIRMATION. 64541591Ssklower */ 64641591Ssklower #ifdef WATERLOO /* be explicit */ 64741591Ssklower if (l == 0 && bcmp(sa->x25_udata, "ean", 3) == 0) 64841591Ssklower pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s", 64941591Ssklower sa->x25_addr, sa->x25_udata[3] & 0xff, errstr); 65041591Ssklower else if (l == 0 && bcmp(sa->x25_udata, "\1\0\0\0", 4) == 0) 65141591Ssklower pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s", 65241591Ssklower sa->x25_addr, errstr); 65341591Ssklower else 65441591Ssklower #endif 65541591Ssklower pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s", 65641591Ssklower sa -> x25_addr, sa -> x25_udata[0] & 0xff, 65741591Ssklower sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff, 65841591Ssklower sa -> x25_udata[3] & 0xff, errstr); 65941591Ssklower if ((m = m_getclr (M_DONTWAIT, MT_HEADER)) == 0) { 66041591Ssklower (void) m_free (dtom (sa)); 66141591Ssklower return; 66241591Ssklower } 66341591Ssklower lcp = mtod (m, struct pklcd *); 66441591Ssklower lcp -> lcd_lcn = lcn; 66541591Ssklower lcp -> lcd_state = RECEIVED_CALL; 66641591Ssklower pk_assoc (pkp, lcp, sa); 66741591Ssklower (void) m_free (dtom (sa)); 66841591Ssklower pk_clear (lcp); 66941591Ssklower } 67041591Ssklower 67141591Ssklower static 67241591Ssklower call_accepted (lcp, xp, len) 67341591Ssklower struct pklcd *lcp; 67441591Ssklower struct x25_packet *xp; 67541591Ssklower { 67641591Ssklower register struct x25_calladdr *ap; 67741591Ssklower register octet *fcp; 67841591Ssklower 67941591Ssklower lcp -> lcd_state = DATA_TRANSFER; 68041591Ssklower soisconnected (lcp -> lcd_so); 68141591Ssklower if (len > 3) { 68241591Ssklower ap = (struct x25_calladdr *) &xp -> packet_data; 68341591Ssklower fcp = (octet *) ap -> address_field + (ap -> calling_addrlen + 68441591Ssklower ap -> called_addrlen + 1) / 2; 68541591Ssklower if (fcp + *fcp <= ((octet *)xp) + len) 68641591Ssklower parse_facilities (fcp, lcp -> lcd_ceaddr); 68741591Ssklower } 68841591Ssklower pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr); 68941591Ssklower } 69041591Ssklower 69141591Ssklower static 69241591Ssklower parse_facilities (fcp, sa) 69341591Ssklower register octet *fcp; 69441591Ssklower register struct sockaddr_x25 *sa; 69541591Ssklower { 69641591Ssklower register octet *maxfcp; 69741591Ssklower 69841591Ssklower maxfcp = fcp + *fcp; 69941591Ssklower fcp++; 70041591Ssklower while (fcp < maxfcp) { 70141591Ssklower /* 70241591Ssklower * Ignore national DCE or DTE facilities 70341591Ssklower */ 70441591Ssklower if (*fcp == 0 || *fcp == 0xff) 70541591Ssklower break; 70641591Ssklower switch (*fcp) { 70741591Ssklower case FACILITIES_WINDOWSIZE: 70841591Ssklower sa -> x25_opts.op_wsize = fcp[1]; 70941591Ssklower fcp += 3; 71041591Ssklower break; 71141591Ssklower 71241591Ssklower case FACILITIES_PACKETSIZE: 71341591Ssklower sa -> x25_opts.op_psize = fcp[1]; 71441591Ssklower fcp += 3; 71541591Ssklower break; 71641591Ssklower 71741591Ssklower case FACILITIES_THROUGHPUT: 71841591Ssklower sa -> x25_opts.op_speed = fcp[1]; 71941591Ssklower fcp += 2; 72041591Ssklower break; 72141591Ssklower 72241591Ssklower case FACILITIES_REVERSE_CHARGE: 72341591Ssklower if (fcp[1] & 01) 72441591Ssklower sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE; 72541591Ssklower /* 72641591Ssklower * Datapac specific: for a X.25(1976) DTE, bit 2 72741591Ssklower * indicates a "hi priority" (eg. international) call. 72841591Ssklower */ 72941591Ssklower if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0) 73041591Ssklower sa -> x25_opts.op_psize = X25_PS128; 73141591Ssklower fcp += 2; 73241591Ssklower break; 73341591Ssklower 73441591Ssklower default: 73541591Ssklower /*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/ 73641591Ssklower switch ((*fcp & 0xc0) >> 6) { 73741591Ssklower case 0: /* class A */ 73841591Ssklower fcp += 2; 73941591Ssklower break; 74041591Ssklower 74141591Ssklower case 1: 74241591Ssklower fcp += 3; 74341591Ssklower break; 74441591Ssklower 74541591Ssklower case 2: 74641591Ssklower fcp += 4; 74741591Ssklower break; 74841591Ssklower 74941591Ssklower case 3: 75041591Ssklower fcp++; 75141591Ssklower fcp += *fcp; 75241591Ssklower } 75341591Ssklower } 75441591Ssklower } 75541591Ssklower } 75641591Ssklower 75741591Ssklower from_bcd (a, x, len) 75841591Ssklower register char *a; 75941591Ssklower register octet **x; 76041591Ssklower register int len; 76141591Ssklower { 76241591Ssklower register int posn = 0; 76341591Ssklower 76441591Ssklower while (--len >= 0) { 76541591Ssklower if (posn++ & 0x01) 76641591Ssklower *a = *(*x)++ & 0x0f; 76741591Ssklower else 76841591Ssklower *a = (**x >> 4) & 0x0F; 76941591Ssklower *a++ |= 0x30; 77041591Ssklower } 77141591Ssklower } 772