xref: /csrg-svn/sys/netccitt/pk_subr.c (revision 56530)
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*56530Sbostic  *	@(#)pk_subr.c	7.22 (Berkeley) 10/11/92
1341709Ssklower  */
1441593Ssklower 
15*56530Sbostic #include <sys/param.h>
16*56530Sbostic #include <sys/systm.h>
17*56530Sbostic #include <sys/mbuf.h>
18*56530Sbostic #include <sys/socket.h>
19*56530Sbostic #include <sys/protosw.h>
20*56530Sbostic #include <sys/socketvar.h>
21*56530Sbostic #include <sys/errno.h>
22*56530Sbostic #include <sys/time.h>
23*56530Sbostic #include <sys/kernel.h>
2441593Ssklower 
25*56530Sbostic #include <net/if.h>
2642277Ssklower 
27*56530Sbostic #include <netccitt/x25.h>
28*56530Sbostic #include <netccitt/pk.h>
29*56530Sbostic #include <netccitt/pk_var.h>
30*56530Sbostic #include <netccitt/x25err.h>
3141593Ssklower 
3241593Ssklower int     pk_sendspace = 1024 * 2 + 8;
3341593Ssklower int     pk_recvspace = 1024 * 2 + 8;
3441593Ssklower 
3547271Ssklower struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q};
3647271Ssklower 
3741593Ssklower /*
3841593Ssklower  *  Attach X.25 protocol to socket, allocate logical channel descripter
3941593Ssklower  *  and buffer space, and enter LISTEN state if we are to accept
4041593Ssklower  *  IN-COMMING CALL packets.
4141593Ssklower  *
4241593Ssklower  */
4341593Ssklower 
4442277Ssklower struct pklcd *
4541593Ssklower pk_attach (so)
4641593Ssklower struct socket *so;
4741593Ssklower {
4841593Ssklower 	register struct pklcd *lcp;
4942277Ssklower 	register int error = ENOBUFS;
5049018Ssklower 	int pk_output();
5141593Ssklower 
5247271Ssklower 	MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
5342277Ssklower 	if (lcp) {
5447271Ssklower 		bzero ((caddr_t)lcp, sizeof (*lcp));
5547271Ssklower 		insque (&lcp -> lcd_q, &pklcd_q);
5649595Ssklower 		lcp -> lcd_state = READY;
5749595Ssklower 		lcp -> lcd_send = pk_output;
5842277Ssklower 		if (so) {
5942277Ssklower 			error = soreserve (so, pk_sendspace, pk_recvspace);
6042277Ssklower 			lcp -> lcd_so = so;
6142277Ssklower 			if (so -> so_options & SO_ACCEPTCONN)
6242277Ssklower 				lcp -> lcd_state = LISTEN;
6343361Ssklower 		} else
6445165Ssklower 			sbreserve (&lcp -> lcd_sb, pk_sendspace);
6542277Ssklower 	}
6642277Ssklower 	if (so) {
6742277Ssklower 		so -> so_pcb = (caddr_t) lcp;
6842277Ssklower 		so -> so_error = error;
6942277Ssklower 	}
7042277Ssklower 	return (lcp);
7141593Ssklower }
7241593Ssklower 
7341593Ssklower /*
7441593Ssklower  *  Disconnect X.25 protocol from socket.
7541593Ssklower  */
7641593Ssklower 
7741593Ssklower pk_disconnect (lcp)
7841593Ssklower register struct pklcd *lcp;
7941593Ssklower {
8041593Ssklower 	register struct socket *so = lcp -> lcd_so;
8141593Ssklower 	register struct pklcd *l, *p;
8241593Ssklower 
8341593Ssklower 	switch (lcp -> lcd_state) {
8441593Ssklower 	case LISTEN:
8541593Ssklower 		for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen);
8641593Ssklower 		if (p == 0) {
8741593Ssklower 			if (l != 0)
8841593Ssklower 				pk_listenhead = l -> lcd_listen;
8941593Ssklower 		}
9041593Ssklower 		else
9141593Ssklower 		if (l != 0)
9241593Ssklower 			p -> lcd_listen = l -> lcd_listen;
9341593Ssklower 		pk_close (lcp);
9441593Ssklower 		break;
9541593Ssklower 
9641593Ssklower 	case READY:
9741593Ssklower 		pk_acct (lcp);
9841593Ssklower 		pk_close (lcp);
9941593Ssklower 		break;
10041593Ssklower 
10141593Ssklower 	case SENT_CLEAR:
10241593Ssklower 	case RECEIVED_CLEAR:
10341593Ssklower 		break;
10441593Ssklower 
10541593Ssklower 	default:
10641593Ssklower 		pk_acct (lcp);
10742140Ssklower 		if (so) {
10842140Ssklower 			soisdisconnecting (so);
10942140Ssklower 			sbflush (&so -> so_rcv);
11042140Ssklower 		}
11145895Ssklower 		pk_clear (lcp, 241, 0); /* Normal Disconnect */
11241593Ssklower 
11341593Ssklower 	}
11441593Ssklower }
11541593Ssklower 
11641593Ssklower /*
11741593Ssklower  *  Close an X.25 Logical Channel. Discard all space held by the
11841593Ssklower  *  connection and internal descriptors. Wake up any sleepers.
11941593Ssklower  */
12041593Ssklower 
12141593Ssklower pk_close (lcp)
12241593Ssklower struct pklcd *lcp;
12341593Ssklower {
12441593Ssklower 	register struct socket *so = lcp -> lcd_so;
12541593Ssklower 
12641593Ssklower 	pk_freelcd (lcp);
12741593Ssklower 
12841593Ssklower 	if (so == NULL)
12941593Ssklower 		return;
13041593Ssklower 
13141593Ssklower 	so -> so_pcb = 0;
13241593Ssklower 	soisdisconnected (so);
13345895Ssklower 	/* sofree (so);	/* gak!!! you can't do that here */
13441593Ssklower }
13541593Ssklower 
13641593Ssklower /*
13741593Ssklower  *  Create a template to be used to send X.25 packets on a logical
13841593Ssklower  *  channel. It allocates an mbuf and fills in a skeletal packet
13941593Ssklower  *  depending on its type. This packet is passed to pk_output where
14041593Ssklower  *  the remainer of the packet is filled in.
14141593Ssklower */
14241593Ssklower 
14345895Ssklower struct mbuf *
14441593Ssklower pk_template (lcn, type)
14541593Ssklower int lcn, type;
14641593Ssklower {
14741593Ssklower 	register struct mbuf *m;
14841593Ssklower 	register struct x25_packet *xp;
14941593Ssklower 
15045297Ssklower 	MGETHDR (m, M_DONTWAIT, MT_HEADER);
15141593Ssklower 	if (m == 0)
15241593Ssklower 		panic ("pk_template");
15341593Ssklower 	m -> m_act = 0;
15441593Ssklower 
15541593Ssklower 	/*
15641593Ssklower 	 * Efficiency hack: leave a four byte gap at the beginning
15741593Ssklower 	 * of the packet level header with the hope that this will
15841593Ssklower 	 * be enough room for the link level to insert its header.
15941593Ssklower 	 */
16045297Ssklower 	m -> m_data += max_linkhdr;
16149595Ssklower 	m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
16241593Ssklower 
16341593Ssklower 	xp = mtod (m, struct x25_packet *);
16441593Ssklower 	*(long *)xp = 0;		/* ugly, but fast */
16541593Ssklower /*	xp -> q_bit = 0;*/
16641593Ssklower 	xp -> fmt_identifier = 1;
16741593Ssklower /*	xp -> lc_group_number = 0;*/
16841593Ssklower 
16945574Ssklower 	SET_LCN(xp, lcn);
17041593Ssklower 	xp -> packet_type = type;
17141593Ssklower 
17245895Ssklower 	return (m);
17341593Ssklower }
17441593Ssklower 
17541593Ssklower /*
17641593Ssklower  *  This routine restarts all the virtual circuits. Actually,
17741593Ssklower  *  the virtual circuits are not "restarted" as such. Instead,
17841593Ssklower  *  any active switched circuit is simply returned to READY
17941593Ssklower  *  state.
18041593Ssklower  */
18141593Ssklower 
18241593Ssklower pk_restart (pkp, restart_cause)
18341593Ssklower register struct pkcb *pkp;
18441593Ssklower int restart_cause;
18541593Ssklower {
18645895Ssklower 	register struct mbuf *m;
18741593Ssklower 	register struct pklcd *lcp;
18841593Ssklower 	register int i;
18941593Ssklower 
19041593Ssklower 	/* Restart all logical channels. */
19145297Ssklower 	if (pkp -> pk_chan == 0)
19242140Ssklower 		return;
19345297Ssklower 	for (i = 1; i <= pkp -> pk_maxlcn; ++i)
19445297Ssklower 		if ((lcp = pkp -> pk_chan[i]) != NULL) {
19545895Ssklower 			if (lcp -> lcd_so) {
19645297Ssklower 				lcp -> lcd_so -> so_error = ENETRESET;
19745895Ssklower 				pk_close (lcp);
19845895Ssklower 			} else {
19945895Ssklower 				pk_flush (lcp);
20045895Ssklower 				lcp -> lcd_state = READY;
20145895Ssklower 				if (lcp -> lcd_upper)
20247271Ssklower 					lcp -> lcd_upper (lcp, 0);
20345895Ssklower 			}
20441593Ssklower 		}
20541593Ssklower 
20641593Ssklower 	if (restart_cause < 0)
20741593Ssklower 		return;
20841593Ssklower 
20945297Ssklower 	pkp -> pk_state = DTE_SENT_RESTART;
21045297Ssklower 	lcp = pkp -> pk_chan[0];
21145895Ssklower 	m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
21249595Ssklower 	m -> m_pkthdr.len = m -> m_len += 2;
21347271Ssklower 	mtod (m, struct x25_packet *) -> packet_data = 0;	/* DTE only */
21447271Ssklower 	mtod (m, octet *)[4]  = restart_cause;
21541593Ssklower 	pk_output (lcp);
21641593Ssklower }
21741593Ssklower 
21841593Ssklower 
21941593Ssklower /*
22041593Ssklower  *  This procedure frees up the Logical Channel Descripter.
22141593Ssklower  */
22241593Ssklower 
22341593Ssklower pk_freelcd (lcp)
22441593Ssklower register struct pklcd *lcp;
22541593Ssklower {
22641593Ssklower 	if (lcp == NULL)
22741593Ssklower 		return;
22841593Ssklower 
22941593Ssklower 	if (lcp -> lcd_lcn > 0)
23041593Ssklower 		lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL;
23141593Ssklower 
23247271Ssklower 	pk_flush (lcp);
23347271Ssklower 	remque (&lcp -> lcd_q);
23447271Ssklower 	free ((caddr_t)lcp, M_PCB);
23541593Ssklower }
23641593Ssklower 
23741593Ssklower 
23841593Ssklower /*
23941593Ssklower  *  Bind a address and protocol value to a socket.  The important
24041593Ssklower  *  part is the protocol value - the first four characters of the
24141593Ssklower  *  Call User Data field.
24241593Ssklower  */
24341593Ssklower 
24441593Ssklower pk_bind (lcp, nam)
24541593Ssklower struct pklcd *lcp;
24641593Ssklower struct mbuf *nam;
24741593Ssklower {
24841593Ssklower 	register struct pkcb *pkp;
24941593Ssklower 	register struct pklcd *pp;
25042277Ssklower 	register struct sockaddr_x25 *sa;
25141593Ssklower 
25241593Ssklower 	if (nam == NULL)
25341593Ssklower 		return (EADDRNOTAVAIL);
25441593Ssklower 	if (lcp -> lcd_ceaddr)				/* XXX */
25541593Ssklower 		return (EADDRINUSE);
25645895Ssklower 	if (pk_checksockaddr (nam))
25741593Ssklower 		return (EINVAL);
25841593Ssklower 	sa = mtod (nam, struct sockaddr_x25 *);
25941593Ssklower 
26041593Ssklower 	/*
26141593Ssklower 	 * If the user wishes to accept calls only from a particular
26241593Ssklower 	 * net (net != 0), make sure the net is known
26341593Ssklower 	 */
26441593Ssklower 
26541593Ssklower 	if (sa -> x25_net)
26641593Ssklower 		for (pkp = pkcbhead; ; pkp = pkp -> pk_next) {
26741593Ssklower 			if (pkp == 0)
26841593Ssklower 				return (ENETUNREACH);
26945165Ssklower 			if (pkp -> pk_xcp -> xc_addr.x25_net == sa -> x25_net)
27041593Ssklower 				break;
27141593Ssklower 		}
27241593Ssklower 
27345895Ssklower 	/*
27445895Ssklower 	 * For ISO's sake permit default listeners, but only one such . . .
27545895Ssklower 	 */
27645895Ssklower 	for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) {
27745895Ssklower 		register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr;
27845895Ssklower 		if ((sa2 -> x25_udlen == sa -> x25_udlen) &&
27945895Ssklower 		    (sa2 -> x25_udlen == 0 ||
28045895Ssklower 		     (bcmp (sa2 -> x25_udata, sa -> x25_udata,
28145895Ssklower 			    min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0)))
28245895Ssklower 				return (EADDRINUSE);
28345895Ssklower 	}
28442277Ssklower 	lcp -> lcd_laddr = *sa;
28542277Ssklower 	lcp -> lcd_ceaddr = &lcp -> lcd_laddr;
28641593Ssklower 	return (0);
28741593Ssklower }
28841593Ssklower 
28941593Ssklower /*
29045895Ssklower  * Include a bound control block in the list of listeners.
29145895Ssklower  */
29245895Ssklower pk_listen (lcp)
29345895Ssklower register struct pklcd *lcp;
29445895Ssklower {
29545895Ssklower 	register struct pklcd **pp;
29645895Ssklower 
29745895Ssklower 	if (lcp -> lcd_ceaddr == 0)
29845895Ssklower 		return (EDESTADDRREQ);
29945895Ssklower 
30045895Ssklower 	lcp -> lcd_state = LISTEN;
30145895Ssklower 	/*
30245895Ssklower 	 * Add default listener at end, any others at start.
30345895Ssklower 	 */
30445895Ssklower 	if (lcp -> lcd_ceaddr -> x25_udlen == 0) {
30545895Ssklower 		for (pp = &pk_listenhead; *pp; )
30645895Ssklower 			pp = &((*pp) -> lcd_listen);
30745895Ssklower 		*pp = lcp;
30845895Ssklower 	} else {
30945895Ssklower 		lcp -> lcd_listen = pk_listenhead;
31045895Ssklower 		pk_listenhead = lcp;
31145895Ssklower 	}
31245895Ssklower 	return (0);
31345895Ssklower }
31445895Ssklower /*
31545895Ssklower  * Include a listening control block for the benefit of other protocols.
31645895Ssklower  */
31745895Ssklower pk_protolisten (spi, spilen, callee)
31847271Ssklower int (*callee) ();
31945895Ssklower {
32045895Ssklower 	register struct pklcd *lcp = pk_attach ((struct socket *)0);
32145895Ssklower 	register struct mbuf *nam;
32245895Ssklower 	register struct sockaddr_x25 *sa;
32345895Ssklower 	int error = ENOBUFS;
32445895Ssklower 
32545895Ssklower 	if (lcp) {
32647271Ssklower 		if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) {
32747271Ssklower 			sa = mtod (nam, struct sockaddr_x25 *);
32845895Ssklower 			sa -> x25_family = AF_CCITT;
32945895Ssklower 			sa -> x25_len = nam -> m_len = sizeof (*sa);
33045895Ssklower 			sa -> x25_udlen = spilen;
33145895Ssklower 			sa -> x25_udata[0] = spi;
33245895Ssklower 			lcp -> lcd_upper = callee;
33345895Ssklower 			lcp -> lcd_flags = X25_MBS_HOLD;
33449929Ssklower 			if ((error = pk_bind (lcp, nam)) == 0)
33549929Ssklower 				error = pk_listen (lcp);
33645895Ssklower 			(void) m_free (nam);
33745895Ssklower 		}
33845895Ssklower 		if (error)
33947271Ssklower 			pk_freelcd (lcp);
34045895Ssklower 	}
34145895Ssklower 	return error; /* Hopefully Zero !*/
34245895Ssklower }
34345895Ssklower 
34445895Ssklower /*
34541593Ssklower  * Associate a logical channel descriptor with a network.
34641593Ssklower  * Fill in the default network specific parameters and then
34741593Ssklower  * set any parameters explicitly specified by the user or
34841593Ssklower  * by the remote DTE.
34941593Ssklower  */
35041593Ssklower 
35141593Ssklower pk_assoc (pkp, lcp, sa)
35241593Ssklower register struct pkcb *pkp;
35341593Ssklower register struct pklcd *lcp;
35441593Ssklower register struct sockaddr_x25 *sa;
35541593Ssklower {
35641593Ssklower 
35741593Ssklower 	lcp -> lcd_pkp = pkp;
35841593Ssklower 	lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize;
35941593Ssklower 	lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize;
36041593Ssklower 	lcp -> lcd_rsn = MODULUS - 1;
36141593Ssklower 	pkp -> pk_chan[lcp -> lcd_lcn] = lcp;
36241593Ssklower 
36341593Ssklower 	if (sa -> x25_opts.op_psize)
36441593Ssklower 		lcp -> lcd_packetsize = sa -> x25_opts.op_psize;
36541593Ssklower 	else
36641593Ssklower 		sa -> x25_opts.op_psize = lcp -> lcd_packetsize;
36741593Ssklower 	if (sa -> x25_opts.op_wsize)
36841593Ssklower 		lcp -> lcd_windowsize = sa -> x25_opts.op_wsize;
36941593Ssklower 	else
37041593Ssklower 		sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
37145165Ssklower 	sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
37250020Ssklower 	lcp -> lcd_flags |= sa -> x25_opts.op_flags;
37341593Ssklower 	lcp -> lcd_stime = time.tv_sec;
37441593Ssklower }
37541593Ssklower 
37645895Ssklower pk_connect (lcp, sa)
37741593Ssklower register struct pklcd *lcp;
37842277Ssklower register struct sockaddr_x25 *sa;
37941593Ssklower {
38041593Ssklower 	register struct pkcb *pkp;
38141593Ssklower 
38241593Ssklower 	if (sa -> x25_addr[0] == '\0')
38341593Ssklower 		return (EDESTADDRREQ);
38445297Ssklower 	if (lcp -> lcd_pkp == 0)
38545297Ssklower 	    for (pkp = pkcbhead; ; pkp = pkp -> pk_next) {
38641593Ssklower 		if (pkp == 0)
38741593Ssklower 			return (ENETUNREACH);
38841593Ssklower 		/*
38941593Ssklower 		 * use first net configured (last in list
39041593Ssklower 		 * headed by pkcbhead) if net is zero
39149929Ssklower 		 *
39249929Ssklower 		 * This is clearly bogus for many llc2's sharing
39349929Ssklower 		 * the same xcp; we will replace this with a
39449929Ssklower 		 * routing lookup.
39541593Ssklower 		 */
39641593Ssklower 		if (sa -> x25_net == 0 && pkp -> pk_next == 0)
39741593Ssklower 			break;
39845165Ssklower 		if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net)
39941593Ssklower 			break;
40041593Ssklower 	}
40141593Ssklower 
40241593Ssklower 	if (pkp -> pk_state != DTE_READY)
40341593Ssklower 		return (ENETDOWN);
40441593Ssklower 	if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0)
40541593Ssklower 		return (EMFILE);
40642277Ssklower 	lcp -> lcd_faddr = *sa;
40745297Ssklower 	lcp -> lcd_ceaddr = & lcp -> lcd_faddr;
40841593Ssklower 	pk_assoc (pkp, lcp, lcp -> lcd_ceaddr);
40945165Ssklower 	if (lcp -> lcd_so)
41042140Ssklower 		soisconnecting (lcp -> lcd_so);
41141593Ssklower 	lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
41242277Ssklower 	pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
41349929Ssklower 	return (*pkp -> pk_ia -> ia_start) (lcp);
41441593Ssklower }
41541593Ssklower 
41649747Ssklower struct bcdinfo {
41749747Ssklower 	octet *cp;
41849747Ssklower 	unsigned posn;
41949747Ssklower };
42041593Ssklower /*
42141593Ssklower  *  Build the rest of the CALL REQUEST packet. Fill in calling
42241593Ssklower  *  address, facilities fields and the user data field.
42341593Ssklower  */
42441593Ssklower 
42542277Ssklower pk_callrequest (lcp, sa, xcp)
42641593Ssklower struct pklcd *lcp;
42742277Ssklower register struct sockaddr_x25 *sa;
42841593Ssklower register struct x25config *xcp;
42941593Ssklower {
43041593Ssklower 	register struct x25_calladdr *a;
43145895Ssklower 	register struct mbuf *m = lcp -> lcd_template;
43247271Ssklower 	register struct x25_packet *xp = mtod (m, struct x25_packet *);
43349747Ssklower 	struct bcdinfo b;
43441593Ssklower 
43545574Ssklower 	if (lcp -> lcd_flags & X25_DBIT)
43645895Ssklower 		xp -> d_bit = 1;
43745895Ssklower 	a = (struct x25_calladdr *) &xp -> packet_data;
43849747Ssklower 	b.cp = (octet *) a -> address_field;
43949747Ssklower 	b.posn = 0;
44049747Ssklower 	a -> called_addrlen = to_bcd (&b, sa, xcp);
44149747Ssklower 	a -> calling_addrlen = to_bcd (&b, &xcp -> xc_addr, xcp);
44249747Ssklower 	if (b.posn & 0x01)
44349747Ssklower 		*b.cp++ &= 0xf0;
44449747Ssklower 	m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
44541593Ssklower 
44645895Ssklower 	if (lcp -> lcd_facilities) {
44747271Ssklower 		m -> m_pkthdr.len +=
44849747Ssklower 			(m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
44945895Ssklower 		lcp -> lcd_facilities = 0;
45045895Ssklower 	} else
45149747Ssklower 		pk_build_facilities (m, sa, (int)xcp -> xc_type);
45241593Ssklower 
45347271Ssklower 	m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
45441593Ssklower }
45541593Ssklower 
45649747Ssklower pk_build_facilities (m, sa, type)
45745895Ssklower register struct mbuf *m;
45841593Ssklower struct sockaddr_x25 *sa;
45941593Ssklower {
46045895Ssklower 	register octet *cp;
46141593Ssklower 	register octet *fcp;
46241593Ssklower 	register int revcharge;
46341593Ssklower 
46447271Ssklower 	cp = mtod (m, octet *) + m -> m_len;
46545895Ssklower 	fcp = cp + 1;
46641593Ssklower 	revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
46741593Ssklower 	/*
46841593Ssklower 	 * This is specific to Datapac X.25(1976) DTEs.  International
46941593Ssklower 	 * calls must have the "hi priority" bit on.
47041593Ssklower 	 */
47141593Ssklower 	if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)
47241593Ssklower 		revcharge |= 02;
47341593Ssklower 	if (revcharge) {
47441593Ssklower 		*fcp++ = FACILITIES_REVERSE_CHARGE;
47541593Ssklower 		*fcp++ = revcharge;
47641593Ssklower 	}
47741593Ssklower 	switch (type) {
47841593Ssklower 	case X25_1980:
47941593Ssklower 	case X25_1984:
48041593Ssklower 		*fcp++ = FACILITIES_PACKETSIZE;
48141593Ssklower 		*fcp++ = sa -> x25_opts.op_psize;
48241593Ssklower 		*fcp++ = sa -> x25_opts.op_psize;
48341593Ssklower 
48441593Ssklower 		*fcp++ = FACILITIES_WINDOWSIZE;
48541593Ssklower 		*fcp++ = sa -> x25_opts.op_wsize;
48641593Ssklower 		*fcp++ = sa -> x25_opts.op_wsize;
48741593Ssklower 	}
48845895Ssklower 	*cp = fcp - cp - 1;
48945895Ssklower 	m -> m_pkthdr.len = (m -> m_len += *cp + 1);
49041593Ssklower }
49141593Ssklower 
49249747Ssklower to_bcd (b, sa, xcp)
49349747Ssklower register struct bcdinfo *b;
49449747Ssklower struct sockaddr_x25 *sa;
49549747Ssklower register struct x25config *xcp;
49641593Ssklower {
49749747Ssklower 	register char *x = sa -> x25_addr;
49849747Ssklower 	unsigned start = b -> posn;
49949747Ssklower 	/*
50049747Ssklower 	 * The nodnic and prepnd0 stuff looks tedious,
50149747Ssklower 	 * but it does allow full X.121 addresses to be used,
50249747Ssklower 	 * which is handy for routing info (& OSI type 37 addresses).
50349747Ssklower 	 */
50449747Ssklower 	if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
50549747Ssklower 		char dnicname[sizeof(long) * NBBY/3 + 2];
50649747Ssklower 		register char *p = dnicname;
50749747Ssklower 
50849747Ssklower 		sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
50949747Ssklower 		for (; *p; p++) /* *p == 0 means dnic matched */
51049747Ssklower 			if ((*p ^ *x++) & 0x0f)
51149747Ssklower 				break;
51249747Ssklower 		if (*p || xcp -> xc_nodnic == 0)
51349747Ssklower 			x = sa -> x25_addr;
51449747Ssklower 		if (*p && xcp -> xc_prepnd0) {
51549747Ssklower 			if ((b -> posn)++ & 0x01)
51649747Ssklower 				*(b -> cp)++;
51749747Ssklower 			else
51849747Ssklower 				*(b -> cp) = 0;
51949747Ssklower 		}
52049747Ssklower 	}
52149747Ssklower 	while (*x)
52249747Ssklower 		if ((b -> posn)++ & 0x01)
52349747Ssklower 			*(b -> cp)++ |= *x++ & 0x0F;
52441593Ssklower 		else
52549747Ssklower 			*(b -> cp) = *x++ << 4;
52649747Ssklower 	return ((b -> posn) - start);
52741593Ssklower }
52841593Ssklower 
52941593Ssklower /*
53041593Ssklower  *  This routine gets the  first available logical channel number.  The
53141593Ssklower  *  search is from the highest number to lowest number (DTE).
53241593Ssklower  */
53341593Ssklower 
53441593Ssklower pk_getlcn (pkp)
53541593Ssklower register struct pkcb *pkp;
53641593Ssklower {
53741593Ssklower 	register int i;
53841593Ssklower 
53945297Ssklower 	if (pkp -> pk_chan == 0)
54042140Ssklower 		return (0);
54141593Ssklower 	for (i = pkp -> pk_maxlcn; i > 0; --i)
54241593Ssklower 		if (pkp -> pk_chan[i] == NULL)
54341593Ssklower 			break;
54441593Ssklower 	return (i);
54541593Ssklower 
54641593Ssklower }
54741593Ssklower 
54841593Ssklower /*
54941593Ssklower  *  This procedure sends a CLEAR request packet. The lc state is
55041593Ssklower  *  set to "SENT_CLEAR".
55141593Ssklower  */
55241593Ssklower 
55345895Ssklower pk_clear (lcp, diagnostic, abortive)
55445895Ssklower register struct pklcd *lcp;
55541593Ssklower {
55645895Ssklower 	register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);
55741593Ssklower 
55845895Ssklower 	m -> m_len += 2;
55951739Ssklower 	m -> m_pkthdr.len += 2;
56047271Ssklower 	mtod (m, struct x25_packet *) -> packet_data = 0;
56147271Ssklower 	mtod (m, octet *)[4] = diagnostic;
56245895Ssklower 	if (lcp -> lcd_facilities) {
56345895Ssklower 		m -> m_next = lcp -> lcd_facilities;
56445895Ssklower 		m -> m_pkthdr.len += m -> m_next -> m_len;
56545895Ssklower 		lcp -> lcd_facilities = 0;
56645895Ssklower 	}
56745895Ssklower 	if (abortive)
56845895Ssklower 		lcp -> lcd_template = m;
56945895Ssklower 	else {
57045895Ssklower 		struct socket *so = lcp -> lcd_so;
57145895Ssklower 		struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;
57247271Ssklower 		sbappendrecord (sb, m);
57345895Ssklower 	}
57441593Ssklower 	pk_output (lcp);
57541593Ssklower 
57641593Ssklower }
57741593Ssklower 
57847271Ssklower /*
57947271Ssklower  * This procedure generates RNR's or RR's to inhibit or enable
58047271Ssklower  * inward data flow, if the current state changes (blocked ==> open or
58147271Ssklower  * vice versa), or if forced to generate one.  One forces RNR's to ack data.
58247271Ssklower  */
58347271Ssklower pk_flowcontrol (lcp, inhibit, forced)
58447271Ssklower register struct pklcd *lcp;
58547271Ssklower {
58647271Ssklower 	inhibit = (inhibit != 0);
58747271Ssklower 	if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||
58847271Ssklower 	    (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
58947271Ssklower 		return;
59047271Ssklower 	lcp -> lcd_rxrnr_condition = inhibit;
59149929Ssklower 	lcp -> lcd_template =
59249929Ssklower 		pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
59347271Ssklower 	pk_output (lcp);
59447271Ssklower }
59547271Ssklower 
59641593Ssklower /*
59747271Ssklower  *  This procedure sends a RESET request packet. It re-intializes
59841593Ssklower  *  virtual circuit.
59941593Ssklower  */
60041593Ssklower 
60141593Ssklower static
60245895Ssklower pk_reset (lcp, diagnostic)
60341593Ssklower register struct pklcd *lcp;
60441593Ssklower {
60545895Ssklower 	register struct mbuf *m;
60645895Ssklower 	register struct socket *so = lcp -> lcd_so;
60741593Ssklower 
60841593Ssklower 	if (lcp -> lcd_state != DATA_TRANSFER)
60941593Ssklower 		return;
61041593Ssklower 
61145895Ssklower 	if (so)
61245895Ssklower 		so -> so_error = ECONNRESET;
61341593Ssklower 	lcp -> lcd_reset_condition = TRUE;
61441593Ssklower 
61541593Ssklower 	/* Reset all the control variables for the channel. */
61645895Ssklower 	pk_flush (lcp);
61741593Ssklower 	lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
61841593Ssklower 		lcp -> lcd_intrconf_pending = FALSE;
61941593Ssklower 	lcp -> lcd_rsn = MODULUS - 1;
62041593Ssklower 	lcp -> lcd_ssn = 0;
62141593Ssklower 	lcp -> lcd_output_window = lcp -> lcd_input_window =
62241593Ssklower 		lcp -> lcd_last_transmitted_pr = 0;
62345895Ssklower 	m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
62449595Ssklower 	m -> m_pkthdr.len = m -> m_len += 2;
62547271Ssklower 	mtod (m, struct x25_packet *) -> packet_data = 0;
62647271Ssklower 	mtod (m, octet *)[4] = diagnostic;
62745895Ssklower 	pk_output (lcp);
62845895Ssklower 
62945895Ssklower }
63045895Ssklower 
63145895Ssklower /*
63245895Ssklower  * This procedure frees all data queued for output or delivery on a
63345895Ssklower  *  virtual circuit.
63445895Ssklower  */
63545895Ssklower 
63645895Ssklower pk_flush (lcp)
63745895Ssklower register struct pklcd *lcp;
63845895Ssklower {
63945895Ssklower 	register struct socket *so;
64045895Ssklower 
64145895Ssklower 	if (lcp -> lcd_template)
64245895Ssklower 		m_freem (lcp -> lcd_template);
64345895Ssklower 
64445895Ssklower 	if (lcp -> lcd_cps) {
64547271Ssklower 		m_freem (lcp -> lcd_cps);
64645895Ssklower 		lcp -> lcd_cps = 0;
64745895Ssklower 	}
64847271Ssklower 	if (lcp -> lcd_facilities) {
64947271Ssklower 		m_freem (lcp -> lcd_facilities);
65047271Ssklower 		lcp -> lcd_facilities = 0;
65147271Ssklower 	}
65247271Ssklower 	if (so = lcp -> lcd_so) {
65342140Ssklower 		sbflush (&so -> so_snd);
65445895Ssklower 	} else
65545895Ssklower 		sbflush (&lcp -> lcd_sb);
65641593Ssklower }
65741593Ssklower 
65841593Ssklower /*
65941593Ssklower  *  This procedure handles all local protocol procedure errors.
66041593Ssklower  */
66141593Ssklower 
66245895Ssklower pk_procerror (error, lcp, errstr, diagnostic)
66341593Ssklower register struct pklcd *lcp;
66441593Ssklower char *errstr;
66541593Ssklower {
66641593Ssklower 
66741593Ssklower 	pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);
66841593Ssklower 
66941593Ssklower 	switch (error) {
67041593Ssklower 	case CLEAR:
67145297Ssklower 		if (lcp -> lcd_so) {
67245297Ssklower 			lcp -> lcd_so -> so_error = ECONNABORTED;
67345297Ssklower 			soisdisconnecting (lcp -> lcd_so);
67441593Ssklower 		}
67545895Ssklower 		pk_clear (lcp, diagnostic, 1);
67641593Ssklower 		break;
67741593Ssklower 
67841593Ssklower 	case RESET:
67945895Ssklower 		pk_reset (lcp, diagnostic);
68041593Ssklower 	}
68141593Ssklower }
68241593Ssklower 
68341593Ssklower /*
68441593Ssklower  *  This procedure is called during the DATA TRANSFER state to check
68541593Ssklower  *  and  process  the P(R) values  received  in the DATA,  RR OR RNR
68641593Ssklower  *  packets.
68741593Ssklower  */
68841593Ssklower 
68941593Ssklower pk_ack (lcp, pr)
69041593Ssklower struct pklcd *lcp;
69141593Ssklower unsigned pr;
69241593Ssklower {
69341593Ssklower 	register struct socket *so = lcp -> lcd_so;
69441593Ssklower 
69541593Ssklower 	if (lcp -> lcd_output_window == pr)
69641593Ssklower 		return (PACKET_OK);
69741593Ssklower 	if (lcp -> lcd_output_window < lcp -> lcd_ssn) {
69841593Ssklower 		if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {
69945895Ssklower 			pk_procerror (RESET, lcp,
70045895Ssklower 				"p(r) flow control error", 2);
70141593Ssklower 			return (ERROR_PACKET);
70241593Ssklower 		}
70341593Ssklower 	}
70441593Ssklower 	else {
70541593Ssklower 		if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {
70645895Ssklower 			pk_procerror (RESET, lcp,
70747271Ssklower 				"p(r) flow control error #2", 2);
70841593Ssklower 			return (ERROR_PACKET);
70941593Ssklower 		}
71041593Ssklower 	}
71141593Ssklower 
71241593Ssklower 	lcp -> lcd_output_window = pr;		/* Rotate window. */
71341593Ssklower 	if (lcp -> lcd_window_condition == TRUE)
71441593Ssklower 		lcp -> lcd_window_condition = FALSE;
71541593Ssklower 
71653744Ssklower 	if (so && (so -> so_snd.sb_flags & SB_NOTIFY))
71741593Ssklower 		sowwakeup (so);
71841593Ssklower 
71941593Ssklower 	return (PACKET_OK);
72041593Ssklower }
72141593Ssklower 
72241593Ssklower /*
72341593Ssklower  *  This procedure decodes the X.25 level 3 packet returning a
72441593Ssklower  *  code to be used in switchs or arrays.
72541593Ssklower  */
72641593Ssklower 
72741593Ssklower pk_decode (xp)
72841593Ssklower register struct x25_packet *xp;
72941593Ssklower {
73041593Ssklower 	register int type;
73141593Ssklower 
73241593Ssklower 	if (xp -> fmt_identifier != 1)
73341593Ssklower 		return (INVALID_PACKET);
73445895Ssklower #ifdef ancient_history
73541593Ssklower 	/*
73641593Ssklower 	 *  Make sure that the logical channel group number is 0.
73741593Ssklower 	 *  This restriction may be removed at some later date.
73841593Ssklower 	 */
73941593Ssklower 	if (xp -> lc_group_number != 0)
74041593Ssklower 		return (INVALID_PACKET);
74145895Ssklower #endif
74241593Ssklower 	/*
74341593Ssklower 	 *  Test for data packet first.
74441593Ssklower 	 */
74541593Ssklower 	if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))
74641593Ssklower 		return (DATA);
74741593Ssklower 
74841593Ssklower 	/*
74941593Ssklower 	 *  Test if flow control packet (RR or RNR).
75041593Ssklower 	 */
75141593Ssklower 	if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))
75247271Ssklower 		switch (xp -> packet_type & 0x1f) {
75347271Ssklower 		case X25_RR:
75441593Ssklower 			return (RR);
75547271Ssklower 		case X25_RNR:
75641593Ssklower 			return (RNR);
75747271Ssklower 		case X25_REJECT:
75847271Ssklower 			return (REJECT);
75947271Ssklower 		}
76041593Ssklower 
76141593Ssklower 	/*
76241593Ssklower 	 *  Determine the rest of the packet types.
76341593Ssklower 	 */
76441593Ssklower 	switch (xp -> packet_type) {
76541593Ssklower 	case X25_CALL:
76641593Ssklower 		type = CALL;
76741593Ssklower 		break;
76841593Ssklower 
76941593Ssklower 	case X25_CALL_ACCEPTED:
77041593Ssklower 		type = CALL_ACCEPTED;
77141593Ssklower 		break;
77241593Ssklower 
77341593Ssklower 	case X25_CLEAR:
77441593Ssklower 		type = CLEAR;
77541593Ssklower 		break;
77641593Ssklower 
77741593Ssklower 	case X25_CLEAR_CONFIRM:
77841593Ssklower 		type = CLEAR_CONF;
77941593Ssklower 		break;
78041593Ssklower 
78141593Ssklower 	case X25_INTERRUPT:
78241593Ssklower 		type = INTERRUPT;
78341593Ssklower 		break;
78441593Ssklower 
78541593Ssklower 	case X25_INTERRUPT_CONFIRM:
78641593Ssklower 		type = INTERRUPT_CONF;
78741593Ssklower 		break;
78841593Ssklower 
78941593Ssklower 	case X25_RESET:
79041593Ssklower 		type = RESET;
79141593Ssklower 		break;
79241593Ssklower 
79341593Ssklower 	case X25_RESET_CONFIRM:
79441593Ssklower 		type = RESET_CONF;
79541593Ssklower 		break;
79641593Ssklower 
79741593Ssklower 	case X25_RESTART:
79841593Ssklower 		type = RESTART;
79941593Ssklower 		break;
80041593Ssklower 
80141593Ssklower 	case X25_RESTART_CONFIRM:
80241593Ssklower 		type = RESTART_CONF;
80341593Ssklower 		break;
80441593Ssklower 
80547271Ssklower 	case X25_DIAGNOSTIC:
80648873Ssklower 		type = DIAG_TYPE;
80747271Ssklower 		break;
80847271Ssklower 
80941593Ssklower 	default:
81041593Ssklower 		type = INVALID_PACKET;
81141593Ssklower 	}
81241593Ssklower 	return (type);
81341593Ssklower }
81441593Ssklower 
81541593Ssklower /*
81641593Ssklower  *  A restart packet has been received. Print out the reason
81741593Ssklower  *  for the restart.
81841593Ssklower  */
81941593Ssklower 
82041593Ssklower pk_restartcause (pkp, xp)
82141593Ssklower struct pkcb *pkp;
82241593Ssklower register struct x25_packet *xp;
82341593Ssklower {
82441593Ssklower 	register struct x25config *xcp = pkp -> pk_xcp;
82545574Ssklower 	register int lcn = LCN(xp);
82641593Ssklower 
82741593Ssklower 	switch (xp -> packet_data) {
82841593Ssklower 	case X25_RESTART_LOCAL_PROCEDURE_ERROR:
82941593Ssklower 		pk_message (lcn, xcp, "restart: local procedure error");
83041593Ssklower 		break;
83141593Ssklower 
83241593Ssklower 	case X25_RESTART_NETWORK_CONGESTION:
83341593Ssklower 		pk_message (lcn, xcp, "restart: network congestion");
83441593Ssklower 		break;
83541593Ssklower 
83641593Ssklower 	case X25_RESTART_NETWORK_OPERATIONAL:
83741593Ssklower 		pk_message (lcn, xcp, "restart: network operational");
83841593Ssklower 		break;
83941593Ssklower 
84041593Ssklower 	default:
84141593Ssklower 		pk_message (lcn, xcp, "restart: unknown cause");
84241593Ssklower 	}
84341593Ssklower }
84441593Ssklower 
84541593Ssklower #define MAXRESETCAUSE	7
84641593Ssklower 
84741593Ssklower int     Reset_cause[] = {
84841593Ssklower 	EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG
84941593Ssklower };
85041593Ssklower 
85141593Ssklower /*
85241593Ssklower  *  A reset packet has arrived. Return the cause to the user.
85341593Ssklower  */
85441593Ssklower 
85541593Ssklower pk_resetcause (pkp, xp)
85641593Ssklower struct pkcb *pkp;
85741593Ssklower register struct x25_packet *xp;
85841593Ssklower {
85945297Ssklower 	register struct pklcd *lcp =
86045574Ssklower 				pkp -> pk_chan[LCN(xp)];
86141593Ssklower 	register int code = xp -> packet_data;
86241593Ssklower 
86341593Ssklower 	if (code > MAXRESETCAUSE)
86441593Ssklower 		code = 7;	/* EXRNCG */
86541593Ssklower 
86647271Ssklower 	pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
86747271Ssklower 			xp -> packet_data, 4[(u_char *)xp]);
86847271Ssklower 
86949929Ssklower 	if (lcp -> lcd_so)
87049929Ssklower 		lcp -> lcd_so -> so_error = Reset_cause[code];
87141593Ssklower }
87241593Ssklower 
87341593Ssklower #define MAXCLEARCAUSE	25
87441593Ssklower 
87541593Ssklower int     Clear_cause[] = {
87641593Ssklower 	EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,
87741593Ssklower 	0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,
87841593Ssklower 	0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC
87941593Ssklower };
88041593Ssklower 
88141593Ssklower /*
88241593Ssklower  *  A clear packet has arrived. Return the cause to the user.
88341593Ssklower  */
88441593Ssklower 
88541593Ssklower pk_clearcause (pkp, xp)
88641593Ssklower struct pkcb *pkp;
88741593Ssklower register struct x25_packet *xp;
88841593Ssklower {
88945297Ssklower 	register struct pklcd *lcp =
89045574Ssklower 		pkp -> pk_chan[LCN(xp)];
89141593Ssklower 	register int code = xp -> packet_data;
89241593Ssklower 
89341593Ssklower 	if (code > MAXCLEARCAUSE)
89441593Ssklower 		code = 5;	/* EXRNCG */
89549595Ssklower 	if (lcp -> lcd_so)
89649595Ssklower 		lcp -> lcd_so -> so_error = Clear_cause[code];
89741593Ssklower }
89841593Ssklower 
89941593Ssklower char *
90041593Ssklower format_ntn (xcp)
90141593Ssklower register struct x25config *xcp;
90241593Ssklower {
90341593Ssklower 
90445165Ssklower 	return (xcp -> xc_addr.x25_addr);
90541593Ssklower }
90641593Ssklower 
90741593Ssklower /* VARARGS1 */
90841593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)
90941593Ssklower struct x25config *xcp;
91041593Ssklower char *fmt;
91141593Ssklower {
91241593Ssklower 
91341593Ssklower 	if (lcn)
91441593Ssklower 		if (pkcbhead -> pk_next)
91541593Ssklower 			printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);
91641593Ssklower 		else
91741593Ssklower 			printf ("X.25: lcn %d: ", lcn);
91841593Ssklower 	else
91941593Ssklower 		if (pkcbhead -> pk_next)
92041593Ssklower 			printf ("X.25(%s): ", format_ntn (xcp));
92141593Ssklower 		else
92241593Ssklower 			printf ("X.25: ");
92341593Ssklower 
92441593Ssklower 	printf (fmt, a1, a2, a3, a4, a5, a6);
92541593Ssklower 	printf ("\n");
92641593Ssklower }
92745297Ssklower 
92847271Ssklower pk_fragment (lcp, m0, qbit, mbit, wait)
92945297Ssklower struct mbuf *m0;
93045297Ssklower register struct pklcd *lcp;
93145297Ssklower {
93245297Ssklower 	register struct mbuf *m = m0;
93345297Ssklower 	register struct x25_packet *xp;
93445297Ssklower 	register struct sockbuf *sb;
93547271Ssklower 	struct mbuf *head = 0, *next, **mp = &head, *m_split ();
93645297Ssklower 	int totlen, psize = 1 << (lcp -> lcd_packetsize);
93745297Ssklower 
93845297Ssklower 	if (m == 0)
93949595Ssklower 		return 0;
94052433Ssklower 	if ((m -> m_flags & M_PKTHDR) == 0)
94147271Ssklower 		panic ("pk_fragment");
94245297Ssklower 	totlen = m -> m_pkthdr.len;
94345574Ssklower 	m -> m_act = 0;
94445297Ssklower 	sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;
94545297Ssklower 	do {
94645297Ssklower 		if (totlen > psize) {
94747271Ssklower 			if ((next = m_split (m, psize, wait)) == 0)
94845297Ssklower 				goto abort;
94945297Ssklower 			totlen -= psize;
95045574Ssklower 		} else
95145574Ssklower 			next = 0;
95245297Ssklower 		M_PREPEND(m, PKHEADERLN, wait);
95345297Ssklower 		if (m == 0)
95445297Ssklower 			goto abort;
95545574Ssklower 		*mp = m;
95645574Ssklower 		mp = & m -> m_act;
95745574Ssklower 		*mp = 0;
95847271Ssklower 		xp = mtod (m, struct x25_packet *);
95945297Ssklower 		0[(char *)xp] = 0;
96045297Ssklower 		if (qbit)
96145574Ssklower 			xp -> q_bit = 1;
96245574Ssklower 		if (lcp -> lcd_flags & X25_DBIT)
96345574Ssklower 			xp -> d_bit = 1;
96445297Ssklower 		xp -> fmt_identifier = 1;
96545297Ssklower 		xp -> packet_type = X25_DATA;
96645574Ssklower 		SET_LCN(xp, lcp -> lcd_lcn);
96745574Ssklower 		if (next || (mbit && (totlen == psize ||
96845574Ssklower 				      (lcp -> lcd_flags & X25_DBIT))))
96945297Ssklower 			MBIT(xp) = 1;
97045297Ssklower 	} while (m = next);
97145574Ssklower 	for (m = head; m; m = next) {
97245297Ssklower 		next = m -> m_act;
97345297Ssklower 		m -> m_act = 0;
97447271Ssklower 		sbappendrecord (sb, m);
97545297Ssklower 	}
97645297Ssklower 	return 0;
97745297Ssklower abort:
97845574Ssklower 	if (wait)
97947271Ssklower 		panic ("pk_fragment null mbuf after wait");
98045574Ssklower 	if (next)
98147271Ssklower 		m_freem (next);
98245574Ssklower 	for (m = head; m; m = next) {
98345297Ssklower 		next = m -> m_act;
98447271Ssklower 		m_freem (m);
98545297Ssklower 	}
98645297Ssklower 	return ENOBUFS;
98745297Ssklower }
988