xref: /original-bsd/sys/netccitt/pk_subr.c (revision dc4562f1)
1 /*
2  * Copyright (c) University of British Columbia, 1984
3  * Copyright (C) Computer Science Department IV,
4  * 		 University of Erlangen-Nuremberg, Germany, 1992
5  * Copyright (c) 1991, 1992  The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by the
9  * Laboratory for Computation Vision and the Computer Science Department
10  * of the the University of British Columbia and the Computer Science
11  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
12  *
13  * %sccs.include.redist.c%
14  *
15  *	@(#)pk_subr.c	7.24 (Berkeley) 12/08/92
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/mbuf.h>
21 #include <sys/socket.h>
22 #include <sys/protosw.h>
23 #include <sys/socketvar.h>
24 #include <sys/errno.h>
25 #include <sys/time.h>
26 #include <sys/kernel.h>
27 
28 #include <net/if.h>
29 #include <net/route.h>
30 
31 #include <netccitt/dll.h>
32 #include <netccitt/x25.h>
33 #include <netccitt/x25err.h>
34 #include <netccitt/pk.h>
35 #include <netccitt/pk_var.h>
36 
37 int     pk_sendspace = 1024 * 2 + 8;
38 int     pk_recvspace = 1024 * 2 + 8;
39 
40 struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q};
41 
42 struct x25bitslice x25_bitslice[] = {
43 /*	  mask, shift value */
44 	{ 0xf0, 0x4 },
45 	{ 0xf,  0x0 },
46 	{ 0x80, 0x7 },
47 	{ 0x40, 0x6 },
48 	{ 0x30, 0x4 },
49 	{ 0xe0, 0x5 },
50 	{ 0x10, 0x4 },
51 	{ 0xe,  0x1 },
52 	{ 0x1,  0x0 }
53 };
54 
55 
56 /*
57  *  Attach X.25 protocol to socket, allocate logical channel descripter
58  *  and buffer space, and enter LISTEN state if we are to accept
59  *  IN-COMMING CALL packets.
60  *
61  */
62 
63 struct pklcd *
64 pk_attach (so)
65 struct socket *so;
66 {
67 	register struct pklcd *lcp;
68 	register int error = ENOBUFS;
69 	int pk_output();
70 
71 	MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
72 	if (lcp) {
73 		bzero ((caddr_t)lcp, sizeof (*lcp));
74 		insque (&lcp -> lcd_q, &pklcd_q);
75 		lcp -> lcd_state = READY;
76 		lcp -> lcd_send = pk_output;
77 		if (so) {
78 			error = soreserve (so, pk_sendspace, pk_recvspace);
79 			lcp -> lcd_so = so;
80 			if (so -> so_options & SO_ACCEPTCONN)
81 				lcp -> lcd_state = LISTEN;
82 		} else
83 			sbreserve (&lcp -> lcd_sb, pk_sendspace);
84 	}
85 	if (so) {
86 		so -> so_pcb = (caddr_t) lcp;
87 		so -> so_error = error;
88 	}
89 	return (lcp);
90 }
91 
92 /*
93  *  Disconnect X.25 protocol from socket.
94  */
95 
96 pk_disconnect (lcp)
97 register struct pklcd *lcp;
98 {
99 	register struct socket *so = lcp -> lcd_so;
100 	register struct pklcd *l, *p;
101 
102 	switch (lcp -> lcd_state) {
103 	case LISTEN:
104 		for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen);
105 		if (p == 0) {
106 			if (l != 0)
107 				pk_listenhead = l -> lcd_listen;
108 		}
109 		else
110 		if (l != 0)
111 			p -> lcd_listen = l -> lcd_listen;
112 		pk_close (lcp);
113 		break;
114 
115 	case READY:
116 		pk_acct (lcp);
117 		pk_close (lcp);
118 		break;
119 
120 	case SENT_CLEAR:
121 	case RECEIVED_CLEAR:
122 		break;
123 
124 	default:
125 		pk_acct (lcp);
126 		if (so) {
127 			soisdisconnecting (so);
128 			sbflush (&so -> so_rcv);
129 		}
130 		pk_clear (lcp, 241, 0); /* Normal Disconnect */
131 
132 	}
133 }
134 
135 /*
136  *  Close an X.25 Logical Channel. Discard all space held by the
137  *  connection and internal descriptors. Wake up any sleepers.
138  */
139 
140 pk_close (lcp)
141 struct pklcd *lcp;
142 {
143 	register struct socket *so = lcp -> lcd_so;
144 
145 	/*
146 	 * If the X.25 connection is torn down due to link
147 	 * level failure (e.g. LLC2 FRMR) and at the same the user
148 	 * level is still filling up the socket send buffer that
149 	 * send buffer is locked. An attempt to sbflush() that send
150 	 * buffer will lead us into - no, not temptation but - panic!
151 	 * So - we'll just check wether the send buffer is locked
152 	 * and if that's the case we'll mark the lcp as zombie and
153 	 * have the pk_timer() do the cleaning ...
154 	 */
155 
156 	if (so && so -> so_snd.sb_flags & SB_LOCK)
157 		lcp -> lcd_state = LCN_ZOMBIE;
158 	else
159 		pk_freelcd (lcp);
160 
161 	if (so == NULL)
162 		return;
163 
164 	so -> so_pcb = 0;
165 	soisdisconnected (so);
166 	/* sofree (so);	/* gak!!! you can't do that here */
167 }
168 
169 /*
170  *  Create a template to be used to send X.25 packets on a logical
171  *  channel. It allocates an mbuf and fills in a skeletal packet
172  *  depending on its type. This packet is passed to pk_output where
173  *  the remainer of the packet is filled in.
174 */
175 
176 struct mbuf *
177 pk_template (lcn, type)
178 int lcn, type;
179 {
180 	register struct mbuf *m;
181 	register struct x25_packet *xp;
182 
183 	MGETHDR (m, M_DONTWAIT, MT_HEADER);
184 	if (m == 0)
185 		panic ("pk_template");
186 	m -> m_act = 0;
187 
188 	/*
189 	 * Efficiency hack: leave a four byte gap at the beginning
190 	 * of the packet level header with the hope that this will
191 	 * be enough room for the link level to insert its header.
192 	 */
193 	m -> m_data += max_linkhdr;
194 	m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
195 
196 	xp = mtod (m, struct x25_packet *);
197 	*(long *)xp = 0;		/* ugly, but fast */
198 /*	xp -> q_bit = 0;*/
199 	X25SBITS(xp -> bits, fmt_identifier, 1);
200 /*	xp -> lc_group_number = 0;*/
201 
202 	SET_LCN(xp, lcn);
203 	xp -> packet_type = type;
204 
205 	return (m);
206 }
207 
208 /*
209  *  This routine restarts all the virtual circuits. Actually,
210  *  the virtual circuits are not "restarted" as such. Instead,
211  *  any active switched circuit is simply returned to READY
212  *  state.
213  */
214 
215 pk_restart (pkp, restart_cause)
216 register struct pkcb *pkp;
217 int restart_cause;
218 {
219 	register struct mbuf *m;
220 	register struct pklcd *lcp;
221 	register int i;
222 
223 	/* Restart all logical channels. */
224 	if (pkp -> pk_chan == 0)
225 		return;
226 
227 	/*
228 	 * Don't do this if we're doing a restart issued from
229 	 * inside pk_connect() --- which is only done if and
230 	 * only if the X.25 link is down, i.e. a RESTART needs
231 	 * to be done to get it up.
232 	 */
233 	if (!(pkp -> pk_dxerole & DTE_CONNECTPENDING)) {
234 		for (i = 1; i <= pkp -> pk_maxlcn; ++i)
235 			if ((lcp = pkp -> pk_chan[i]) != NULL) {
236 				if (lcp -> lcd_so) {
237 					lcp -> lcd_so -> so_error = ENETRESET;
238 					pk_close (lcp);
239 				} else {
240 					pk_flush (lcp);
241 					lcp -> lcd_state = READY;
242 					if (lcp -> lcd_upper)
243 						lcp -> lcd_upper (lcp, 0);
244 				}
245 			}
246 	}
247 
248 	if (restart_cause < 0)
249 		return;
250 
251 	pkp -> pk_state = DTE_SENT_RESTART;
252 	pkp -> pk_dxerole &= ~(DTE_PLAYDCE | DTE_PLAYDTE);
253 	lcp = pkp -> pk_chan[0];
254 	m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
255 	m -> m_pkthdr.len = m -> m_len += 2;
256 	mtod (m, struct x25_packet *) -> packet_data = 0;	/* DTE only */
257 	mtod (m, octet *)[4]  = restart_cause;
258 	pk_output (lcp);
259 }
260 
261 
262 /*
263  *  This procedure frees up the Logical Channel Descripter.
264  */
265 
266 pk_freelcd (lcp)
267 register struct pklcd *lcp;
268 {
269 	if (lcp == NULL)
270 		return;
271 
272 	if (lcp -> lcd_lcn > 0)
273 		lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL;
274 
275 	pk_flush (lcp);
276 	remque (&lcp -> lcd_q);
277 	free ((caddr_t)lcp, M_PCB);
278 }
279 
280 
281 /*
282  *  Bind a address and protocol value to a socket.  The important
283  *  part is the protocol value - the first four characters of the
284  *  Call User Data field.
285  */
286 
287 #define XTRACTPKP(rt)	((rt)->rt_flags & RTF_GATEWAY ? \
288 			 ((rt)->rt_llinfo ? \
289 			  (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
290 			  (struct pkcb *) NULL) : \
291 			 (struct pkcb *)((rt)->rt_llinfo))
292 
293 pk_bind (lcp, nam)
294 struct pklcd *lcp;
295 struct mbuf *nam;
296 {
297 	register struct pkcb *pkp;
298 	register struct pklcd *pp;
299 	register struct sockaddr_x25 *sa;
300 	register struct rtentry *rt;
301 
302 	if (nam == NULL)
303 		return (EADDRNOTAVAIL);
304 	if (lcp -> lcd_ceaddr)				/* XXX */
305 		return (EADDRINUSE);
306 	if (pk_checksockaddr (nam))
307 		return (EINVAL);
308 	sa = mtod (nam, struct sockaddr_x25 *);
309 
310 	/*
311 	 * If the user wishes to accept calls only from a particular
312 	 * net (net != 0), make sure the net is known
313 	 */
314 
315 	if ( !(rt =  rtalloc1(sa, 1)))
316 		return (ENETUNREACH);
317 	pkp = XTRACTPKP(rt);
318 
319 	/*
320 	 * For ISO's sake permit default listeners, but only one such . . .
321 	 */
322 	for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) {
323 		register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr;
324 		if ((sa2 -> x25_udlen == sa -> x25_udlen) &&
325 		    (sa2 -> x25_udlen == 0 ||
326 		     (bcmp (sa2 -> x25_udata, sa -> x25_udata,
327 			    min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0)))
328 				return (EADDRINUSE);
329 	}
330 	lcp -> lcd_laddr = *sa;
331 	lcp -> lcd_ceaddr = &lcp -> lcd_laddr;
332 	return (0);
333 }
334 
335 /*
336  * Include a bound control block in the list of listeners.
337  */
338 pk_listen (lcp)
339 register struct pklcd *lcp;
340 {
341 	register struct pklcd **pp;
342 
343 	if (lcp -> lcd_ceaddr == 0)
344 		return (EDESTADDRREQ);
345 
346 	lcp -> lcd_state = LISTEN;
347 	/*
348 	 * Add default listener at end, any others at start.
349 	 */
350 	if (lcp -> lcd_ceaddr -> x25_udlen == 0) {
351 		for (pp = &pk_listenhead; *pp; )
352 			pp = &((*pp) -> lcd_listen);
353 		*pp = lcp;
354 	} else {
355 		lcp -> lcd_listen = pk_listenhead;
356 		pk_listenhead = lcp;
357 	}
358 	return (0);
359 }
360 /*
361  * Include a listening control block for the benefit of other protocols.
362  */
363 pk_protolisten (spi, spilen, callee)
364 int (*callee) ();
365 {
366 	register struct pklcd *lcp = pk_attach ((struct socket *)0);
367 	register struct mbuf *nam;
368 	register struct sockaddr_x25 *sa;
369 	int error = ENOBUFS;
370 
371 	if (lcp) {
372 		if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) {
373 			sa = mtod (nam, struct sockaddr_x25 *);
374 			sa -> x25_family = AF_CCITT;
375 			sa -> x25_len = nam -> m_len = sizeof (*sa);
376 			sa -> x25_udlen = spilen;
377 			sa -> x25_udata[0] = spi;
378 			lcp -> lcd_upper = callee;
379 			lcp -> lcd_flags = X25_MBS_HOLD;
380 			if ((error = pk_bind (lcp, nam)) == 0)
381 				error = pk_listen (lcp);
382 			(void) m_free (nam);
383 		}
384 		if (error)
385 			pk_freelcd (lcp);
386 	}
387 	return error; /* Hopefully Zero !*/
388 }
389 
390 /*
391  * Associate a logical channel descriptor with a network.
392  * Fill in the default network specific parameters and then
393  * set any parameters explicitly specified by the user or
394  * by the remote DTE.
395  */
396 
397 pk_assoc (pkp, lcp, sa)
398 register struct pkcb *pkp;
399 register struct pklcd *lcp;
400 register struct sockaddr_x25 *sa;
401 {
402 
403 	lcp -> lcd_pkp = pkp;
404 	lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize;
405 	lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize;
406 	lcp -> lcd_rsn = MODULUS - 1;
407 	pkp -> pk_chan[lcp -> lcd_lcn] = lcp;
408 
409 	if (sa -> x25_opts.op_psize)
410 		lcp -> lcd_packetsize = sa -> x25_opts.op_psize;
411 	else
412 		sa -> x25_opts.op_psize = lcp -> lcd_packetsize;
413 	if (sa -> x25_opts.op_wsize)
414 		lcp -> lcd_windowsize = sa -> x25_opts.op_wsize;
415 	else
416 		sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
417 	sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
418 	lcp -> lcd_flags |= sa -> x25_opts.op_flags;
419 	lcp -> lcd_stime = time.tv_sec;
420 }
421 
422 pk_connect (lcp, sa)
423 register struct pklcd *lcp;
424 register struct sockaddr_x25 *sa;
425 {
426 	register struct pkcb *pkp;
427 	register struct rtentry *rt;
428 	register struct rtentry *nrt;
429 
430 	struct rtentry *npaidb_enter();
431 	struct pkcb *pk_newlink();
432 
433 	if (sa -> x25_addr[0] == '\0')
434 		return (EDESTADDRREQ);
435 
436 	/*
437 	 * Is the destination address known?
438 	 */
439 	if (!(rt = rtalloc1 (sa, 1)))
440 		return (ENETUNREACH);
441 
442 	if (!(pkp = XTRACTPKP(rt)))
443 		pkp = pk_newlink((struct x25_ifaddr *) (rt -> rt_ifa),
444 				 (caddr_t) 0);
445 
446 	/*
447 	 * Have we entered the LLC address?
448 	 */
449 	if (nrt = npaidb_enter(rt -> rt_gateway, rt_key(rt), rt, 0))
450 		pkp -> pk_llrt = nrt;
451 
452 	/*
453 	 * Have we allocated an LLC2 link yet?
454 	 */
455 	if (pkp->pk_llnext == (caddr_t)0 && pkp->pk_llctlinput) {
456 		struct dll_ctlinfo ctlinfo;
457 
458 		ctlinfo.dlcti_rt = rt;
459 		ctlinfo.dlcti_pcb = (caddr_t) pkp;
460 		ctlinfo.dlcti_conf =
461 			(struct dllconfig *) (&((struct x25_ifaddr *)(rt->rt_ifa))->ia_xc);
462 		pkp->pk_llnext =
463 			(pkp->pk_llctlinput)(PRC_CONNECT_REQUEST, 0, &ctlinfo);
464 	}
465 
466 	if (pkp -> pk_state != DTE_READY && pkp -> pk_state != DTE_WAITING)
467 			return (ENETDOWN);
468 	if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0)
469 		return (EMFILE);
470 
471 	lcp -> lcd_faddr = *sa;
472 	lcp -> lcd_ceaddr = & lcp -> lcd_faddr;
473 	pk_assoc (pkp, lcp, lcp -> lcd_ceaddr);
474 
475 	/*
476 	 * If the link is not up yet, initiate an X.25 RESTART
477 	 */
478 	if (pkp -> pk_state == DTE_WAITING) {
479 		pkp -> pk_dxerole |= DTE_CONNECTPENDING;
480 		pk_ctlinput(PRC_LINKUP, (struct sockaddr *)0, pkp);
481 		if (lcp -> lcd_so)
482 			soisconnecting (lcp -> lcd_so);
483 		return 0;
484 	}
485 
486 	if (lcp -> lcd_so)
487 		soisconnecting (lcp -> lcd_so);
488 	lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
489 	pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
490 	return (*pkp -> pk_ia -> ia_start) (lcp);
491 }
492 
493 /*
494  * Complete all pending X.25 call requests --- this gets called after
495  * the X.25 link has been restarted.
496  */
497 #define RESHUFFLELCN(maxlcn, lcn) ((maxlcn) - (lcn) + 1)
498 
499 pk_callcomplete(pkp)
500 	register struct pkcb *pkp;
501 {
502 	register struct pklcd *lcp;
503 	register int i;
504 	register int ni;
505 
506 
507 	if (pkp -> pk_dxerole & DTE_CONNECTPENDING)
508 		pkp -> pk_dxerole &= ~DTE_CONNECTPENDING;
509 	else return;
510 
511 	if (pkp -> pk_chan == 0)
512 		return;
513 
514 	/*
515 	 * We pretended to be a DTE for allocating lcns, if
516 	 * it turns out that we are in reality performing as a
517 	 * DCE we need to reshuffle the lcps.
518 	 *
519          *             /+---------------+--------     -
520 	 *            / | a  (maxlcn-1) |              \
521 	 *           /  +---------------+              	\
522 	 *     +--- *   | b  (maxlcn-2) |         	 \
523 	 *     |     \  +---------------+         	  \
524 	 *   r |      \ | c  (maxlcn-3) |         	   \
525 	 *   e |       \+---------------+         	    |
526 	 *   s |        |	 .                	    |
527 	 *   h |        |        .                	    | m
528 	 *   u |        |	 .      	  	    | a
529 	 *   f |        |	 .      	  	    | x
530 	 *   f |        |	 .                	    | l
531 	 *   l |       /+---------------+         	    | c
532 	 *   e |      / | c' (   3    ) |         	    | n
533 	 *     |     /  +---------------+         	    |
534 	 *     +--> *   | b' (   2    ) |         	   /
535 	 *           \  +---------------+         	  /
536 	 *            \ | a' (   1    ) |         	 /
537     	 *             \+---------------+               /
538          *              | 0             |              /
539 	 *              +---------------+--------     -
540 	 *
541 	 */
542 	if (pkp -> pk_dxerole & DTE_PLAYDCE) {
543 		/* Sigh, reshuffle it */
544 		for (i = pkp -> pk_maxlcn; i > 0; --i)
545 			if (pkp -> pk_chan[i]) {
546 				ni = RESHUFFLELCN(pkp -> pk_maxlcn, i);
547 				pkp -> pk_chan[ni] = pkp -> pk_chan[i];
548 				pkp -> pk_chan[i] = NULL;
549 				pkp -> pk_chan[ni] -> lcd_lcn = ni;
550 			}
551 	}
552 
553 	for (i = 1; i <= pkp -> pk_maxlcn; ++i)
554 		if ((lcp = pkp -> pk_chan[i]) != NULL) {
555 			/* if (lcp -> lcd_so)
556 				soisconnecting (lcp -> lcd_so); */
557 			lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
558 			pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
559 			(*pkp -> pk_ia -> ia_start)(lcp);
560 		}
561 }
562 
563 struct bcdinfo {
564 	octet *cp;
565 	unsigned posn;
566 };
567 /*
568  *  Build the rest of the CALL REQUEST packet. Fill in calling
569  *  address, facilities fields and the user data field.
570  */
571 
572 pk_callrequest (lcp, sa, xcp)
573 struct pklcd *lcp;
574 register struct sockaddr_x25 *sa;
575 register struct x25config *xcp;
576 {
577 	register struct x25_calladdr *a;
578 	register struct mbuf *m = lcp -> lcd_template;
579 	register struct x25_packet *xp = mtod (m, struct x25_packet *);
580 	struct bcdinfo b;
581 
582 	if (lcp -> lcd_flags & X25_DBIT)
583 		X25SBITS(xp -> bits, d_bit, 1);
584 	a = (struct x25_calladdr *) &xp -> packet_data;
585 	b.cp = (octet *) a -> address_field;
586 	b.posn = 0;
587 	X25SBITS(a -> addrlens, called_addrlen, to_bcd (&b, sa, xcp));
588 	X25SBITS(a -> addrlens, calling_addrlen, to_bcd (&b, &xcp -> xc_addr, xcp));
589 	if (b.posn & 0x01)
590 		*b.cp++ &= 0xf0;
591 	m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
592 
593 	if (lcp -> lcd_facilities) {
594 		m -> m_pkthdr.len +=
595 			(m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
596 		lcp -> lcd_facilities = 0;
597 	} else
598 		pk_build_facilities (m, sa, (int)xcp -> xc_type);
599 
600 	m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
601 }
602 
603 pk_build_facilities (m, sa, type)
604 register struct mbuf *m;
605 struct sockaddr_x25 *sa;
606 {
607 	register octet *cp;
608 	register octet *fcp;
609 	register int revcharge;
610 
611 	cp = mtod (m, octet *) + m -> m_len;
612 	fcp = cp + 1;
613 	revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
614 	/*
615 	 * This is specific to Datapac X.25(1976) DTEs.  International
616 	 * calls must have the "hi priority" bit on.
617 	 */
618 	if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)
619 		revcharge |= 02;
620 	if (revcharge) {
621 		*fcp++ = FACILITIES_REVERSE_CHARGE;
622 		*fcp++ = revcharge;
623 	}
624 	switch (type) {
625 	case X25_1980:
626 	case X25_1984:
627 		*fcp++ = FACILITIES_PACKETSIZE;
628 		*fcp++ = sa -> x25_opts.op_psize;
629 		*fcp++ = sa -> x25_opts.op_psize;
630 
631 		*fcp++ = FACILITIES_WINDOWSIZE;
632 		*fcp++ = sa -> x25_opts.op_wsize;
633 		*fcp++ = sa -> x25_opts.op_wsize;
634 	}
635 	*cp = fcp - cp - 1;
636 	m -> m_pkthdr.len = (m -> m_len += *cp + 1);
637 }
638 
639 to_bcd (b, sa, xcp)
640 register struct bcdinfo *b;
641 struct sockaddr_x25 *sa;
642 register struct x25config *xcp;
643 {
644 	register char *x = sa -> x25_addr;
645 	unsigned start = b -> posn;
646 	/*
647 	 * The nodnic and prepnd0 stuff looks tedious,
648 	 * but it does allow full X.121 addresses to be used,
649 	 * which is handy for routing info (& OSI type 37 addresses).
650 	 */
651 	if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
652 		char dnicname[sizeof(long) * NBBY/3 + 2];
653 		register char *p = dnicname;
654 
655 		sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
656 		for (; *p; p++) /* *p == 0 means dnic matched */
657 			if ((*p ^ *x++) & 0x0f)
658 				break;
659 		if (*p || xcp -> xc_nodnic == 0)
660 			x = sa -> x25_addr;
661 		if (*p && xcp -> xc_prepnd0) {
662 			if ((b -> posn)++ & 0x01)
663 				*(b -> cp)++;
664 			else
665 				*(b -> cp) = 0;
666 		}
667 	}
668 	while (*x)
669 		if ((b -> posn)++ & 0x01)
670 			*(b -> cp)++ |= *x++ & 0x0F;
671 		else
672 			*(b -> cp) = *x++ << 4;
673 	return ((b -> posn) - start);
674 }
675 
676 /*
677  *  This routine gets the  first available logical channel number.  The
678  *  search is
679  *  		- from the highest number to lowest number if playing DTE, and
680  *		- from lowest to highest number if playing DCE.
681  */
682 
683 pk_getlcn (pkp)
684 register struct pkcb *pkp;
685 {
686 	register int i;
687 
688 	if (pkp -> pk_chan == 0)
689 		return (0);
690 	if ( pkp -> pk_dxerole & DTE_PLAYDCE ) {
691 		for (i = 1; i <= pkp -> pk_maxlcn; ++i)
692 			if (pkp -> pk_chan[i] == NULL)
693 				break;
694 	} else {
695 		for (i = pkp -> pk_maxlcn; i > 0; --i)
696 			if (pkp -> pk_chan[i] == NULL)
697 				break;
698 	}
699 	i = ( i > pkp -> pk_maxlcn ? 0 : i );
700 	return (i);
701 }
702 
703 /*
704  *  This procedure sends a CLEAR request packet. The lc state is
705  *  set to "SENT_CLEAR".
706  */
707 
708 pk_clear (lcp, diagnostic, abortive)
709 register struct pklcd *lcp;
710 {
711 	register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);
712 
713 	m -> m_len += 2;
714 	m -> m_pkthdr.len += 2;
715 	mtod (m, struct x25_packet *) -> packet_data = 0;
716 	mtod (m, octet *)[4] = diagnostic;
717 	if (lcp -> lcd_facilities) {
718 		m -> m_next = lcp -> lcd_facilities;
719 		m -> m_pkthdr.len += m -> m_next -> m_len;
720 		lcp -> lcd_facilities = 0;
721 	}
722 	if (abortive)
723 		lcp -> lcd_template = m;
724 	else {
725 		struct socket *so = lcp -> lcd_so;
726 		struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;
727 		sbappendrecord (sb, m);
728 	}
729 	pk_output (lcp);
730 
731 }
732 
733 /*
734  * This procedure generates RNR's or RR's to inhibit or enable
735  * inward data flow, if the current state changes (blocked ==> open or
736  * vice versa), or if forced to generate one.  One forces RNR's to ack data.
737  */
738 pk_flowcontrol (lcp, inhibit, forced)
739 register struct pklcd *lcp;
740 {
741 	inhibit = (inhibit != 0);
742 	if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||
743 	    (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
744 		return;
745 	lcp -> lcd_rxrnr_condition = inhibit;
746 	lcp -> lcd_template =
747 		pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
748 	pk_output (lcp);
749 }
750 
751 /*
752  *  This procedure sends a RESET request packet. It re-intializes
753  *  virtual circuit.
754  */
755 
756 static
757 pk_reset (lcp, diagnostic)
758 register struct pklcd *lcp;
759 {
760 	register struct mbuf *m;
761 	register struct socket *so = lcp -> lcd_so;
762 
763 	if (lcp -> lcd_state != DATA_TRANSFER)
764 		return;
765 
766 	if (so)
767 		so -> so_error = ECONNRESET;
768 	lcp -> lcd_reset_condition = TRUE;
769 
770 	/* Reset all the control variables for the channel. */
771 	pk_flush (lcp);
772 	lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
773 		lcp -> lcd_intrconf_pending = FALSE;
774 	lcp -> lcd_rsn = MODULUS - 1;
775 	lcp -> lcd_ssn = 0;
776 	lcp -> lcd_output_window = lcp -> lcd_input_window =
777 		lcp -> lcd_last_transmitted_pr = 0;
778 	m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
779 	m -> m_pkthdr.len = m -> m_len += 2;
780 	mtod (m, struct x25_packet *) -> packet_data = 0;
781 	mtod (m, octet *)[4] = diagnostic;
782 	pk_output (lcp);
783 
784 }
785 
786 /*
787  * This procedure frees all data queued for output or delivery on a
788  *  virtual circuit.
789  */
790 
791 pk_flush (lcp)
792 register struct pklcd *lcp;
793 {
794 	register struct socket *so;
795 
796 	if (lcp -> lcd_template)
797 		m_freem (lcp -> lcd_template);
798 
799 	if (lcp -> lcd_cps) {
800 		m_freem (lcp -> lcd_cps);
801 		lcp -> lcd_cps = 0;
802 	}
803 	if (lcp -> lcd_facilities) {
804 		m_freem (lcp -> lcd_facilities);
805 		lcp -> lcd_facilities = 0;
806 	}
807 	if (so = lcp -> lcd_so)
808 		sbflush (&so -> so_snd);
809 	else
810 		sbflush (&lcp -> lcd_sb);
811 }
812 
813 /*
814  *  This procedure handles all local protocol procedure errors.
815  */
816 
817 pk_procerror (error, lcp, errstr, diagnostic)
818 register struct pklcd *lcp;
819 char *errstr;
820 {
821 
822 	pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);
823 
824 	switch (error) {
825 	case CLEAR:
826 		if (lcp -> lcd_so) {
827 			lcp -> lcd_so -> so_error = ECONNABORTED;
828 			soisdisconnecting (lcp -> lcd_so);
829 		}
830 		pk_clear (lcp, diagnostic, 1);
831 		break;
832 
833 	case RESET:
834 		pk_reset (lcp, diagnostic);
835 	}
836 }
837 
838 /*
839  *  This procedure is called during the DATA TRANSFER state to check
840  *  and  process  the P(R) values  received  in the DATA,  RR OR RNR
841  *  packets.
842  */
843 
844 pk_ack (lcp, pr)
845 struct pklcd *lcp;
846 unsigned pr;
847 {
848 	register struct socket *so = lcp -> lcd_so;
849 
850 	if (lcp -> lcd_output_window == pr)
851 		return (PACKET_OK);
852 	if (lcp -> lcd_output_window < lcp -> lcd_ssn) {
853 		if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {
854 			pk_procerror (RESET, lcp,
855 				"p(r) flow control error", 2);
856 			return (ERROR_PACKET);
857 		}
858 	}
859 	else {
860 		if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {
861 			pk_procerror (RESET, lcp,
862 				"p(r) flow control error #2", 2);
863 			return (ERROR_PACKET);
864 		}
865 	}
866 
867 	lcp -> lcd_output_window = pr;		/* Rotate window. */
868 	if (lcp -> lcd_window_condition == TRUE)
869 		lcp -> lcd_window_condition = FALSE;
870 
871 	if (so && ((so -> so_snd.sb_flags & SB_WAIT) ||
872 		   (so -> so_snd.sb_flags & SB_NOTIFY)))
873 		sowwakeup (so);
874 
875 	return (PACKET_OK);
876 }
877 
878 /*
879  *  This procedure decodes the X.25 level 3 packet returning a
880  *  code to be used in switchs or arrays.
881  */
882 
883 pk_decode (xp)
884 register struct x25_packet *xp;
885 {
886 	register int type;
887 
888 	if (X25GBITS(xp -> bits, fmt_identifier) != 1)
889 		return (INVALID_PACKET);
890 #ifdef ancient_history
891 	/*
892 	 *  Make sure that the logical channel group number is 0.
893 	 *  This restriction may be removed at some later date.
894 	 */
895 	if (xp -> lc_group_number != 0)
896 		return (INVALID_PACKET);
897 #endif
898 	/*
899 	 *  Test for data packet first.
900 	 */
901 	if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))
902 		return (DATA);
903 
904 	/*
905 	 *  Test if flow control packet (RR or RNR).
906 	 */
907 	if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))
908 		switch (xp -> packet_type & 0x1f) {
909 		case X25_RR:
910 			return (RR);
911 		case X25_RNR:
912 			return (RNR);
913 		case X25_REJECT:
914 			return (REJECT);
915 		}
916 
917 	/*
918 	 *  Determine the rest of the packet types.
919 	 */
920 	switch (xp -> packet_type) {
921 	case X25_CALL:
922 		type = CALL;
923 		break;
924 
925 	case X25_CALL_ACCEPTED:
926 		type = CALL_ACCEPTED;
927 		break;
928 
929 	case X25_CLEAR:
930 		type = CLEAR;
931 		break;
932 
933 	case X25_CLEAR_CONFIRM:
934 		type = CLEAR_CONF;
935 		break;
936 
937 	case X25_INTERRUPT:
938 		type = INTERRUPT;
939 		break;
940 
941 	case X25_INTERRUPT_CONFIRM:
942 		type = INTERRUPT_CONF;
943 		break;
944 
945 	case X25_RESET:
946 		type = RESET;
947 		break;
948 
949 	case X25_RESET_CONFIRM:
950 		type = RESET_CONF;
951 		break;
952 
953 	case X25_RESTART:
954 		type = RESTART;
955 		break;
956 
957 	case X25_RESTART_CONFIRM:
958 		type = RESTART_CONF;
959 		break;
960 
961 	case X25_DIAGNOSTIC:
962 		type = DIAG_TYPE;
963 		break;
964 
965 	default:
966 		type = INVALID_PACKET;
967 	}
968 	return (type);
969 }
970 
971 /*
972  *  A restart packet has been received. Print out the reason
973  *  for the restart.
974  */
975 
976 pk_restartcause (pkp, xp)
977 struct pkcb *pkp;
978 register struct x25_packet *xp;
979 {
980 	register struct x25config *xcp = pkp -> pk_xcp;
981 	register int lcn = LCN(xp);
982 
983 	switch (xp -> packet_data) {
984 	case X25_RESTART_LOCAL_PROCEDURE_ERROR:
985 		pk_message (lcn, xcp, "restart: local procedure error");
986 		break;
987 
988 	case X25_RESTART_NETWORK_CONGESTION:
989 		pk_message (lcn, xcp, "restart: network congestion");
990 		break;
991 
992 	case X25_RESTART_NETWORK_OPERATIONAL:
993 		pk_message (lcn, xcp, "restart: network operational");
994 		break;
995 
996 	default:
997 		pk_message (lcn, xcp, "restart: unknown cause");
998 	}
999 }
1000 
1001 #define MAXRESETCAUSE	7
1002 
1003 int     Reset_cause[] = {
1004 	EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG
1005 };
1006 
1007 /*
1008  *  A reset packet has arrived. Return the cause to the user.
1009  */
1010 
1011 pk_resetcause (pkp, xp)
1012 struct pkcb *pkp;
1013 register struct x25_packet *xp;
1014 {
1015 	register struct pklcd *lcp =
1016 				pkp -> pk_chan[LCN(xp)];
1017 	register int code = xp -> packet_data;
1018 
1019 	if (code > MAXRESETCAUSE)
1020 		code = 7;	/* EXRNCG */
1021 
1022 	pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
1023 			xp -> packet_data, 4[(u_char *)xp]);
1024 
1025 	if (lcp -> lcd_so)
1026 		lcp -> lcd_so -> so_error = Reset_cause[code];
1027 }
1028 
1029 #define MAXCLEARCAUSE	25
1030 
1031 int     Clear_cause[] = {
1032 	EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,
1033 	0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,
1034 	0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC
1035 };
1036 
1037 /*
1038  *  A clear packet has arrived. Return the cause to the user.
1039  */
1040 
1041 pk_clearcause (pkp, xp)
1042 struct pkcb *pkp;
1043 register struct x25_packet *xp;
1044 {
1045 	register struct pklcd *lcp =
1046 		pkp -> pk_chan[LCN(xp)];
1047 	register int code = xp -> packet_data;
1048 
1049 	if (code > MAXCLEARCAUSE)
1050 		code = 5;	/* EXRNCG */
1051 	if (lcp -> lcd_so)
1052 		lcp -> lcd_so -> so_error = Clear_cause[code];
1053 }
1054 
1055 char *
1056 format_ntn (xcp)
1057 register struct x25config *xcp;
1058 {
1059 
1060 	return (xcp -> xc_addr.x25_addr);
1061 }
1062 
1063 /* VARARGS1 */
1064 pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)
1065 struct x25config *xcp;
1066 char *fmt;
1067 {
1068 
1069 	if (lcn)
1070 		if (!PQEMPTY)
1071 			printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);
1072 		else
1073 			printf ("X.25: lcn %d: ", lcn);
1074 	else
1075 		if (!PQEMPTY)
1076 			printf ("X.25(%s): ", format_ntn (xcp));
1077 		else
1078 			printf ("X.25: ");
1079 
1080 	printf (fmt, a1, a2, a3, a4, a5, a6);
1081 	printf ("\n");
1082 }
1083 
1084 pk_fragment (lcp, m0, qbit, mbit, wait)
1085 struct mbuf *m0;
1086 register struct pklcd *lcp;
1087 {
1088 	register struct mbuf *m = m0;
1089 	register struct x25_packet *xp;
1090 	register struct sockbuf *sb;
1091 	struct mbuf *head = 0, *next, **mp = &head, *m_split ();
1092 	int totlen, psize = 1 << (lcp -> lcd_packetsize);
1093 
1094 	if (m == 0)
1095 		return 0;
1096 	if (m -> m_flags & M_PKTHDR == 0)
1097 		panic ("pk_fragment");
1098 	totlen = m -> m_pkthdr.len;
1099 	m -> m_act = 0;
1100 	sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;
1101 	do {
1102 		if (totlen > psize) {
1103 			if ((next = m_split (m, psize, wait)) == 0)
1104 				goto abort;
1105 			totlen -= psize;
1106 		} else
1107 			next = 0;
1108 		M_PREPEND(m, PKHEADERLN, wait);
1109 		if (m == 0)
1110 			goto abort;
1111 		*mp = m;
1112 		mp = & m -> m_act;
1113 		*mp = 0;
1114 		xp = mtod (m, struct x25_packet *);
1115 		0[(char *)xp] = 0;
1116 		if (qbit)
1117 			X25SBITS(xp -> bits, q_bit, 1);
1118 		if (lcp -> lcd_flags & X25_DBIT)
1119 			X25SBITS(xp -> bits, d_bit, 1);
1120 		X25SBITS(xp -> bits, fmt_identifier, 1);
1121 		xp -> packet_type = X25_DATA;
1122 		SET_LCN(xp, lcp -> lcd_lcn);
1123 		if (next || (mbit && (totlen == psize ||
1124 				      (lcp -> lcd_flags & X25_DBIT))))
1125 			SMBIT(xp, 1);
1126 	} while (m = next);
1127 	for (m = head; m; m = next) {
1128 		next = m -> m_act;
1129 		m -> m_act = 0;
1130 		sbappendrecord (sb, m);
1131 	}
1132 	return 0;
1133 abort:
1134 	if (wait)
1135 		panic ("pk_fragment null mbuf after wait");
1136 	if (next)
1137 		m_freem (next);
1138 	for (m = head; m; m = next) {
1139 		next = m -> m_act;
1140 		m_freem (m);
1141 	}
1142 	return ENOBUFS;
1143 }
1144