xref: /csrg-svn/sys/netccitt/pk_input.c (revision 41709)
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