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