xref: /csrg-svn/sys/netccitt/pk_input.c (revision 47268)
141709Ssklower /*
241709Ssklower  * Copyright (c) University of British Columbia, 1984
341709Ssklower  * Copyright (c) 1990 The Regents of the University of California.
441709Ssklower  * All rights reserved.
541709Ssklower  *
641709Ssklower  * This code is derived from software contributed to Berkeley by
741709Ssklower  * the Laboratory for Computation Vision and the Computer Science Department
841709Ssklower  * of the University of British Columbia.
941709Ssklower  *
1041709Ssklower  * %sccs.include.redist.c%
1141709Ssklower  *
12*47268Ssklower  *	@(#)pk_input.c	7.9 (Berkeley) 03/12/91
1341709Ssklower  */
1441591Ssklower 
1545165Ssklower #include "param.h"
1645165Ssklower #include "systm.h"
1745165Ssklower #include "mbuf.h"
1845165Ssklower #include "socket.h"
1945165Ssklower #include "protosw.h"
2045165Ssklower #include "socketvar.h"
2145165Ssklower #include "errno.h"
2241591Ssklower 
2341591Ssklower #include "../net/if.h"
2441591Ssklower 
2545165Ssklower #include "x25.h"
2645165Ssklower #include "pk.h"
2745165Ssklower #include "pk_var.h"
2841591Ssklower 
2941591Ssklower /*
3041591Ssklower  *  This procedure is called by the link level whenever the link
3141591Ssklower  *  becomes operational, is reset, or when the link goes down.
3241591Ssklower  */
3341591Ssklower 
3445297Ssklower pk_ctlinput (code, xcp)
3545297Ssklower register struct x25config *xcp;
3641591Ssklower {
3741591Ssklower 
3845297Ssklower 	register struct pkcb *pkp;
3945297Ssklower 
4045297Ssklower 	for (pkp = pkcbhead; pkp; pkp = pkp -> pk_next)
4145297Ssklower 		if (pkp -> pk_xcp == xcp)
4245297Ssklower 			break;
4345297Ssklower 
4442277Ssklower 	if (pkp == 0)
4541591Ssklower 		return (EINVAL);
4645297Ssklower 
4741591Ssklower 	switch (code) {
4841591Ssklower 	case PRC_LINKUP:
4941591Ssklower 		if (pkp -> pk_state == DTE_WAITING)
5041591Ssklower 			pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION);
5141591Ssklower 		break;
5241591Ssklower 
5341591Ssklower 	case PRC_LINKDOWN:
5441591Ssklower 		pk_restart (pkp, -1);	/* Clear all active circuits */
5541591Ssklower 		pkp -> pk_state = DTE_WAITING;
5641591Ssklower 		break;
5741591Ssklower 
5841591Ssklower 	case PRC_LINKRESET:
5941591Ssklower 		pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION);
6041591Ssklower 		break;
6141591Ssklower 
6241591Ssklower 	}
6341591Ssklower 	return (0);
6441591Ssklower }
6545297Ssklower struct ifqueue pkintrq;
6645297Ssklower /*
6745297Ssklower  * This routine is called if there are semi-smart devices that do HDLC
6845297Ssklower  * in hardware and want to queue the packet and call level 3 directly
6945297Ssklower  */
7045297Ssklower pkintr ()
7145297Ssklower {
7245297Ssklower 	register struct mbuf *m;
7345297Ssklower 	register struct ifaddr *ifa;
7445297Ssklower 	register struct ifnet *ifp;
7545297Ssklower 	register int s;
7641591Ssklower 
7745297Ssklower 	for (;;) {
7845297Ssklower 		s = splimp ();
7945297Ssklower 		IF_DEQUEUE (&pkintrq, m);
8045297Ssklower 		splx (s);
8145297Ssklower 		if (m == 0)
8245297Ssklower 			break;
8345297Ssklower 		if (m->m_len < PKHEADERLN) {
8445297Ssklower 			printf ("pkintr: packet too short (len=%d)\n",
8545297Ssklower 				m->m_len);
8645297Ssklower 			m_freem (m);
8745297Ssklower 			continue;
8845297Ssklower 		}
8945297Ssklower 		if ((m->m_flags & M_PKTHDR) == 0)
9045297Ssklower 			panic("pkintr");
9145297Ssklower 		ifp = m->m_pkthdr.rcvif;
9245297Ssklower 		/*
9345297Ssklower 		 * look up the appropriate control block
9445297Ssklower 		 */
9545297Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
9645297Ssklower 			if (ifa->ifa_addr->sa_family == AF_CCITT)
9745297Ssklower 				break;
9845297Ssklower 		if (ifa == 0)
9945297Ssklower 			continue;
10045297Ssklower 		pk_input(m, ((struct x25_ifaddr *)ifa)->ia_xcp);
10145297Ssklower 	}
10245297Ssklower }
10345297Ssklower struct mbuf *pk_bad_packet;
10441591Ssklower /*
10541591Ssklower  *  X.25 PACKET INPUT
10641591Ssklower  *
10741591Ssklower  *  This procedure is called by a link level procedure whenever
10841591Ssklower  *  an information frame is received. It decodes the packet and
10941591Ssklower  *  demultiplexes based on the logical channel number.
11041591Ssklower  *
11141591Ssklower  */
11241591Ssklower 
11341591Ssklower pk_input (m, xcp)
11441591Ssklower register struct mbuf *m;
11541591Ssklower struct x25config *xcp;
11641591Ssklower {
11741591Ssklower 	register struct x25_packet *xp;
11841591Ssklower 	register struct pklcd *lcp;
11941591Ssklower 	register struct socket *so = 0;
12041591Ssklower 	register struct pkcb *pkp;
12141591Ssklower 	int  ptype, lcn, lcdstate = LISTEN;
12241591Ssklower 	static struct x25config *lastxcp;
12341591Ssklower 	static struct pkcb *lastpkp;
12441591Ssklower 
12541591Ssklower 	if (xcp == lastxcp)
12641591Ssklower 		pkp = lastpkp;
12741591Ssklower 	else {
12841591Ssklower 		for (pkp = pkcbhead; ; pkp = pkp -> pk_next) {
12941591Ssklower 			if (pkp == 0) {
13041591Ssklower 				pk_message (0, xcp, "pk_input: unknown network");
13141591Ssklower 				m_freem (m);
13241591Ssklower 				return;
13341591Ssklower 			}
13441591Ssklower 			if (pkp -> pk_xcp == xcp)
13541591Ssklower 				break;
13641591Ssklower 		}
13741591Ssklower 		lastxcp = xcp;
13841591Ssklower 		lastpkp = pkp;
13941591Ssklower 	}
14041591Ssklower 
14141591Ssklower 	xp = mtod (m, struct x25_packet *);
14241591Ssklower 	ptype = pk_decode (xp);
14345573Ssklower 	lcn = LCN(xp);
14441591Ssklower 	lcp = pkp -> pk_chan[lcn];
14541591Ssklower 
14641591Ssklower 	/*
14741591Ssklower 	 *  If the DTE is in Restart  state, then it will ignore data,
14841591Ssklower 	 *  interrupt, call setup and clearing, flow control and reset
14941591Ssklower 	 *  packets.
15041591Ssklower 	 */
15141591Ssklower 	if (lcn < 0 || lcn > pkp -> pk_maxlcn) {
15241591Ssklower 		pk_message (lcn, pkp -> pk_xcp, "illegal lcn");
15341591Ssklower 		m_freem (m);
15441591Ssklower 		return;
15541591Ssklower 	}
15641591Ssklower 
15745895Ssklower 	pk_trace (pkp -> pk_xcp, m, "P-In");
15841591Ssklower 
15941591Ssklower 	if (pkp -> pk_state != DTE_READY && ptype != RESTART && ptype != RESTART_CONF) {
16041591Ssklower 		m_freem (m);
16141591Ssklower 		return;
16241591Ssklower 	}
16341591Ssklower 	if (lcp) {
16441591Ssklower 		so = lcp -> lcd_so;
16541591Ssklower 		lcdstate = lcp -> lcd_state;
16641591Ssklower 	} else {
16741591Ssklower 		if (ptype == CLEAR) {	/* idle line probe (Datapac specific) */
16841591Ssklower 			/* send response on lcd 0's output queue */
16941591Ssklower 			lcp -> lcd_template = pk_template (lcn, X25_CLEAR_CONFIRM);
17041591Ssklower 			pk_output (lcp);
17141591Ssklower 			m_freem (m);
17241591Ssklower 			return;
17341591Ssklower 		}
17441591Ssklower 		if (ptype != CALL)
17541591Ssklower 			ptype = INVALID_PACKET;
17641591Ssklower 	}
17741591Ssklower 
17841591Ssklower 	if (lcn == 0 && ptype != RESTART && ptype != RESTART_CONF) {
17945297Ssklower 		pk_message (0, pkp -> pk_xcp, "illegal ptype (%d, %s) on lcn 0",
18045297Ssklower 			ptype, pk_name[ptype / MAXSTATES]);
18145297Ssklower 		if (pk_bad_packet)
18245297Ssklower 			m_freem (pk_bad_packet);
18345297Ssklower 		pk_bad_packet = m;
18441591Ssklower 		return;
18541591Ssklower 	}
18641591Ssklower 
18741591Ssklower 	switch (ptype + lcdstate) {
18841591Ssklower 	/*
18941591Ssklower 	 *  Incoming Call packet received.
19041591Ssklower 	 */
19141591Ssklower 	case CALL + LISTEN:
19245895Ssklower 		incoming_call (pkp, m);
19341591Ssklower 		break;
19441591Ssklower 
19541591Ssklower 	/*
19641591Ssklower 	 *  Call collision: Just throw this "incoming call" away since
19741591Ssklower 	 *  the DCE will ignore it anyway.
19841591Ssklower 	 */
19941591Ssklower 	case CALL + SENT_CALL:
20045573Ssklower 		pk_message ((int)lcn, pkp -> pk_xcp,
20141591Ssklower 			"incoming call collision");
20241591Ssklower 		break;
20341591Ssklower 
20441591Ssklower 	/*
20541591Ssklower 	 *  Call confirmation packet received. This usually means our
20641591Ssklower 	 *  previous connect request is now complete.
20741591Ssklower 	 */
20841591Ssklower 	case CALL_ACCEPTED + SENT_CALL:
20941591Ssklower 		call_accepted (lcp, xp, m -> m_len);
21041591Ssklower 		break;
21141591Ssklower 
21241591Ssklower 	/*
21341591Ssklower 	 *  This condition can only happen if the previous state was
21441591Ssklower 	 *  SENT_CALL. Just ignore the packet, eventually a clear
21541591Ssklower 	 *  confirmation should arrive.
21641591Ssklower 	 */
21741591Ssklower 	case CALL_ACCEPTED + SENT_CLEAR:
21841591Ssklower 		break;
21941591Ssklower 
22041591Ssklower 	/*
22141591Ssklower 	 *  Clear packet received. This requires a complete tear down
22241591Ssklower 	 *  of the virtual circuit.  Free buffers and control blocks.
22341591Ssklower 	 *  and send a clear confirmation.
22441591Ssklower 	 */
22541591Ssklower 	case CLEAR + READY:
22641591Ssklower 	case CLEAR + RECEIVED_CALL:
22741591Ssklower 	case CLEAR + SENT_CALL:
22841591Ssklower 	case CLEAR + DATA_TRANSFER:
22941591Ssklower 		lcp -> lcd_state = RECEIVED_CLEAR;
23041591Ssklower 		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR_CONFIRM);
23141591Ssklower 		pk_output (lcp);
23241591Ssklower 		pk_clearcause (pkp, xp);
23341591Ssklower 		pk_close (lcp);
23441591Ssklower 		break;
23541591Ssklower 
23641591Ssklower 	/*
23741591Ssklower 	 *  Clear collision: Treat this clear packet as a confirmation.
23841591Ssklower 	 */
23941591Ssklower 	case CLEAR + SENT_CLEAR:
24041591Ssklower 		pk_close (lcp);
24141591Ssklower 		break;
24241591Ssklower 
24341591Ssklower 	/*
24441591Ssklower 	 *  Clear confirmation received. This usually means the virtual
24541591Ssklower 	 *  circuit is now completely removed.
24641591Ssklower 	 */
24741591Ssklower 	case CLEAR_CONF + SENT_CLEAR:
24841591Ssklower 		pk_close (lcp);
24941591Ssklower 		break;
25041591Ssklower 
25141591Ssklower 	/*
25241591Ssklower 	 *  A clear confirmation on an unassigned logical channel - just
25341591Ssklower 	 *  ignore it. Note: All other packets on an unassigned channel
25441591Ssklower 	 *  results in a clear.
25541591Ssklower 	 */
25641591Ssklower 	case CLEAR_CONF + READY:
25741591Ssklower 		break;
25841591Ssklower 
25941591Ssklower 	/*
26041591Ssklower 	 *  Data packet received. Pass on to next level. Move the Q and M
26141591Ssklower 	 *  bits into the data portion for the next level.
26241591Ssklower 	 */
26341591Ssklower 	case DATA + DATA_TRANSFER:
26441591Ssklower 		if (lcp -> lcd_reset_condition) {
26541591Ssklower 			ptype = DELETE_PACKET;
26641591Ssklower 			break;
26741591Ssklower 		}
26841591Ssklower 
26941591Ssklower 		/*
27041591Ssklower 		 *  Process the P(S) flow control information in this Data packet.
27141591Ssklower 		 *  Check that the packets arrive in the correct sequence and that
27241591Ssklower 		 *  they are within the "lcd_input_window". Input window rotation is
27341591Ssklower 		 *  initiated by the receive interface.
27441591Ssklower 		 */
27541591Ssklower 
27641591Ssklower 		if (PS(xp) != ((lcp -> lcd_rsn + 1) % MODULUS) ||
27741591Ssklower 			PS(xp) == ((lcp -> lcd_input_window + lcp->lcd_windowsize) % MODULUS)) {
27841591Ssklower 			m_freem (m);
27945895Ssklower 			pk_procerror (RESET, lcp, "p(s) flow control error", 1);
28041591Ssklower 			break;
28141591Ssklower 		}
28241591Ssklower 		lcp -> lcd_rsn = PS(xp);
28341591Ssklower 
28441591Ssklower 		if (pk_ack (lcp, PR(xp)) != PACKET_OK) {
28541591Ssklower 			m_freem (m);
28641591Ssklower 			break;
28741591Ssklower 		}
28845895Ssklower 		m -> m_data += PKHEADERLN;
28945895Ssklower 		m -> m_len -= PKHEADERLN;
29045895Ssklower 		m -> m_pkthdr.len -= PKHEADERLN;
29145895Ssklower 
29245895Ssklower 		if (lcp -> lcd_flags & X25_MBS_HOLD) {
29345895Ssklower 			register struct mbuf *n = lcp -> lcd_cps;
29445895Ssklower 			int mbit = MBIT(xp);
29545895Ssklower 			octet q_and_d_bits;
29645895Ssklower 
29745895Ssklower 			if (n) {
29845895Ssklower 				n -> m_pkthdr.len += m -> m_pkthdr.len;
29945895Ssklower 				while (n -> m_next)
30045895Ssklower 					n = n -> m_next;
30145895Ssklower 				n -> m_next = m;
30245895Ssklower 				m = lcp -> lcd_cps;
30345895Ssklower 
30445895Ssklower 				if (lcp -> lcd_cpsmax &&
30545895Ssklower 				    n -> m_pkthdr.len > lcp -> lcd_cpsmax) {
30645895Ssklower 					pk_procerror (RESET, lcp,
30745895Ssklower 						"C.P.S. overflow", 128);
30845895Ssklower 					return;
30945895Ssklower 				}
31045895Ssklower 				q_and_d_bits = 0xc0 & *(octet *)xp;
31145895Ssklower 				xp = (struct x25_packet *)
31245895Ssklower 					(mtod(m, octet *) - PKHEADERLN);
31345895Ssklower 				*(octet *)xp |= q_and_d_bits;
31445895Ssklower 			}
31545895Ssklower 			if (mbit) {
31645895Ssklower 				lcp -> lcd_cps = m;
317*47268Ssklower 				lcp -> lcd_rxcnt++;
318*47268Ssklower 				pk_flowcontrol(lcp, 0, 1);
31945895Ssklower 				return;
32045895Ssklower 			}
32145895Ssklower 			lcp -> lcd_cps = 0;
32245895Ssklower 		}
32345297Ssklower 		if (so == 0)
32445297Ssklower 			break;
32541591Ssklower 		if (lcp -> lcd_flags & X25_MQBIT) {
32645573Ssklower 			octet t = (xp -> q_bit) ? t = 0x80 : 0;
32741591Ssklower 
32845573Ssklower 			if (MBIT(xp))
32945573Ssklower 				t |= 0x40;
33043361Ssklower 			m -> m_data -= 1;
33141591Ssklower 			m -> m_len += 1;
33245895Ssklower 			m -> m_pkthdr.len += 1;
33345573Ssklower 			*mtod(m, octet *) = t;
33441591Ssklower 		}
33541591Ssklower 
33641591Ssklower 		/*
33741591Ssklower 		 * Discard Q-BIT packets if the application
33841591Ssklower 		 * doesn't want to be informed of M and Q bit status
33941591Ssklower 		 */
34041591Ssklower 		if (xp -> q_bit && (lcp -> lcd_flags & X25_MQBIT) == 0) {
34141591Ssklower 			m_freem (m);
34241591Ssklower 			lcp -> lcd_rxcnt++;
34341591Ssklower 			/*
34441591Ssklower 			 * NB.  This is dangerous: sending a RR here can
34541591Ssklower 			 * cause sequence number errors if a previous data
34641591Ssklower 			 * packet has not yet been passed up to the application
34741591Ssklower 			 * (RR's are normally generated via PRU_RCVD).
34841591Ssklower 			 */
349*47268Ssklower 			pk_flowcontrol(lcp, 0, 1);
35041591Ssklower 		} else {
35141591Ssklower 			sbappendrecord (&so -> so_rcv, m);
35241591Ssklower 			sorwakeup (so);
35341591Ssklower 		}
35441591Ssklower 		break;
35541591Ssklower 
35641591Ssklower 	/*
35741591Ssklower 	 *  Interrupt packet received.
35841591Ssklower 	 */
35941591Ssklower 	case INTERRUPT + DATA_TRANSFER:
36041591Ssklower 		if (lcp -> lcd_reset_condition)
36141591Ssklower 			break;
36241591Ssklower 		lcp -> lcd_intrdata = xp -> packet_data;
36341591Ssklower 		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM);
36441591Ssklower 		pk_output (lcp);
36545895Ssklower 		m -> m_data += PKHEADERLN;
36645895Ssklower 		m -> m_len -= PKHEADERLN;
36745895Ssklower 		m -> m_pkthdr.len -= PKHEADERLN;
36845297Ssklower 		MCHTYPE(m, MT_OOBDATA);
36945895Ssklower 		if (so) {
37045895Ssklower 			if (so -> so_options & SO_OOBINLINE)
37145895Ssklower 				sbinsertoob (&so -> so_rcv, m);
37245895Ssklower 			else
37345895Ssklower 				m_freem (m);
37445297Ssklower 			sohasoutofband (so);
37545895Ssklower 		}
37641591Ssklower 		break;
37741591Ssklower 
37841591Ssklower 	/*
37941591Ssklower 	 *  Interrupt confirmation packet received.
38041591Ssklower 	 */
38141591Ssklower 	case INTERRUPT_CONF + DATA_TRANSFER:
38241591Ssklower 		if (lcp -> lcd_reset_condition)
38341591Ssklower 			break;
38441591Ssklower 		if (lcp -> lcd_intrconf_pending == TRUE)
38541591Ssklower 			lcp -> lcd_intrconf_pending = FALSE;
38641591Ssklower 		else
38745895Ssklower 			pk_procerror (RESET, lcp, "unexpected packet", 43);
38841591Ssklower 		break;
38941591Ssklower 
39041591Ssklower 	/*
39141591Ssklower 	 *  Receiver ready received. Rotate the output window and output
39241591Ssklower 	 *  any data packets waiting transmission.
39341591Ssklower 	 */
39441591Ssklower 	case RR + DATA_TRANSFER:
39545297Ssklower 		if (lcp -> lcd_reset_condition ||
39645297Ssklower 		    pk_ack (lcp, PR(xp)) != PACKET_OK) {
39745297Ssklower 			ptype = DELETE_PACKET;
39841591Ssklower 			break;
39945297Ssklower 		}
40041591Ssklower 		if (lcp -> lcd_rnr_condition == TRUE)
40141591Ssklower 			lcp -> lcd_rnr_condition = FALSE;
40241591Ssklower 		pk_output (lcp);
40341591Ssklower 		break;
40441591Ssklower 
40541591Ssklower 	/*
40641591Ssklower 	 *  Receiver Not Ready received. Packets up to the P(R) can be
40741591Ssklower 	 *  be sent. Condition is cleared with a RR.
40841591Ssklower 	 */
40941591Ssklower 	case RNR + DATA_TRANSFER:
41045297Ssklower 		if (lcp -> lcd_reset_condition ||
41145297Ssklower 		    pk_ack (lcp, PR(xp)) != PACKET_OK) {
41245297Ssklower 			ptype = DELETE_PACKET;
41341591Ssklower 			break;
41445297Ssklower 		}
41541591Ssklower 		lcp -> lcd_rnr_condition = TRUE;
41641591Ssklower 		break;
41741591Ssklower 
41841591Ssklower 	/*
41941591Ssklower 	 *  Reset packet received. Set state to FLOW_OPEN.  The Input and
42041591Ssklower 	 *  Output window edges ar set to zero. Both the send and receive
42141591Ssklower 	 *  numbers are reset. A confirmation is returned.
42241591Ssklower 	 */
42341591Ssklower 	case RESET + DATA_TRANSFER:
42441591Ssklower 		if (lcp -> lcd_reset_condition)
42541591Ssklower 			/* Reset collision. Just ignore packet. */
42641591Ssklower 			break;
42741591Ssklower 
42841591Ssklower 		pk_resetcause (pkp, xp);
42941591Ssklower 		lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
43041591Ssklower 			lcp -> lcd_intrconf_pending = FALSE;
43141591Ssklower 		lcp -> lcd_output_window = lcp -> lcd_input_window =
43241591Ssklower 			lcp -> lcd_last_transmitted_pr = 0;
43341591Ssklower 		lcp -> lcd_ssn = 0;
43441591Ssklower 		lcp -> lcd_rsn = MODULUS - 1;
43541591Ssklower 
43641591Ssklower 		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM);
43741591Ssklower 		pk_output (lcp);
43845297Ssklower 
43945895Ssklower 		pk_flush(lcp);
44045297Ssklower 		if (so == 0)
44145297Ssklower 			break;
44245297Ssklower 		wakeup ((caddr_t) & so -> so_timeo);
44345297Ssklower 		sorwakeup (so);
44445297Ssklower 		sowwakeup (so);
44541591Ssklower 		break;
44641591Ssklower 
44741591Ssklower 	/*
44841591Ssklower 	 *  Reset confirmation received.
44941591Ssklower 	 */
45041591Ssklower 	case RESET_CONF + DATA_TRANSFER:
45141591Ssklower 		if (lcp -> lcd_reset_condition) {
45241591Ssklower 			lcp -> lcd_reset_condition = FALSE;
45341591Ssklower 			pk_output (lcp);
45441591Ssklower 		}
45541591Ssklower 		else
45645895Ssklower 			pk_procerror (RESET, lcp, "unexpected packet", 32);
45741591Ssklower 		break;
45841591Ssklower 
45941591Ssklower 	case DATA + SENT_CLEAR:
46041591Ssklower 		ptype = DELETE_PACKET;
46141591Ssklower 	case RR + SENT_CLEAR:
46241591Ssklower 	case RNR + SENT_CLEAR:
46341591Ssklower 	case INTERRUPT + SENT_CLEAR:
46441591Ssklower 	case INTERRUPT_CONF + SENT_CLEAR:
46541591Ssklower 	case RESET + SENT_CLEAR:
46641591Ssklower 	case RESET_CONF + SENT_CLEAR:
46745297Ssklower 		/* Just ignore p if we have sent a CLEAR already.
46841591Ssklower 		   */
46941591Ssklower 		break;
47041591Ssklower 
47141591Ssklower 	/*
47241591Ssklower 	 *  Restart sets all the permanent virtual circuits to the "Data
47341591Ssklower 	 *  Transfer" stae and  all the switched virtual circuits to the
47441591Ssklower 	 *  "Ready" state.
47541591Ssklower 	 */
47641591Ssklower 	case RESTART + READY:
47741591Ssklower 		switch (pkp -> pk_state) {
47841591Ssklower 		case DTE_SENT_RESTART:
47941591Ssklower 			/* Restart collision. */
48041591Ssklower 			pkp -> pk_state = DTE_READY;
48141591Ssklower 			pk_message (0, pkp -> pk_xcp,
48241591Ssklower 				"Packet level operational");
48341591Ssklower 			break;
48441591Ssklower 
48541591Ssklower 		default:
48641591Ssklower 			pk_restart (pkp, -1);
48741591Ssklower 			pk_restartcause (pkp, xp);
48841591Ssklower 			pkp -> pk_chan[0] -> lcd_template = pk_template (0,
48941591Ssklower 				X25_RESTART_CONFIRM);
49041591Ssklower 			pk_output (pkp -> pk_chan[0]);
49141591Ssklower 		}
49241591Ssklower 		break;
49341591Ssklower 
49441591Ssklower 	/*
49541591Ssklower 	 *  Restart confirmation received. All logical channels are set
49641591Ssklower 	 *  to READY.
49741591Ssklower 	 */
49841591Ssklower 	case RESTART_CONF + READY:
49941591Ssklower 		switch (pkp -> pk_state) {
50041591Ssklower 		case DTE_SENT_RESTART:
50141591Ssklower 			pkp -> pk_state = DTE_READY;
50241591Ssklower 			pk_message (0, pkp -> pk_xcp,
50341591Ssklower 				"Packet level operational");
50441591Ssklower 			break;
50541591Ssklower 
50641591Ssklower 		default:
50741591Ssklower 			/* Restart local procedure error. */
50841591Ssklower 			pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR);
50941591Ssklower 			pkp -> pk_state = DTE_SENT_RESTART;
51041591Ssklower 		}
51141591Ssklower 		break;
51241591Ssklower 
51341591Ssklower 	default:
51441591Ssklower 		if (lcp) {
51545895Ssklower 			pk_procerror (CLEAR, lcp, "unknown packet error", 33);
51641591Ssklower 			pk_message (lcn, pkp -> pk_xcp,
51741591Ssklower 				"\"%s\" unexpected in \"%s\" state",
51841591Ssklower 				pk_name[ptype/MAXSTATES], pk_state[lcdstate]);
51945895Ssklower 		} else
52045573Ssklower 			pk_message (lcn, pkp -> pk_xcp,
52141591Ssklower 				"packet arrived on unassigned lcn");
52241591Ssklower 		break;
52341591Ssklower 	}
524*47268Ssklower 	if (so == 0 && lcp && lcp -> lcd_upper &&
52545895Ssklower 	    (lcdstate == SENT_CALL || lcdstate == DATA_TRANSFER)) {
52645895Ssklower 		if (ptype != DATA && ptype != INTERRUPT)
52745895Ssklower 			MCHTYPE(m, MT_CONTROL);
52845297Ssklower 		lcp -> lcd_upper (lcp, m);
52945895Ssklower 	} else if (ptype != DATA && ptype != INTERRUPT)
53041591Ssklower 		m_freem (m);
53141591Ssklower }
53241591Ssklower 
53341591Ssklower 
53441591Ssklower /*
53541591Ssklower  * This routine handles incoming call packets. It matches the protocol
53641591Ssklower  * field on the Call User Data field (usually the first four bytes) with
53741591Ssklower  * sockets awaiting connections.
53841591Ssklower  */
53941591Ssklower 
54041591Ssklower static
54145895Ssklower incoming_call (pkp, m0)
54245895Ssklower struct mbuf *m0;
54341591Ssklower struct pkcb *pkp;
54441591Ssklower {
54542277Ssklower 	register struct pklcd *lcp = 0, *l;
54641591Ssklower 	register struct sockaddr_x25 *sa;
54741591Ssklower 	register struct x25_calladdr *a;
54842277Ssklower 	register struct socket *so = 0;
54945895Ssklower 	struct x25_packet *xp = mtod(m0, struct x25_packet *);
55041591Ssklower 	struct mbuf *m;
55145895Ssklower 	int len = m0->m_pkthdr.len;
55241591Ssklower 	register int l1, l2;
55341591Ssklower 	char *e, *errstr = "server unavailable";
55445895Ssklower 	octet *u, *facp;
55545573Ssklower 	int lcn = LCN(xp);
55641591Ssklower 
55741591Ssklower 	/* First, copy the data from the incoming call packet to a X25_socket
55841591Ssklower 	   descriptor. */
55941591Ssklower 
56041591Ssklower 	a = (struct x25_calladdr *) &xp -> packet_data;
56141591Ssklower 	l1 = a -> calling_addrlen;
56241591Ssklower 	l2 = a -> called_addrlen;
56345297Ssklower 	if ((m = m_getclr (M_DONTWAIT, MT_SONAME)) == 0)
56441591Ssklower 		return;
56541591Ssklower 	sa = mtod (m, struct sockaddr_x25 *);
56641591Ssklower 	u = (octet *) (a -> address_field + l2 / 2);
56741591Ssklower 	e = sa -> x25_addr;
56841591Ssklower 	if (l2 & 0x01) {
56941591Ssklower 		*e++ = *u++ & 0x0f;
57041591Ssklower 		l1--;
57141591Ssklower 	}
57241591Ssklower 	from_bcd (e, &u, l1);
57341591Ssklower 	if (l1 & 0x01)
57441591Ssklower 		u++;
57541591Ssklower 
57645895Ssklower 	facp = u;
57741591Ssklower 	parse_facilities (u, sa);
57841591Ssklower 	u += *u + 1;
57941591Ssklower 	sa -> x25_udlen = min (16, ((octet *)xp) + len - u);
58041591Ssklower 	if (sa -> x25_udlen < 0)
58141591Ssklower 		sa -> x25_udlen = 0;
58241591Ssklower 	bcopy ((caddr_t)u, sa -> x25_udata, (unsigned)sa -> x25_udlen);
58341591Ssklower 
58441591Ssklower 	/*
58541591Ssklower 	 * Now, loop through the  listen sockets looking for a match on the
58641591Ssklower 	 * PID. That is  the first  four octets  of the user data field.  This
58741591Ssklower 	 * is the closest thing to a port number for X.25 packets. What it
58841591Ssklower 	 * does provide is away of  multiplexing  services at the user level.
58941591Ssklower 	 */
59041591Ssklower 
59141591Ssklower 	for (l = pk_listenhead; l; l = l -> lcd_listen) {
59241591Ssklower 		struct sockaddr_x25 *sxp = l -> lcd_ceaddr;
59341591Ssklower 
59441591Ssklower 		if (bcmp (sxp -> x25_udata, sa -> x25_udata, sxp->x25_udlen))
59541591Ssklower 			continue;
59645165Ssklower 		if (sxp -> x25_net &&
59745165Ssklower 		    sxp -> x25_net != pkp->pk_xc.xc_addr.x25_net)
59841591Ssklower 			continue;
59941591Ssklower 		/*
60041591Ssklower 		 * don't accept incoming collect calls unless
60141591Ssklower 		 * the server sets the reverse charging option.
60241591Ssklower 		 */
60341591Ssklower 		if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 &&
60441591Ssklower 			sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) {
60541591Ssklower 			errstr = "incoming collect call refused";
60641591Ssklower 			break;
60741591Ssklower 		}
60845573Ssklower 		/*
60945573Ssklower 		 * don't accept incoming calls with the D-Bit on
61045573Ssklower 		 * unless the server agrees
61145573Ssklower 		 */
61245573Ssklower 		if (xp -> d_bit && !(sxp -> x25_opts.op_flags & X25_DBIT)) {
61345573Ssklower 			errstr = "incoming D-Bit mismatch";
61445573Ssklower 			break;
61545573Ssklower 		}
61642277Ssklower 		if (l -> lcd_so) {
61745165Ssklower 			if (so = sonewconn (l -> lcd_so, SS_ISCONNECTED))
61842277Ssklower 				    lcp = (struct pklcd *) so -> so_pcb;
61942277Ssklower 		} else
62042277Ssklower 			lcp = pk_attach((struct socket *) 0);
62142277Ssklower 		if (lcp == 0) {
62241591Ssklower 			/*
62341591Ssklower 			 * Insufficient space or too many unaccepted
62441591Ssklower 			 * connections.  Just throw the call away.
62541591Ssklower 			 */
62641591Ssklower 			errstr = "server malfunction";
62741591Ssklower 			break;
62841591Ssklower 		}
62943361Ssklower 		lcp -> lcd_upper = l -> lcd_upper;
63043361Ssklower 		lcp -> lcd_upnext = l -> lcd_upnext;
63141591Ssklower 		lcp -> lcd_lcn = lcn;
63241591Ssklower 		lcp -> lcd_state = RECEIVED_CALL;
63341591Ssklower 		lcp -> lcd_craddr = sa;
63441591Ssklower 		sa -> x25_opts.op_flags |= sxp -> x25_opts.op_flags &
63541591Ssklower 			~X25_REVERSE_CHARGE;
63641591Ssklower 		pk_assoc (pkp, lcp, sa);
63741591Ssklower 		lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED);
63845573Ssklower 		if (lcp -> lcd_flags & X25_DBIT) {
63945573Ssklower 			if (xp -> d_bit)
64045895Ssklower 				mtod(lcp -> lcd_template,
64145895Ssklower 					struct x25_packet *) -> d_bit = 1;
64245573Ssklower 			else
64345573Ssklower 				lcp -> lcd_flags &= ~X25_DBIT;
64445573Ssklower 		}
64543361Ssklower 		if (so) {
64643361Ssklower 			pk_output (lcp);
64742277Ssklower 			soisconnected (so);
64845895Ssklower 			if (so -> so_options & SO_OOBINLINE)
64945895Ssklower 				save_extra(m0, facp, so);
65045895Ssklower 		} else if (lcp -> lcd_upper) {
65145895Ssklower 			m -> m_next = m0;
65245895Ssklower 			(*lcp -> lcd_upper) (lcp, m);
65345895Ssklower 			(void) m_free (m);  /* only m; m0 freed by caller */
65445895Ssklower 		}
65541591Ssklower 		return;
65641591Ssklower 	}
65741591Ssklower 
65841591Ssklower 	/*
65941591Ssklower 	 * If the call fails for whatever reason, we still need to build a
66041591Ssklower 	 * skeleton LCD in order to be able to properly  receive the CLEAR
66141591Ssklower 	 * CONFIRMATION.
66241591Ssklower 	 */
66341591Ssklower #ifdef WATERLOO		/* be explicit */
66441591Ssklower 	if (l == 0 && bcmp(sa->x25_udata, "ean", 3) == 0)
66541591Ssklower 		pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s",
66641591Ssklower 			sa->x25_addr, sa->x25_udata[3] & 0xff, errstr);
66741591Ssklower 	else if (l == 0 && bcmp(sa->x25_udata, "\1\0\0\0", 4) == 0)
66841591Ssklower 		pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s",
66941591Ssklower 			sa->x25_addr, errstr);
67041591Ssklower 	else
67141591Ssklower #endif
67241591Ssklower 	pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s",
67341591Ssklower 		sa -> x25_addr, sa -> x25_udata[0] & 0xff,
67441591Ssklower 		sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff,
67541591Ssklower 		sa -> x25_udata[3] & 0xff, errstr);
67645297Ssklower 	if ((lcp = pk_attach((struct socket *)0)) == 0) {
67745297Ssklower 		(void) m_free (m);
67841591Ssklower 		return;
67941591Ssklower 	}
68041591Ssklower 	lcp -> lcd_lcn = lcn;
68141591Ssklower 	lcp -> lcd_state = RECEIVED_CALL;
68241591Ssklower 	pk_assoc (pkp, lcp, sa);
68345297Ssklower 	(void) m_free (m);
68445895Ssklower 	pk_clear (lcp, 0, 1);
68541591Ssklower }
68641591Ssklower 
68741591Ssklower static
68845895Ssklower save_extra(m0, fp, so)
68945895Ssklower struct mbuf *m0;
69045895Ssklower octet *fp;
69145895Ssklower struct socket *so;
69245895Ssklower {
69345895Ssklower 	register struct mbuf *m;
69445895Ssklower 	struct cmsghdr cmsghdr;
69545895Ssklower 	if (m = m_copym (m, 0, (int)M_COPYALL)) {
69645895Ssklower 		int off = fp - mtod (m0, octet *);
69745895Ssklower 		int len = m->m_pkthdr.len - off + sizeof (cmsghdr);
69845895Ssklower 		cmsghdr.cmsg_len = len;
69945895Ssklower 		cmsghdr.cmsg_level = AF_CCITT;
70045895Ssklower 		cmsghdr.cmsg_type = PK_FACILITIES;
70145895Ssklower 		m_adj (m, off);
70245895Ssklower 		M_PREPEND (m, sizeof(cmsghdr), M_DONTWAIT);
70345895Ssklower 		if (m == 0)
70445895Ssklower 			return;
70545895Ssklower 		bcopy ((caddr_t)&cmsghdr, mtod (m, caddr_t), sizeof (cmsghdr));
70645895Ssklower 		MCHTYPE(m, MT_CONTROL);
70745895Ssklower 		sbappendrecord(&so -> so_rcv, m);
70845895Ssklower 	}
70945895Ssklower }
71045895Ssklower 
71145895Ssklower static
71241591Ssklower call_accepted (lcp, xp, len)
71341591Ssklower struct pklcd *lcp;
71441591Ssklower struct x25_packet *xp;
71541591Ssklower {
71641591Ssklower 	register struct x25_calladdr *ap;
71741591Ssklower 	register octet *fcp;
71841591Ssklower 
71941591Ssklower 	lcp -> lcd_state = DATA_TRANSFER;
72045297Ssklower 	if (lcp -> lcd_so)
72145297Ssklower 		soisconnected (lcp -> lcd_so);
72245573Ssklower 	if ((lcp -> lcd_flags & X25_DBIT) && (xp -> d_bit == 0))
72345573Ssklower 		lcp -> lcd_flags &= ~X25_DBIT;
72441591Ssklower 	if (len > 3) {
72541591Ssklower 		ap = (struct x25_calladdr *) &xp -> packet_data;
72641591Ssklower 		fcp = (octet *) ap -> address_field + (ap -> calling_addrlen +
72741591Ssklower 			ap -> called_addrlen + 1) / 2;
72841591Ssklower 		if (fcp + *fcp <= ((octet *)xp) + len)
72941591Ssklower 			parse_facilities (fcp, lcp -> lcd_ceaddr);
73041591Ssklower 	}
73141591Ssklower 	pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr);
73241591Ssklower }
73341591Ssklower 
73441591Ssklower static
73541591Ssklower parse_facilities (fcp, sa)
73641591Ssklower register octet *fcp;
73741591Ssklower register struct sockaddr_x25 *sa;
73841591Ssklower {
73941591Ssklower 	register octet *maxfcp;
74041591Ssklower 
74141591Ssklower 	maxfcp = fcp + *fcp;
74241591Ssklower 	fcp++;
74341591Ssklower 	while (fcp < maxfcp) {
74441591Ssklower 		/*
74541591Ssklower 		 * Ignore national DCE or DTE facilities
74641591Ssklower 		 */
74741591Ssklower 		if (*fcp == 0 || *fcp == 0xff)
74841591Ssklower 			break;
74941591Ssklower 		switch (*fcp) {
75041591Ssklower 		case FACILITIES_WINDOWSIZE:
75141591Ssklower 			sa -> x25_opts.op_wsize = fcp[1];
75241591Ssklower 			fcp += 3;
75341591Ssklower 			break;
75441591Ssklower 
75541591Ssklower 		case FACILITIES_PACKETSIZE:
75641591Ssklower 			sa -> x25_opts.op_psize = fcp[1];
75741591Ssklower 			fcp += 3;
75841591Ssklower 			break;
75941591Ssklower 
76041591Ssklower 		case FACILITIES_THROUGHPUT:
76141591Ssklower 			sa -> x25_opts.op_speed = fcp[1];
76241591Ssklower 			fcp += 2;
76341591Ssklower 			break;
76441591Ssklower 
76541591Ssklower 		case FACILITIES_REVERSE_CHARGE:
76641591Ssklower 			if (fcp[1] & 01)
76741591Ssklower 				sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE;
76841591Ssklower 			/*
76941591Ssklower 			 * Datapac specific: for a X.25(1976) DTE, bit 2
77041591Ssklower 			 * indicates a "hi priority" (eg. international) call.
77141591Ssklower 			 */
77241591Ssklower 			if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0)
77341591Ssklower 				sa -> x25_opts.op_psize = X25_PS128;
77441591Ssklower 			fcp += 2;
77541591Ssklower 			break;
77641591Ssklower 
77741591Ssklower 		default:
77841591Ssklower /*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/
77941591Ssklower 			switch ((*fcp & 0xc0) >> 6) {
78041591Ssklower 			case 0:			/* class A */
78141591Ssklower 				fcp += 2;
78241591Ssklower 				break;
78341591Ssklower 
78441591Ssklower 			case 1:
78541591Ssklower 				fcp += 3;
78641591Ssklower 				break;
78741591Ssklower 
78841591Ssklower 			case 2:
78941591Ssklower 				fcp += 4;
79041591Ssklower 				break;
79141591Ssklower 
79241591Ssklower 			case 3:
79341591Ssklower 				fcp++;
79441591Ssklower 				fcp += *fcp;
79541591Ssklower 			}
79641591Ssklower 		}
79741591Ssklower 	}
79841591Ssklower }
79941591Ssklower 
80041591Ssklower from_bcd (a, x, len)
80141591Ssklower register char *a;
80241591Ssklower register octet **x;
80341591Ssklower register int len;
80441591Ssklower {
80541591Ssklower 	register int posn = 0;
80641591Ssklower 
80741591Ssklower 	while (--len >= 0) {
80841591Ssklower 		if (posn++ & 0x01)
80941591Ssklower 			*a = *(*x)++ & 0x0f;
81041591Ssklower 		else
81141591Ssklower 			*a = (**x >> 4) & 0x0F;
81241591Ssklower 		*a++ |= 0x30;
81341591Ssklower 	}
81441591Ssklower }
815