xref: /original-bsd/sys/netccitt/llc_subr.c (revision 5ec50ca3)
1 /*
2  * Copyright (C) Dirk Husemann, Computer Science Department IV,
3  * 		 University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
4  * Copyright (c) 1992   Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Dirk Husemann and the Computer Science Department (IV) of
9  * the University of Erlangen-Nuremberg, Germany.
10  *
11  * %sccs.include.redist.c%
12  *
13  *	@(#)llc_subr.c	7.1 (Berkeley) 12/08/92
14  */
15 
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <sys/mbuf.h>
19 #include <sys/domain.h>
20 #include <sys/socket.h>
21 #include <sys/protosw.h>
22 #include <sys/socketvar.h>
23 #include <sys/errno.h>
24 #include <sys/time.h>
25 #include <sys/kernel.h>
26 
27 #include <net/if.h>
28 #include <net/if_dl.h>
29 #include <net/if_llc.h>
30 #include <net/route.h>
31 
32 #include <netccitt/dll.h>
33 #include <netccitt/llc_var.h>
34 
35 /*
36  * Frame names for diagnostic messages
37  */
38 char *frame_names[] = { "INFO", "RR", "RNR", "REJ", "DM", "SABME", "DISC",
39 	"UA", "FRMR", "UI", "XID", "TEST", "ILLEGAL", "TIMER", "N2xT1"};
40 
41 
42 /*
43  * Trace level
44  */
45 int llc_tracelevel = LLCTR_URGENT;
46 
47 /*
48  * Values for accessing various bitfields
49  */
50 struct bitslice llc_bitslice[] = {
51 /*	  mask, shift value */
52 	{ 0x1,  0x0 },
53 	{ 0xfe, 0x1 },
54 	{ 0x3,  0x0 },
55 	{ 0xc,  0x2 },
56 	{ 0x10, 0x4 },
57 	{ 0xe0, 0x5 },
58 	{ 0x1f, 0x0 }
59 };
60 
61 /*
62  * We keep the link control blocks on a doubly linked list -
63  * primarily for checking in llc_time()
64  */
65 
66 struct llccb_q llccb_q = { &llccb_q, &llccb_q };
67 
68 /*
69  * Functions dealing with struct sockaddr_dl */
70 
71 /* Compare sdl_a w/ sdl_b */
72 
73 sdl_cmp(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b)
74 {
75 	if (LLADDRLEN(sdl_a) != LLADDRLEN(sdl_b))
76 		return(1);
77 	return(bcmp((caddr_t) sdl_a->sdl_data, (caddr_t) sdl_b->sdl_data,
78 		    LLADDRLEN(sdl_a)));
79 }
80 
81 /* Copy sdl_f to sdl_t */
82 
83 sdl_copy(struct sockaddr_dl *sdl_f, struct sockaddr_dl *sdl_t)
84 {
85 	bcopy((caddr_t) sdl_f, (caddr_t) sdl_t, sdl_f->sdl_len);
86 }
87 
88 /* Swap sdl_a w/ sdl_b */
89 
90 sdl_swapaddr(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b)
91 {
92 	struct sockaddr_dl sdl_tmp;
93 
94 	sdl_copy(sdl_a, &sdl_tmp);
95 	sdl_copy(sdl_b, sdl_a);
96 	sdl_copy(&sdl_tmp, sdl_b);
97 }
98 
99 /* Fetch the sdl of the associated if */
100 
101 struct sockaddr_dl *
102 sdl_getaddrif(struct ifnet *ifp)
103 {
104 	register struct ifaddr *ifa;
105 
106 	for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
107 		if (ifa->ifa_addr->sa_family == AF_LINK )
108 			return((struct sockaddr_dl *)(ifa->ifa_addr));
109 
110 	return((struct sockaddr_dl *)0);
111 }
112 
113 /* Check addr of interface with the one given */
114 
115 sdl_checkaddrif(struct ifnet *ifp, struct sockaddr_dl *sdl_c)
116 {
117 	register struct ifaddr *ifa;
118 
119 	for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
120 		if ((ifa->ifa_addr->sa_family == AF_LINK ) &&
121 		    !sdl_cmp((struct sockaddr_dl *)(ifa->ifa_addr), sdl_c))
122 			return(1);
123 
124 	return(0);
125 }
126 
127 /* Build an sdl from MAC addr, DLSAP addr, and interface */
128 
129 sdl_setaddrif(struct ifnet *ifp, u_char *mac_addr, u_char dlsap_addr,
130 	      u_char mac_len, struct sockaddr_dl *sdl_to)
131 {
132 	register struct sockaddr_dl *sdl_tmp;
133 
134 	if ((sdl_tmp = sdl_getaddrif(ifp)) ) {
135 		sdl_copy(sdl_tmp, sdl_to);
136 		bcopy((caddr_t) mac_addr, (caddr_t) LLADDR(sdl_to), mac_len);
137 		*(LLADDR(sdl_to)+mac_len) = dlsap_addr;
138 		sdl_to->sdl_alen = mac_len+1;
139 		return(1);
140 	} else return(0);
141 }
142 
143 /* Fill out the sdl header aggregate */
144 
145 sdl_sethdrif(struct ifnet *ifp, u_char *mac_src, u_char dlsap_src, u_char *mac_dst,
146 	     u_char dlsap_dst, u_char mac_len, struct sdl_hdr *sdlhdr_to)
147 {
148 	if ( !sdl_setaddrif(ifp, mac_src, dlsap_src, mac_len,
149 			     &sdlhdr_to->sdlhdr_src) ||
150 	     !sdl_setaddrif(ifp, mac_dst, dlsap_dst, mac_len,
151 			     &sdlhdr_to->sdlhdr_dst) )
152 		return(0);
153 	else return(1);
154 }
155 
156 
157 static af_link_rts_init_done = 0;
158 #define USES_AF_LINK_RTS { \
159 	if (!af_link_rts_init_done) { \
160 	       rn_inithead((void **)&rt_tables[AF_LINK], 32); \
161 	       af_link_rts_init_done++; \
162 	       } \
163 	 }
164 
165 static struct sockaddr_dl sap_saddr;
166 static struct sockaddr_dl sap_sgate = {
167 	sizeof(struct sockaddr_dl), /* _len */
168 	AF_LINK                     /* _af */
169 };
170 
171 /*
172  * Set sapinfo for SAP address, llcconfig, af, and interface
173  */
174 struct npaidbentry *
175 llc_setsapinfo(struct ifnet *ifp, u_char af, u_char sap, struct dllconfig *llconf)
176 {
177 	struct protosw *pp;
178 	struct sockaddr_dl *ifdl_addr;
179 	struct rtentry *sirt = (struct rtentry *)0;
180 	struct npaidbentry *sapinfo;
181 	u_char saploc;
182 	int size = sizeof(struct npaidbentry);
183 
184 	USES_AF_LINK_RTS;
185 
186 	/*
187 	 * We rely/assume that only STREAM protocols will make use of
188 	 * connection oriented LLC2. If this will one day not be the
189 	 * case this will obviously fail.
190 	 */
191 	pp = pffindtype (af, SOCK_STREAM);
192 	if (pp == 0 || pp->pr_input == 0 || pp->pr_ctlinput == 0) {
193 		printf("network	level protosw error");
194 		return 0;
195 	}
196 
197 	/*
198 	 * We need a way to jot down the LLC2 configuration for
199 	 * a certain LSAP address. To do this we enter
200 	 * a "route" for the SAP.
201 	 */
202 	ifdl_addr = sdl_getaddrif(ifp);
203 	sdl_copy(ifdl_addr, &sap_saddr);
204 	sdl_copy(ifdl_addr, &sap_sgate);
205 	saploc = LLSAPLOC(&sap_saddr, ifp);
206 	sap_saddr.sdl_data[saploc] = sap;
207 	sap_saddr.sdl_alen++;
208 
209 	/* now enter it */
210 	rtrequest(RTM_ADD, &sap_saddr, &sap_sgate, 0, 0, &sirt);
211 	if (sirt == 0)
212 		return 0;
213 
214 	/* Plug in config information in rt->rt_llinfo */
215 
216 	sirt->rt_llinfo = malloc(size , M_PCB, M_WAITOK);
217 	sapinfo = (struct npaidbentry *) sirt->rt_llinfo;
218 	if (sapinfo) {
219 		bzero ((caddr_t)sapinfo, size);
220 		/*
221 		 * For the time being we support LLC CLASS II here
222 		 * only
223 		 */
224 		sapinfo->si_class = LLC_CLASS_II;
225 		sapinfo->si_window = llconf->dllcfg_window;
226 		sapinfo->si_trace = llconf->dllcfg_trace;
227 		if (sapinfo->si_trace)
228 			llc_tracelevel--;
229 		else llc_tracelevel++;
230 		sapinfo->si_input = pp->pr_input;
231 		sapinfo->si_ctlinput = (caddr_t (*)())pp->pr_ctlinput;
232 
233 		return (sapinfo);
234 	}
235 
236 	return 0;
237 }
238 
239 /*
240  * Get sapinfo for SAP address and interface
241  */
242 struct npaidbentry *
243 llc_getsapinfo(u_char sap, struct ifnet *ifp)
244 {
245 	struct sockaddr_dl *ifdl_addr;
246 	struct sockaddr_dl si_addr;
247 	struct rtentry *sirt;
248 	u_char saploc;
249 
250 	USES_AF_LINK_RTS;
251 
252 	ifdl_addr = sdl_getaddrif(ifp);
253 	sdl_copy(ifdl_addr, &si_addr);
254 	saploc = LLSAPLOC(&si_addr, ifp);
255 	si_addr.sdl_data[saploc] = sap;
256 	si_addr.sdl_alen++;
257 
258 	if ((sirt = rtalloc1(&si_addr, 0)))
259 		sirt->rt_refcnt--;
260 	else return(0);
261 
262 	return((struct npaidbentry *)sirt->rt_llinfo);
263 }
264 
265 /*
266  * Network Protocol Addressing Information DataBase (npaidb)
267  *
268  * To speed up locating the entity dealing with an LLC packet use is made
269  * of a routing tree. This npaidb routing tree is handled
270  * by the normal rn_*() routines just like (almost) any other routing tree.
271  *
272  * The mapping being done by the npaidb_*() routines is as follows:
273  *
274  *     Key:       MAC,LSAP (enhancing struct sockaddr_dl)
275  *     Gateway:   sockaddr_x25 (i.e. X.25 address - X.121 or NSAP)
276  *     Llinfo:    npaidbentry {
277  *                         struct llc_linkcb *npaidb_linkp;
278  *                         struct rtentry *npaidb_rt;
279  *                }
280  *
281  * Using the npaidbentry provided by llinfo we can then access
282  *
283  *       o the pkcb by using (struct pkcb *) (npaidb_rt->rt_llinfo)
284  *       o the linkcb via npaidb_linkp
285  *
286  * The following functions are provided
287  *
288  *       o npaidb_enter(struct sockaddr_dl *sdl, struct sockaddr_x25 *sx25,
289  *                      struct struct llc_linkcb *link, struct rtentry *rt)
290  *
291  *       o npaidb_enrich(short type, caddr_t info)
292  *
293  */
294 
295 struct sockaddr_dl npdl_netmask = {
296  sizeof(struct sockaddr_dl),					/* _len */
297  0,								/* _family */
298  0,								/* _index */
299  0,								/* _type */
300  -1,								/* _nlen */
301  -1,								/* _alen */
302  -1,								/* _slen */
303  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},		/* _data */
304 };
305 struct sockaddr npdl_dummy;
306 
307 int npdl_datasize = sizeof(struct sockaddr_dl)-
308 		((int)((caddr_t)&((struct sockaddr_dl *)0)->sdl_data[0]));
309 
310 struct rtentry *
311 npaidb_enter(struct sockaddr_dl *key, struct sockaddr *value,
312 	     struct rtentry *rt, struct llc_linkcb *link)
313 {
314 	struct rtentry *nprt; register int i;
315 
316 	USES_AF_LINK_RTS;
317 
318 	if ((nprt = rtalloc1(key, 0)) == 0) {
319 		register u_int size = sizeof(struct npaidbentry);
320 		register u_char saploc = LLSAPLOC(key, rt->rt_ifp);
321 
322 		/*
323 		 * set up netmask: LLC2 packets have the lowest bit set in
324 		 * response packets (e.g. 0x7e for command packets, 0x7f for
325 		 * response packets), to facilitate the lookup we use a netmask
326 		 * of 11111110 for the SAP position. The remaining positions
327 		 * are zeroed out.
328 		 */
329 		npdl_netmask.sdl_data[saploc] = NPDL_SAPNETMASK;
330 		bzero((caddr_t)&npdl_netmask.sdl_data[saploc+1],
331 		      npdl_datasize-saploc-1);
332 
333 		if (value == 0)
334 			value = &npdl_dummy;
335 
336 		/* now enter it */
337 		rtrequest(RTM_ADD, key, value, &npdl_netmask, 0, &nprt);
338 
339 		/* and reset npdl_netmask */
340 		for (i = saploc; i < npdl_datasize; i++)
341 			npdl_netmask.sdl_data[i] = -1;
342 
343 		nprt->rt_llinfo = malloc(size , M_PCB, M_WAITOK);
344 		if (nprt->rt_llinfo) {
345 			bzero (nprt->rt_llinfo, size);
346 			((struct npaidbentry *) (nprt->rt_llinfo))->np_rt = rt;
347 		}
348 	} else nprt->rt_refcnt--;
349 	return nprt;
350 }
351 
352 struct rtentry *
353 npaidb_enrich(short type, caddr_t info, struct sockaddr_dl *sdl)
354 {
355 	struct rtentry *rt;
356 
357 	USES_AF_LINK_RTS;
358 
359 	if (rt = rtalloc1(sdl, 0)) {
360 		rt->rt_refcnt--;
361 		switch (type) {
362 		case NPAIDB_LINK:
363 			((struct npaidbentry *)(rt->rt_llinfo))->np_link =
364 				(struct llc_linkcb *) info;
365 			break;
366 		}
367 		return rt;
368 	}
369 
370 	return ((struct rtentry *) 0);
371 
372 }
373 
374 npaidb_destroy(struct rtentry *rt)
375 {
376 	USES_AF_LINK_RTS;
377 
378 	if (rt->rt_llinfo)
379 		free((caddr_t) rt->rt_llinfo, M_PCB);
380 	return(rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
381 			 0, 0));
382 }
383 
384 /*
385  * llc_seq2slot() --- We only allocate enough memory to hold the window. This
386  * introduces the necessity to keep track of two ``pointers''
387  *
388  *        o llcl_freeslot     the next free slot to be used
389  *                            this one advances modulo llcl_window
390  *        o llcl_projvs       the V(S) associated with the next frame
391  *                            to be set via llcl_freeslot
392  *                            this one advances modulo LLC_MAX_SEQUENCE
393  *
394  * A new frame is inserted at llcl_output_buffers[llcl_freeslot], after
395  * which both llcl_freeslot and llcl_projvs are incremented.
396  *
397  * The slot sl(sn) for any given sequence number sn is given by
398  *
399  *        sl(sn) = (llcl_freeslot + llcl_window - 1 - (llcl_projvs +
400  *                  LLC_MAX_SEQUENCE- sn) % LLC_MAX_SEQUENCE) %
401  *                  llcl_window
402  *
403  * i.e. we first calculate the number of frames we need to ``go back''
404  * from the current one (really the next one, but that doesn't matter as
405  * llcl_projvs is likewise of by plus one) and subtract that from the
406  * pointer to the most recently taken frame (llcl_freeslot - 1).
407  */
408 
409 short
410 llc_seq2slot(struct llc_linkcb *linkp, short seqn)
411 {
412 	register sn = 0;
413 
414 	sn = (linkp->llcl_freeslot + linkp->llcl_window -
415 	      (linkp->llcl_projvs + LLC_MAX_SEQUENCE - seqn) %
416 	      LLC_MAX_SEQUENCE) % linkp->llcl_window;
417 
418 	return sn;
419 }
420 
421 /*
422  * LLC2 link state handler
423  *
424  * There is in most cases one function per LLC2 state. The LLC2 standard
425  * ISO 8802-2 allows in some cases for ambiguities, i.e. we have the choice
426  * to do one thing or the other. Right now I have just chosen one but have also
427  * indicated the spot by "multiple possibilities". One could make the behavior
428  * in those cases configurable, allowing the superuser to enter a profile word
429  * (32/64 bits, whatever is needed) that would suit her needs [I quite like
430  * that idea, perhaps I'll get around to it].
431  *
432  * [Preceeding each state handler function is the description as taken from
433  * ISO 8802-2, section 7.9.2.1]
434  */
435 
436 /*
437  * ADM --- The connection component is in the asynchronous disconnected mode.
438  *         It can accept an SABME PDU from a remote LLC SSAP or, at the request
439  *         of the service access point user, can initiate an SABME PDU
440  *         transmission to a remote LLC DSAP, to establish a data link
441  *         connection. It also responds to a DISC command PDU and to any
442  *         command PDU with the P bit set to ``1''.
443  */
444 int
445 llc_state_ADM(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
446 	      int cmdrsp, int pollfinal)
447 {
448 	int action = 0;
449 
450 	switch(frame_kind + cmdrsp) {
451 	case NL_CONNECT_REQUEST:
452 		llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
453 		LLC_SETFLAG(linkp, P, pollfinal);
454 		LLC_SETFLAG(linkp, S, 0);
455 		linkp->llcl_retry = 0;
456 		LLC_NEWSTATE(linkp, SETUP);
457 		break;
458 	case LLCFT_SABME + LLC_CMD:
459 		/*
460 		 * ISO 8802-2, table 7-1, ADM state says to set
461 		 * the P flag, yet this will cause an SABME [P] to be
462 		 * answered with an UA only, not an UA [F], all
463 		 * other `disconnected' states set the F flag, so ...
464 		 */
465 		LLC_SETFLAG(linkp, F, pollfinal);
466 		LLC_NEWSTATE(linkp, CONN);
467 		action = LLC_CONNECT_INDICATION;
468 		break;
469 	case LLCFT_DISC + LLC_CMD:
470 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
471 		break;
472 	default:
473 		if (cmdrsp == LLC_CMD && pollfinal == 1)
474 			llc_send(linkp, LLCFT_DM, LLC_RSP, 1);
475 		/* remain in ADM state */
476 	}
477 
478 	return action;
479 }
480 
481 /*
482  * CONN --- The local connection component has received an SABME PDU from a
483  *          remote LLC SSAP, and it is waiting for the local user to accept or
484  *          refuse the connection.
485  */
486 int
487 llc_state_CONN(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
488 	       int cmdrsp, int pollfinal)
489 {
490 	int action = 0;
491 
492 	switch(frame_kind + cmdrsp) {
493 	case NL_CONNECT_RESPONSE:
494 		llc_send(linkp, LLCFT_UA, LLC_RSP, LLC_GETFLAG(linkp, F));
495 		LLC_RESETCOUNTER(linkp);
496 		LLC_SETFLAG(linkp, P, 0);
497 		LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
498 		LLC_NEWSTATE(linkp, NORMAL);
499 		break;
500 	case NL_DISCONNECT_REQUEST:
501 		llc_send(linkp, LLCFT_DM, LLC_RSP, LLC_GETFLAG(linkp, F));
502 		LLC_NEWSTATE(linkp, ADM);
503 		break;
504 	case LLCFT_SABME + LLC_CMD:
505 		LLC_SETFLAG(linkp, F, pollfinal);
506 		break;
507 	case LLCFT_DM + LLC_RSP:
508 		LLC_NEWSTATE(linkp, ADM);
509 		action = LLC_DISCONNECT_INDICATION;
510 		break;
511 	/* all other frames effect nothing here */
512 	}
513 
514 	return action;
515 }
516 
517 /*
518  * RESET_WAIT --- The local connection component is waiting for the local user
519  *                 to indicate a RESET_REQUEST or a DISCONNECT_REQUEST.
520  */
521 int
522 llc_state_RESET_WAIT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
523 		     int cmdrsp, int pollfinal)
524 {
525 	int action = 0;
526 
527 	switch(frame_kind + cmdrsp) {
528 	case NL_RESET_REQUEST:
529 		if (LLC_GETFLAG(linkp, S) == 0) {
530 			llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
531 			LLC_SETFLAG(linkp, P, pollfinal);
532 			LLC_START_ACK_TIMER(linkp);
533 			linkp->llcl_retry = 0;
534 			LLC_NEWSTATE(linkp, RESET);
535 		} else {
536 			llc_send(linkp, LLCFT_UA, LLC_RSP,
537 				      LLC_GETFLAG(linkp, F));
538 			LLC_RESETCOUNTER(linkp);
539 			LLC_SETFLAG(linkp, P, 0);
540 			LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
541 			LLC_NEWSTATE(linkp, NORMAL);
542 			action = LLC_RESET_CONFIRM;
543 		}
544 		break;
545 	case NL_DISCONNECT_REQUEST:
546 		if (LLC_GETFLAG(linkp, S) == 0) {
547 			llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
548 			LLC_SETFLAG(linkp, P, pollfinal);
549 			LLC_START_ACK_TIMER(linkp);
550 			linkp->llcl_retry = 0;
551 			LLC_NEWSTATE(linkp, D_CONN);
552 		} else {
553 			llc_send(linkp, LLCFT_DM, LLC_RSP,
554 				      LLC_GETFLAG(linkp, F));
555 			LLC_NEWSTATE(linkp, ADM);
556 		}
557 		break;
558 	case LLCFT_DM + LLC_RSP:
559 		LLC_NEWSTATE(linkp, ADM);
560 		action = LLC_DISCONNECT_INDICATION;
561 		break;
562 	case LLCFT_SABME + LLC_CMD:
563 		LLC_SETFLAG(linkp, S, 1);
564 		LLC_SETFLAG(linkp, F, pollfinal);
565 		break;
566 	case LLCFT_DISC + LLC_CMD:
567 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
568 		LLC_NEWSTATE(linkp, ADM);
569 		action = LLC_DISCONNECT_INDICATION;
570 		break;
571 	}
572 
573 	return action;
574 }
575 
576 /*
577  * RESET_CHECK --- The local connection component is waiting for the local user
578  *                 to accept or refuse a remote reset request.
579  */
580 int
581 llc_state_RESET_CHECK(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
582 		      int cmdrsp, int pollfinal)
583 {
584 	int action = 0;
585 
586 	switch(frame_kind + cmdrsp) {
587 	case NL_RESET_RESPONSE:
588 		llc_send(linkp, LLCFT_UA, LLC_RSP, LLC_GETFLAG(linkp, F));
589 		LLC_RESETCOUNTER(linkp);
590 		LLC_SETFLAG(linkp, P, 0);
591 		LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
592 		LLC_NEWSTATE(linkp, NORMAL);
593 		break;
594 	case NL_DISCONNECT_REQUEST:
595 		llc_send(linkp, LLCFT_DM, LLC_RSP, LLC_GETFLAG(linkp, F));
596 		LLC_NEWSTATE(linkp, ADM);
597 		break;
598 	case LLCFT_DM + LLC_RSP:
599 		action = LLC_DISCONNECT_INDICATION;
600 		break;
601 	case LLCFT_SABME + LLC_CMD:
602 		LLC_SETFLAG(linkp, F, pollfinal);
603 		break;
604 	case LLCFT_DISC + LLC_CMD:
605 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
606 		LLC_NEWSTATE(linkp, ADM);
607 		action = LLC_DISCONNECT_INDICATION;
608 		break;
609 	}
610 
611 	return action;
612 }
613 
614 /*
615  * SETUP --- The connection component has transmitted an SABME command PDU to a
616  *           remote LLC DSAP and is waiting for a reply.
617  */
618 int
619 llc_state_SETUP(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
620 		int cmdrsp, int pollfinal)
621 {
622 	int action = 0;
623 
624 	switch(frame_kind + cmdrsp) {
625 	case LLCFT_SABME + LLC_CMD:
626 		LLC_RESETCOUNTER(linkp);
627 		llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
628 		LLC_SETFLAG(linkp, S, 1);
629 		break;
630 	case LLCFT_UA + LLC_RSP:
631 		if (LLC_GETFLAG(linkp, P) == pollfinal) {
632 			LLC_STOP_ACK_TIMER(linkp);
633 			LLC_RESETCOUNTER(linkp);
634 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
635 			LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
636 			LLC_NEWSTATE(linkp, NORMAL);
637 			action = LLC_CONNECT_CONFIRM;
638 		}
639 		break;
640 	case LLC_ACK_TIMER_EXPIRED:
641 		if (LLC_GETFLAG(linkp, S) == 1) {
642 			LLC_SETFLAG(linkp, P, 0);
643 			LLC_SETFLAG(linkp, REMOTE_BUSY, 0),
644 			LLC_NEWSTATE(linkp, NORMAL);
645 			action = LLC_CONNECT_CONFIRM;
646 		} else if (linkp->llcl_retry < llc_n2) {
647 			llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
648 			LLC_SETFLAG(linkp, P, pollfinal);
649 			LLC_START_ACK_TIMER(linkp);
650 			linkp->llcl_retry++;
651 		} else {
652 			LLC_NEWSTATE(linkp, ADM);
653 			action = LLC_DISCONNECT_INDICATION;
654 		}
655 		break;
656 	case LLCFT_DISC + LLC_CMD:
657 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
658 		LLC_STOP_ACK_TIMER(linkp);
659 		LLC_NEWSTATE(linkp, ADM);
660 		action = LLC_DISCONNECT_INDICATION;
661 		break;
662 	case LLCFT_DM + LLC_RSP:
663 		LLC_STOP_ACK_TIMER(linkp);
664 		LLC_NEWSTATE(linkp, ADM);
665 		action = LLC_DISCONNECT_INDICATION;
666 		break;
667 	}
668 
669 	return action;
670 }
671 
672 /*
673  * RESET --- As a result of a service access point user request or the receipt
674  *           of a FRMR response PDU, the local connection component has sent an
675  *           SABME command PDU to the remote LLC DSAP to reset the data link
676  *           connection and is waiting for a reply.
677  */
678 int
679 llc_state_RESET(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
680 		int cmdrsp, int pollfinal)
681 {
682 	int action = 0;
683 
684 	switch(frame_kind + cmdrsp) {
685 	case LLCFT_SABME + LLC_CMD:
686 		LLC_RESETCOUNTER(linkp);
687 		LLC_SETFLAG(linkp, S, 1);
688 		llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
689 		break;
690 	case LLCFT_UA + LLC_RSP:
691 		if (LLC_GETFLAG(linkp, P) == pollfinal) {
692 			LLC_STOP_ACK_TIMER(linkp);
693 			LLC_RESETCOUNTER(linkp);
694 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
695 			LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
696 			LLC_NEWSTATE(linkp, NORMAL);
697 			action = LLC_RESET_CONFIRM;
698 		}
699 		break;
700 	case LLC_ACK_TIMER_EXPIRED:
701 		if (LLC_GETFLAG(linkp, S) == 1) {
702 			LLC_SETFLAG(linkp, P, 0);
703 			LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
704 			LLC_NEWSTATE(linkp, NORMAL);
705 			action = LLC_RESET_CONFIRM;
706 		} else if (linkp->llcl_retry < llc_n2) {
707 			llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
708 			LLC_SETFLAG(linkp, P, pollfinal);
709 			LLC_START_ACK_TIMER(linkp);
710 			linkp->llcl_retry++;
711 		} else {
712 			LLC_NEWSTATE(linkp, ADM);
713 			action = LLC_DISCONNECT_INDICATION;
714 		}
715 		break;
716 	case LLCFT_DISC + LLC_CMD:
717 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
718 		LLC_STOP_ACK_TIMER(linkp);
719 		LLC_NEWSTATE(linkp, ADM);
720 		action = LLC_DISCONNECT_INDICATION;
721 		break;
722 	case LLCFT_DM + LLC_RSP:
723 		LLC_STOP_ACK_TIMER(linkp);
724 		LLC_NEWSTATE(linkp, ADM);
725 		action = LLC_DISCONNECT_INDICATION;
726 		break;
727 	}
728 
729 	return action;
730 }
731 
732 /*
733  * D_CONN --- At the request of the service access point user, the local LLC
734  *            has sent a DISC command PDU to the remote LLC DSAP and is waiting
735  *            for a reply.
736  */
737 int
738 llc_state_D_CONN(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
739 		 int cmdrsp, int pollfinal)
740 {
741 	int action = 0;
742 
743 	switch(frame_kind + cmdrsp) {
744 	case LLCFT_SABME + LLC_CMD:
745 		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
746 		LLC_STOP_ACK_TIMER(linkp);
747 		LLC_NEWSTATE(linkp, ADM);
748 		break;
749 	case LLCFT_UA + LLC_RSP:
750 		if (LLC_GETFLAG(linkp, P) == pollfinal) {
751 			LLC_STOP_ACK_TIMER(linkp);
752 			LLC_NEWSTATE(linkp, ADM);
753 		}
754 		break;
755 	case LLCFT_DISC + LLC_CMD:
756 		llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
757 		break;
758 	case LLCFT_DM + LLC_RSP:
759 		LLC_STOP_ACK_TIMER(linkp);
760 		LLC_NEWSTATE(linkp, ADM);
761 		break;
762 	case LLC_ACK_TIMER_EXPIRED:
763 		if (linkp->llcl_retry < llc_n2) {
764 			llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
765 			LLC_SETFLAG(linkp, P, pollfinal);
766 			LLC_START_ACK_TIMER(linkp);
767 			linkp->llcl_retry++;
768 		} else LLC_NEWSTATE(linkp, ADM);
769 		break;
770 	}
771 
772 	return action;
773 }
774 
775 /*
776  * ERROR --- The local connection component has detected an error in a received
777  *           PDU and has sent a FRMR response PDU. It is waiting for a reply from
778  *           the remote connection component.
779  */
780 int
781 llc_state_ERROR(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
782 		int cmdrsp, int pollfinal)
783 {
784 	int action = 0;
785 
786 	switch(frame_kind + cmdrsp) {
787 	case LLCFT_SABME + LLC_CMD:
788 		LLC_STOP_ACK_TIMER(linkp);
789 		LLC_NEWSTATE(linkp, RESET_CHECK);
790 		action = LLC_RESET_INDICATION_REMOTE;
791 		break;
792 	case LLCFT_DISC + LLC_CMD:
793 		llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
794 		LLC_STOP_ACK_TIMER(linkp);
795 		LLC_NEWSTATE(linkp, ADM);
796 		action = LLC_DISCONNECT_INDICATION;
797 		break;
798 	case LLCFT_DM + LLC_RSP:
799 		LLC_STOP_ACK_TIMER(linkp);
800 		LLC_NEWSTATE(linkp, ADM);
801 		action = LLC_DISCONNECT_INDICATION;
802 		break;
803 	case LLCFT_FRMR + LLC_RSP:
804 		LLC_STOP_ACK_TIMER(linkp);
805 		LLC_SETFLAG(linkp, S, 0);
806 		LLC_NEWSTATE(linkp, RESET_WAIT);
807 		action = LLC_FRMR_RECEIVED;
808 		break;
809 	case LLC_ACK_TIMER_EXPIRED:
810 		if (linkp->llcl_retry < llc_n2) {
811 			llc_send(linkp, LLCFT_FRMR, LLC_RSP, 0);
812 			LLC_START_ACK_TIMER(linkp);
813 			linkp->llcl_retry++;
814 		} else {
815 			LLC_SETFLAG(linkp, S, 0);
816 			LLC_NEWSTATE(linkp, RESET_WAIT);
817 			action = LLC_RESET_INDICATION_LOCAL;
818 		}
819 		break;
820 	default:
821 		if (cmdrsp == LLC_CMD){
822 			llc_send(linkp, LLCFT_FRMR, LLC_RSP, pollfinal);
823 			LLC_START_ACK_TIMER(linkp);
824 		}
825 		break;
826 
827 	}
828 
829 	return action;
830 }
831 
832 /*
833  * NORMAL, BUSY, REJECT, AWAIT, AWAIT_BUSY, and AWAIT_REJECT all share
834  * a common core state handler.
835  */
836 int
837 llc_state_NBRAcore(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
838 		   int cmdrsp, int pollfinal)
839 {
840 	int action = 0;
841 
842 	switch(frame_kind + cmdrsp) {
843 	case NL_DISCONNECT_REQUEST:
844 		llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
845 		LLC_SETFLAG(linkp, P, pollfinal);
846 		LLC_STOP_ALL_TIMERS(linkp);
847 		LLC_START_ACK_TIMER(linkp);
848 		linkp->llcl_retry = 0;
849 		LLC_NEWSTATE(linkp, D_CONN);
850 		break;
851 	case NL_RESET_REQUEST:
852 		llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
853 		LLC_SETFLAG(linkp, P, pollfinal);
854 		LLC_STOP_ALL_TIMERS(linkp);
855 		LLC_START_ACK_TIMER(linkp);
856 		linkp->llcl_retry = 0;
857 		LLC_SETFLAG(linkp, S, 0);
858 		LLC_NEWSTATE(linkp, RESET);
859 		break;
860 	case LLCFT_SABME + LLC_CMD:
861 		LLC_SETFLAG(linkp, F, pollfinal);
862 		LLC_STOP_ALL_TIMERS(linkp);
863 		LLC_NEWSTATE(linkp, RESET_CHECK);
864 		action = LLC_RESET_INDICATION_REMOTE;
865 		break;
866 	case LLCFT_DISC + LLC_CMD:
867 		llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
868 		LLC_STOP_ALL_TIMERS(linkp);
869 		LLC_NEWSTATE(linkp, ADM);
870 		action = LLC_DISCONNECT_INDICATION;
871 		break;
872 	case LLCFT_FRMR + LLC_RSP:
873 		LLC_STOP_ALL_TIMERS(linkp);
874 		LLC_SETFLAG(linkp, S, 0);
875 		LLC_NEWSTATE(linkp, RESET_WAIT);
876 		action =  LLC_FRMR_RECEIVED;
877 		break;
878 	case LLCFT_DM + LLC_RSP:
879 		LLC_STOP_ALL_TIMERS(linkp);
880 		LLC_NEWSTATE(linkp, ADM);
881 		action = LLC_DISCONNECT_INDICATION;
882 		break;
883 	case LLC_INVALID_NR + LLC_CMD:
884 	case LLC_INVALID_NS + LLC_CMD:
885 		LLC_SETFRMR(linkp, frame, cmdrsp,
886 			 (frame_kind == LLC_INVALID_NR ? LLC_FRMR_Z :
887 			  (LLC_FRMR_V | LLC_FRMR_W)));
888 		llc_send(linkp, LLCFT_FRMR, LLC_RSP, pollfinal);
889 		LLC_STOP_ALL_TIMERS(linkp);
890 		LLC_START_ACK_TIMER(linkp);
891 		linkp->llcl_retry = 0;
892 		LLC_NEWSTATE(linkp, ERROR);
893 		action = LLC_FRMR_SENT;
894 		break;
895 	case LLC_INVALID_NR + LLC_RSP:
896 	case LLC_INVALID_NS + LLC_RSP:
897 	case LLCFT_UA + LLC_RSP:
898 	case LLC_BAD_PDU: {
899 		char frmrcause = 0;
900 
901 		switch (frame_kind) {
902 		case LLC_INVALID_NR: frmrcause = LLC_FRMR_Z; break;
903 		case LLC_INVALID_NS: frmrcause = LLC_FRMR_V | LLC_FRMR_W; break;
904 		default: frmrcause = LLC_FRMR_W;
905 		}
906 		LLC_SETFRMR(linkp, frame, cmdrsp, frmrcause);
907 		llc_send(linkp, LLCFT_FRMR, LLC_RSP, 0);
908 		LLC_STOP_ALL_TIMERS(linkp);
909 		LLC_START_ACK_TIMER(linkp);
910 		linkp->llcl_retry = 0;
911 		LLC_NEWSTATE(linkp, ERROR);
912 		action = LLC_FRMR_SENT;
913 		break;
914 	}
915 	default:
916 		if (cmdrsp == LLC_RSP && pollfinal == 1 &&
917 		    LLC_GETFLAG(linkp, P) == 0) {
918 			LLC_SETFRMR(linkp, frame, cmdrsp, LLC_FRMR_W);
919 			LLC_STOP_ALL_TIMERS(linkp);
920 			LLC_START_ACK_TIMER(linkp);
921 			linkp->llcl_retry = 0;
922 			LLC_NEWSTATE(linkp, ERROR);
923 			action = LLC_FRMR_SENT;
924 		}
925 		break;
926 	case LLC_P_TIMER_EXPIRED:
927 	case LLC_ACK_TIMER_EXPIRED:
928 	case LLC_REJ_TIMER_EXPIRED:
929 	case LLC_BUSY_TIMER_EXPIRED:
930 		if (linkp->llcl_retry >= llc_n2) {
931 			LLC_STOP_ALL_TIMERS(linkp);
932 			LLC_SETFLAG(linkp, S, 0);
933 			LLC_NEWSTATE(linkp, RESET_WAIT);
934 			action = LLC_RESET_INDICATION_LOCAL;
935 		}
936 		break;
937 	}
938 
939 	return action;
940 }
941 
942 /*
943  * NORMAL --- A data link connection exists between the local LLC service access
944  *            point and the remote LLC service access point. Sending and
945  *            reception of information and supervisory PDUs can be performed.
946  */
947 int
948 llc_state_NORMAL(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
949 		 int cmdrsp, int pollfinal)
950 {
951 	int action = LLC_PASSITON;
952 
953 	switch(frame_kind + cmdrsp) {
954 	case NL_DATA_REQUEST:
955 		if (LLC_GETFLAG(linkp, REMOTE_BUSY) == 0) {
956 #ifdef not_now
957 			if (LLC_GETFLAG(linkp, P) == 0) {
958 				/* multiple possibilities */
959 				llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
960 				LLC_START_P_TIMER(linkp);
961 				if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
962 					LLC_START_ACK_TIMER(linkp);
963 			} else {
964 #endif
965 				/* multiple possibilities */
966 				llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
967 				if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
968 					LLC_START_ACK_TIMER(linkp);
969 #ifdef not_now
970 			}
971 #endif
972 			action = 0;
973 		}
974 		break;
975 	case LLC_LOCAL_BUSY_DETECTED:
976 		if (LLC_GETFLAG(linkp, P) == 0) {
977 			/* multiple possibilities --- action-wise */
978 			/* multiple possibilities --- CMD/RSP-wise */
979 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
980 			LLC_START_P_TIMER(linkp);
981 			LLC_SETFLAG(linkp, DATA, 0);
982 			LLC_NEWSTATE(linkp, BUSY);
983 			action = 0;
984 		} else {
985 			/* multiple possibilities --- CMD/RSP-wise */
986 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
987 			LLC_SETFLAG(linkp, DATA, 0);
988 			LLC_NEWSTATE(linkp, BUSY);
989 			action = 0;
990 		}
991 		break;
992 	case LLC_INVALID_NS + LLC_CMD:
993 	case LLC_INVALID_NS + LLC_RSP: {
994 		register int p = LLC_GETFLAG(linkp, P);
995 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
996 
997 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
998 			llc_send(linkp, LLCFT_REJ, LLC_RSP, 1);
999 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1000 			LLC_START_REJ_TIMER(linkp);
1001 			LLC_NEWSTATE(linkp, REJECT);
1002 			action = 0;
1003 		} else if (pollfinal == 0 && p == 1) {
1004 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
1005 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1006 			LLC_START_REJ_TIMER(linkp);
1007 			LLC_NEWSTATE(linkp, REJECT);
1008 			action = 0;
1009 		} else if ((pollfinal == 0 && p == 0) ||
1010 			   (pollfinal == 1 && p == 1 && cmdrsp == LLC_RSP)) {
1011 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
1012 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1013 			LLC_START_P_TIMER(linkp);
1014 			LLC_START_REJ_TIMER(linkp);
1015 			if (cmdrsp == LLC_RSP && pollfinal == 1) {
1016 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1017 			} else action = 0;
1018 			LLC_NEWSTATE(linkp, REJECT);
1019 		}
1020 		break;
1021 	}
1022 	case LLCFT_INFO + LLC_CMD:
1023 	case LLCFT_INFO + LLC_RSP: {
1024 		register int p = LLC_GETFLAG(linkp, P);
1025 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1026 
1027 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1028 			LLC_INC(linkp->llcl_vr);
1029 			LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
1030 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1031 			action = LLC_DATA_INDICATION;
1032 		} else if (pollfinal == 0 && p == 1) {
1033 			LLC_INC(linkp->llcl_vr);
1034 			LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
1035 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1036 			action = LLC_DATA_INDICATION;
1037 		} else if ((pollfinal == 0 && p == 0 && cmdrsp == LLC_CMD) ||
1038 			   (pollfinal == p && cmdrsp == LLC_RSP)) {
1039 			LLC_INC(linkp->llcl_vr);
1040 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1041 			LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
1042 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1043 			if (cmdrsp == LLC_RSP && pollfinal == 1)
1044 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1045 			action = LLC_DATA_INDICATION;
1046 		}
1047 		break;
1048 	}
1049 	case LLCFT_RR + LLC_CMD:
1050 	case LLCFT_RR + LLC_RSP: {
1051 		register int p = LLC_GETFLAG(linkp, P);
1052 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1053 
1054 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1055 			LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
1056 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1057 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1058 		} else if ((pollfinal == 0) ||
1059 			   (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
1060 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1061 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1062 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1063 		}
1064 		break;
1065 	}
1066 	case LLCFT_RNR + LLC_CMD:
1067 	case LLCFT_RNR + LLC_RSP: {
1068 		register int p = LLC_GETFLAG(linkp, P);
1069 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1070 
1071 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1072 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1073 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1074 			LLC_SET_REMOTE_BUSY(linkp, action);
1075 		} else if ((pollfinal == 0) ||
1076 			   (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
1077 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1078 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1079 			LLC_SET_REMOTE_BUSY(linkp, action);
1080 		}
1081 		break;
1082 	}
1083 	case LLCFT_REJ + LLC_CMD:
1084 	case LLCFT_REJ + LLC_RSP: {
1085 		register int p = LLC_GETFLAG(linkp, P);
1086 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1087 
1088 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1089 			linkp->llcl_vs = nr;
1090 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1091 			llc_resend(linkp, LLC_RSP, 1);
1092 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1093 		} else if (pollfinal == 0 && p == 1) {
1094 			linkp->llcl_vs = nr;
1095 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1096 			llc_resend(linkp, LLC_CMD, 0);
1097 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1098 		} else if ((pollfinal == 0 && p == 0 && cmdrsp == LLC_CMD) ||
1099 			   (pollfinal == p && cmdrsp == LLC_RSP)) {
1100 			linkp->llcl_vs = nr;
1101 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1102 			LLC_START_P_TIMER(linkp);
1103 			llc_resend(linkp, LLC_CMD, 1);
1104 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1105 		}
1106 		break;
1107 	}
1108 	case NL_INITIATE_PF_CYCLE:
1109 		if (LLC_GETFLAG(linkp, P) == 0) {
1110 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1111 			LLC_START_P_TIMER(linkp);
1112 			action = 0;
1113 		}
1114 		break;
1115 	case LLC_P_TIMER_EXPIRED:
1116 		if (linkp->llcl_retry < llc_n2) {
1117 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1118 			LLC_START_P_TIMER(linkp);
1119 			linkp->llcl_retry++;
1120 			LLC_NEWSTATE(linkp, AWAIT);
1121 			action = 0;
1122 		}
1123 		break;
1124 	case LLC_ACK_TIMER_EXPIRED:
1125 	case LLC_BUSY_TIMER_EXPIRED:
1126 		if ((LLC_GETFLAG(linkp, P) == 0)
1127 		    && (linkp->llcl_retry < llc_n2)) {
1128 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1129 			LLC_START_P_TIMER(linkp);
1130 			linkp->llcl_retry++;
1131 			LLC_NEWSTATE(linkp, AWAIT);
1132 			action = 0;
1133 		}
1134 		break;
1135 	}
1136 	if (action == LLC_PASSITON)
1137 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
1138 					    cmdrsp, pollfinal);
1139 
1140 	return action;
1141 }
1142 
1143 /*
1144  * BUSY --- A data link connection exists between the local LLC service access
1145  *          point and the remote LLC service access point. I PDUs may be sent.
1146  *          Local conditions make it likely that the information feld of
1147  *          received I PDUs will be ignored. Supervisory PDUs may be both sent
1148  *          and received.
1149  */
1150 int
1151 llc_state_BUSY(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
1152 	       int cmdrsp, int pollfinal)
1153 {
1154 	int action = LLC_PASSITON;
1155 
1156 	switch(frame_kind + cmdrsp) {
1157 	case NL_DATA_REQUEST:
1158 		if (LLC_GETFLAG(linkp, REMOTE_BUSY) == 0)
1159 			if (LLC_GETFLAG(linkp, P) == 0) {
1160 				llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
1161 				LLC_START_P_TIMER(linkp);
1162 				if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
1163 					LLC_START_ACK_TIMER(linkp);
1164 				action = 0;
1165 			} else {
1166 				llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
1167 				if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
1168 					LLC_START_ACK_TIMER(linkp);
1169 				action = 0;
1170 			}
1171 		break;
1172 	case LLC_LOCAL_BUSY_CLEARED: {
1173 		register int p = LLC_GETFLAG(linkp, P);
1174 		register int df = LLC_GETFLAG(linkp, DATA);
1175 
1176 		switch (df) {
1177 		case 1:
1178 			if (p == 0) {
1179 				/* multiple possibilities */
1180 				llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
1181 				LLC_START_REJ_TIMER(linkp);
1182 				LLC_START_P_TIMER(linkp);
1183 				LLC_NEWSTATE(linkp, REJECT);
1184 				action = 0;
1185 			} else {
1186 				llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
1187 				LLC_START_REJ_TIMER(linkp);
1188 				LLC_NEWSTATE(linkp, REJECT);
1189 				action = 0;
1190 			}
1191 			break;
1192 		case 0:
1193 			if (p == 0) {
1194 				/* multiple possibilities */
1195 				llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1196 				LLC_START_P_TIMER(linkp);
1197 				LLC_NEWSTATE(linkp, NORMAL);
1198 				action = 0;
1199 			} else {
1200 				llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1201 				LLC_NEWSTATE(linkp, NORMAL);
1202 				action = 0;
1203 			}
1204 			break;
1205 		case 2:
1206 			if (p == 0) {
1207 				/* multiple possibilities */
1208 				llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1209 				LLC_START_P_TIMER(linkp);
1210 				LLC_NEWSTATE(linkp, REJECT);
1211 				action = 0;
1212 			} else {
1213 				llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1214 				LLC_NEWSTATE(linkp, REJECT);
1215 				action =0;
1216 			}
1217 			break;
1218 		}
1219 		break;
1220 	}
1221 	case LLC_INVALID_NS + LLC_CMD:
1222 	case LLC_INVALID_NS + LLC_RSP: {
1223 		register int p = LLC_GETFLAG(linkp, P);
1224 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1225 
1226 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1227 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1228 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1229 			if (LLC_GETFLAG(linkp, DATA) == 0)
1230 				LLC_SETFLAG(linkp, DATA, 1);
1231 			action = 0;
1232 		} else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
1233 			   (cmdrsp == LLC_RSP && pollfinal == p)) {
1234 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1235 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1236 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1237 			if (LLC_GETFLAG(linkp, DATA) == 0)
1238 				LLC_SETFLAG(linkp, DATA, 1);
1239 			if (cmdrsp == LLC_RSP && pollfinal == 1) {
1240 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1241 			} else action = 0;
1242 		} else if (pollfinal == 0 && p == 1) {
1243 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1244 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1245 			if (LLC_GETFLAG(linkp, DATA) == 0)
1246 				LLC_SETFLAG(linkp, DATA, 1);
1247 			action = 0;
1248 		}
1249 		break;
1250 	}
1251 	case LLCFT_INFO + LLC_CMD:
1252 	case LLCFT_INFO + LLC_RSP: {
1253 		register int p = LLC_GETFLAG(linkp, P);
1254 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1255 
1256 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1257 			LLC_INC(linkp->llcl_vr);
1258 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1259 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1260 			if (LLC_GETFLAG(linkp, DATA) == 2)
1261 				LLC_STOP_REJ_TIMER(linkp);
1262 			LLC_SETFLAG(linkp, DATA, 0);
1263 			action = LLC_DATA_INDICATION;
1264 		} else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
1265 			   (cmdrsp == LLC_RSP && pollfinal == p)) {
1266 			LLC_INC(linkp->llcl_vr);
1267 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1268 			LLC_START_P_TIMER(linkp);
1269 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1270 			if (LLC_GETFLAG(linkp, DATA) == 2)
1271 				LLC_STOP_REJ_TIMER(linkp);
1272 			if (cmdrsp == LLC_RSP && pollfinal == 1)
1273 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1274 			action = LLC_DATA_INDICATION;
1275 		} else if (pollfinal == 0 && p == 1) {
1276 			LLC_INC(linkp->llcl_vr);
1277 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1278 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1279 			if (LLC_GETFLAG(linkp, DATA) == 2)
1280 				LLC_STOP_REJ_TIMER(linkp);
1281 			LLC_SETFLAG(linkp, DATA, 0);
1282 			action = LLC_DATA_INDICATION;
1283 		}
1284 		break;
1285 	}
1286 	case LLCFT_RR + LLC_CMD:
1287 	case LLCFT_RR + LLC_RSP:
1288 	case LLCFT_RNR + LLC_CMD:
1289 	case LLCFT_RNR + LLC_RSP: {
1290 		register int p = LLC_GETFLAG(linkp, P);
1291 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1292 
1293 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1294 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1295 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1296 			if (frame_kind == LLCFT_RR) {
1297 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1298 			} else {
1299 				LLC_SET_REMOTE_BUSY(linkp, action);
1300 			}
1301 		} else if (pollfinal = 0 ||
1302 			   (cmdrsp == LLC_RSP && pollfinal == 1)) {
1303 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1304 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1305 			if (frame_kind == LLCFT_RR) {
1306 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1307 			} else  {
1308 				LLC_SET_REMOTE_BUSY(linkp, action);
1309 			}
1310 		}
1311 		break;
1312 	}
1313 	case LLCFT_REJ + LLC_CMD:
1314 	case LLCFT_REJ + LLC_RSP: {
1315 		register int p = LLC_GETFLAG(linkp, P);
1316 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1317 
1318 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1319 			linkp->llcl_vs = nr;
1320 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1321 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1322 			llc_resend(linkp, LLC_CMD, 0);
1323 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1324 		} else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
1325 			   (cmdrsp == LLC_RSP && pollfinal == p)) {
1326 			linkp->llcl_vs = nr;
1327 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1328 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1329 			llc_resend(linkp, LLC_CMD, 0);
1330 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1331 		} else if (pollfinal == 0 && p == 1) {
1332 			linkp->llcl_vs = nr;
1333 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1334 			llc_resend(linkp, LLC_CMD, 0);
1335 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1336 		}
1337 		break;
1338 	}
1339 	case NL_INITIATE_PF_CYCLE:
1340 		if (LLC_GETFLAG(linkp, P) == 0) {
1341 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1342 			LLC_START_P_TIMER(linkp);
1343 			action = 0;
1344 		}
1345 		break;
1346 	case LLC_P_TIMER_EXPIRED:
1347 		/* multiple possibilities */
1348 		if (linkp->llcl_retry < llc_n2) {
1349 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1350 			LLC_START_P_TIMER(linkp);
1351 			linkp->llcl_retry++;
1352 			LLC_NEWSTATE(linkp, AWAIT_BUSY);
1353 			action = 0;
1354 		}
1355 		break;
1356 	case LLC_ACK_TIMER_EXPIRED:
1357 	case LLC_BUSY_TIMER_EXPIRED:
1358 		if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
1359 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1360 			LLC_START_P_TIMER(linkp);
1361 			linkp->llcl_retry++;
1362 			LLC_NEWSTATE(linkp, AWAIT_BUSY);
1363 			action = 0;
1364 		}
1365 		break;
1366 	case LLC_REJ_TIMER_EXPIRED:
1367 		if (linkp->llcl_retry < llc_n2)
1368 			if (LLC_GETFLAG(linkp, P) == 0) {
1369 				/* multiple possibilities */
1370 				llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1371 				LLC_START_P_TIMER(linkp);
1372 				linkp->llcl_retry++;
1373 				LLC_SETFLAG(linkp, DATA, 1);
1374 				LLC_NEWSTATE(linkp, AWAIT_BUSY);
1375 				action = 0;
1376 			} else{
1377 				LLC_SETFLAG(linkp, DATA, 1);
1378 				LLC_NEWSTATE(linkp, BUSY);
1379 				action = 0;
1380 			}
1381 
1382 		break;
1383 	}
1384 	if (action == LLC_PASSITON)
1385 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
1386 					    cmdrsp, pollfinal);
1387 
1388 	return action;
1389 }
1390 
1391 /*
1392  * REJECT --- A data link connection exists between the local LLC service
1393  *            access point and the remote LLC service access point. The local
1394  *            connection component has requested that the remote connection
1395  *            component resend a specific I PDU that the local connection
1396  *            componnent has detected as being out of sequence. Both I PDUs and
1397  *            supervisory PDUs may be sent and received.
1398  */
1399 int
1400 llc_state_REJECT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
1401 		 int cmdrsp, int pollfinal)
1402 {
1403 	int action = LLC_PASSITON;
1404 
1405 	switch(frame_kind + cmdrsp) {
1406 	case NL_DATA_REQUEST:
1407 		if (LLC_GETFLAG(linkp, P) == 0) {
1408 			llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
1409 			LLC_START_P_TIMER(linkp);
1410 			if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
1411 				LLC_START_ACK_TIMER(linkp);
1412 			LLC_NEWSTATE(linkp, REJECT);
1413 			action = 0;
1414 		} else {
1415 			llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
1416 			if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
1417 				LLC_START_ACK_TIMER(linkp);
1418 			LLC_NEWSTATE(linkp, REJECT);
1419 			action = 0;
1420 		}
1421 		break;
1422 	case NL_LOCAL_BUSY_DETECTED:
1423 		if (LLC_GETFLAG(linkp, P) == 0) {
1424 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1425 			LLC_START_P_TIMER(linkp);
1426 			LLC_SETFLAG(linkp, DATA, 2);
1427 			LLC_NEWSTATE(linkp, BUSY);
1428 			action = 0;
1429 		} else {
1430 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1431 			LLC_SETFLAG(linkp, DATA, 2);
1432 			LLC_NEWSTATE(linkp, BUSY);
1433 			action = 0;
1434 		}
1435 		break;
1436 	case LLC_INVALID_NS + LLC_CMD:
1437 	case LLC_INVALID_NS + LLC_RSP: {
1438 		register int p = LLC_GETFLAG(linkp, P);
1439 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1440 
1441 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1442 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1443 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1444 			action = 0;
1445 		} else if (pollfinal == 0 ||
1446 			   (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
1447 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1448 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1449 			if (cmdrsp == LLC_RSP && pollfinal == 1) {
1450 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1451 			} else action = 0;
1452 		}
1453 		break;
1454 	}
1455 	case LLCFT_INFO + LLC_CMD:
1456 	case LLCFT_INFO + LLC_RSP: {
1457 		register int p = LLC_GETFLAG(linkp, P);
1458 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1459 
1460 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1461 			LLC_INC(linkp->llcl_vr);
1462 			LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
1463 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1464 			LLC_STOP_REJ_TIMER(linkp);
1465 			LLC_NEWSTATE(linkp, NORMAL);
1466 			action = LLC_DATA_INDICATION;
1467 		} else if ((cmdrsp = LLC_RSP && pollfinal == p) ||
1468 			   (cmdrsp == LLC_CMD && pollfinal == 0 && p == 0)) {
1469 			LLC_INC(linkp->llcl_vr);
1470 			LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 1);
1471 			LLC_START_P_TIMER(linkp);
1472 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1473 			if (cmdrsp == LLC_RSP && pollfinal == 1)
1474 				LLC_CLEAR_REMOTE_BUSY(linkp, action);
1475 			LLC_STOP_REJ_TIMER(linkp);
1476 			LLC_NEWSTATE(linkp, NORMAL);
1477 			action = LLC_DATA_INDICATION;
1478 		} else if (pollfinal == 0 && p == 1) {
1479 			LLC_INC(linkp->llcl_vr);
1480 			LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
1481 			LLC_STOP_REJ_TIMER(linkp);
1482 			LLC_NEWSTATE(linkp, NORMAL);
1483 			action = LLC_DATA_INDICATION;
1484 		}
1485 		break;
1486 	}
1487 	case LLCFT_RR + LLC_CMD:
1488 	case LLCFT_RR + LLC_RSP: {
1489 		register int p = LLC_GETFLAG(linkp, P);
1490 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1491 
1492 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1493 			LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
1494 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1495 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1496 		} else if (pollfinal == 0 ||
1497 			   (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
1498 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1499 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1500 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1501 		}
1502 		break;
1503 	}
1504 	case LLCFT_RNR + LLC_CMD:
1505 	case LLCFT_RNR + LLC_RSP: {
1506 		register int p = LLC_GETFLAG(linkp, P);
1507 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1508 
1509 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1510 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1511 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1512 			LLC_SET_REMOTE_BUSY(linkp, action);
1513 		} else if (pollfinal == 0 ||
1514 			   (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
1515 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1516 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1517 			action = 0;
1518 		}
1519 		break;
1520 	}
1521 	case LLCFT_REJ + LLC_CMD:
1522 	case LLCFT_REJ + LLC_RSP: {
1523 		register int p = LLC_GETFLAG(linkp, P);
1524 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1525 
1526 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1527 			linkp->llcl_vs = nr;
1528 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1529 			llc_resend(linkp, LLC_RSP, 1);
1530 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1531 		} else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
1532 			   (cmdrsp == LLC_RSP && pollfinal == p)) {
1533 			linkp->llcl_vs = nr;
1534 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1535 			LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
1536 			llc_resend(linkp, LLC_CMD, 0);
1537 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1538 		} else if (pollfinal == 0 && p == 1) {
1539 			linkp->llcl_vs = nr;
1540 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1541 			llc_resend(linkp, LLC_CMD, 0);
1542 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1543 		}
1544 		break;
1545 	}
1546 	case NL_INITIATE_PF_CYCLE:
1547 		if (LLC_GETFLAG(linkp, P) == 0) {
1548 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1549 			LLC_START_P_TIMER(linkp);
1550 			action = 0;
1551 		}
1552 		break;
1553 	case LLC_REJ_TIMER_EXPIRED:
1554 		if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
1555 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
1556 			LLC_START_P_TIMER(linkp);
1557 			LLC_START_REJ_TIMER(linkp);
1558 			linkp->llcl_retry++;
1559 			action = 0;
1560 		}
1561 	case LLC_P_TIMER_EXPIRED:
1562 		if (linkp->llcl_retry < llc_n2) {
1563 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1564 			LLC_START_P_TIMER(linkp);
1565 			LLC_START_REJ_TIMER(linkp);
1566 			linkp->llcl_retry++;
1567 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1568 			action = 0;
1569 		}
1570 		break;
1571 	case LLC_ACK_TIMER_EXPIRED:
1572 	case LLC_BUSY_TIMER_EXPIRED:
1573 		if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
1574 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1575 			LLC_START_P_TIMER(linkp);
1576 			LLC_START_REJ_TIMER(linkp);
1577 			linkp->llcl_retry++;
1578 			/*
1579 			 * I cannot locate the description of RESET_V(S)
1580 			 * in ISO 8802-2, table 7-1, state REJECT, last event,
1581 			 * and  assume they meant to set V(S) to 0 ...
1582 			 */
1583 			linkp->llcl_vs = 0; /* XXX */
1584 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1585 			action = 0;
1586 		}
1587 
1588 		break;
1589 	}
1590 	if (action == LLC_PASSITON)
1591 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
1592 					    cmdrsp, pollfinal);
1593 
1594 	return action;
1595 }
1596 
1597 /*
1598  * AWAIT --- A data link connection exists between the local LLC service access
1599  *           point and the remote LLC service access point. The local LLC is
1600  *           performing a timer recovery operation and has sent a command PDU
1601  *           with the P bit set to ``1'', and is awaiting an acknowledgement
1602  *           from the remote LLC. I PDUs may be received but not sent.
1603  *           Supervisory PDUs may be both sent and received.
1604  */
1605 int
1606 llc_state_AWAIT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
1607 		int cmdrsp, int pollfinal)
1608 {
1609 	int action = LLC_PASSITON;
1610 
1611 	switch(frame_kind + cmdrsp) {
1612 	case LLC_LOCAL_BUSY_DETECTED:
1613 		llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1614 		LLC_SETFLAG(linkp, DATA, 0);
1615 		LLC_NEWSTATE(linkp, AWAIT_BUSY);
1616 		action = 0;
1617 		break;
1618 	case LLC_INVALID_NS + LLC_CMD:
1619 	case LLC_INVALID_NS + LLC_RSP: {
1620 		register int p = LLC_GETFLAG(linkp, P);
1621 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1622 
1623 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1624 			llc_send(linkp, LLCFT_REJ, LLC_RSP, 1);
1625 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1626 			LLC_START_REJ_TIMER(linkp);
1627 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1628 			action = 0;
1629 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1630 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
1631 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1632 			linkp->llcl_vs = nr;
1633 			LLC_STOP_P_TIMER(linkp);
1634 			llc_resend(linkp, LLC_CMD, 0);
1635 			LLC_START_REJ_TIMER(linkp);
1636 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1637 			LLC_NEWSTATE(linkp, REJECT);
1638 		} else if (pollfinal == 0) {
1639 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
1640 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1641 			LLC_START_REJ_TIMER(linkp);
1642 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1643 			action = 0;
1644 		}
1645 		break;
1646 	}
1647 	case LLCFT_INFO + LLC_RSP:
1648 	case LLCFT_INFO + LLC_CMD: {
1649 		register int p = LLC_GETFLAG(linkp, P);
1650 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1651 
1652 		LLC_INC(linkp->llcl_vr);
1653 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1654 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1655 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1656 			action = LLC_DATA_INDICATION;
1657 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1658 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1659 			linkp->llcl_vs = nr;
1660 			llc_resend(linkp, LLC_CMD, 1);
1661 			LLC_START_P_TIMER(linkp);
1662 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1663 			LLC_NEWSTATE(linkp, NORMAL);
1664 			action = LLC_DATA_INDICATION;
1665 		} else if (pollfinal == 0) {
1666 			llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1667 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1668 			action = LLC_DATA_INDICATION;
1669 		}
1670 		break;
1671 	}
1672 	case LLCFT_RR + LLC_CMD:
1673 	case LLCFT_RR + LLC_RSP:
1674 	case LLCFT_REJ + LLC_CMD:
1675 	case LLCFT_REJ + LLC_RSP: {
1676 		register int p = LLC_GETFLAG(linkp, P);
1677 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1678 
1679 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1680 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1681 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1682 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1683 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1684 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1685 			linkp->llcl_vs = nr;
1686 			LLC_STOP_P_TIMER(linkp);
1687 			llc_resend(linkp, LLC_CMD, 0);
1688 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1689 			LLC_NEWSTATE(linkp, NORMAL);
1690 		} else if (pollfinal == 0) {
1691 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1692 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1693 		}
1694 		break;
1695 	}
1696 	case LLCFT_RNR + LLC_CMD:
1697 	case LLCFT_RNR + LLC_RSP: {
1698 		register int p = LLC_GETFLAG(linkp, P);
1699 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1700 
1701 		if (pollfinal == 1 && cmdrsp == LLC_CMD) {
1702 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1703 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1704 			LLC_SET_REMOTE_BUSY(linkp, action);
1705 		} else if (pollfinal == 1 && cmdrsp == LLC_RSP) {
1706 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1707 			linkp->llcl_vs = nr;
1708 			LLC_STOP_P_TIMER(linkp);
1709 			LLC_SET_REMOTE_BUSY(linkp, action);
1710 			LLC_NEWSTATE(linkp, NORMAL);
1711 		} else if (pollfinal == 0) {
1712 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1713 			LLC_SET_REMOTE_BUSY(linkp, action);
1714 		}
1715 		break;
1716 	}
1717 	case LLC_P_TIMER_EXPIRED:
1718 		if (linkp->llcl_retry < llc_n2) {
1719 			llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
1720 			LLC_START_P_TIMER(linkp);
1721 			linkp->llcl_retry++;
1722 			action = 0;
1723 		}
1724 		break;
1725 	}
1726 	if (action == LLC_PASSITON)
1727 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
1728 					    cmdrsp, pollfinal);
1729 
1730 	return action;
1731 }
1732 
1733 /*
1734  * AWAIT_BUSY --- A data link connection exists between the local LLC service
1735  *                access point and the remote LLC service access point. The
1736  *                local LLC is performing a timer recovery operation and has
1737  *                sent a command PDU with the P bit set to ``1'', and is
1738  *                awaiting an acknowledgement from the remote LLC. I PDUs may
1739  *                not be sent. Local conditions make it likely that the
1740  *                information feld of receoved I PDUs will be ignored.
1741  *                Supervisory PDUs may be both sent and received.
1742  */
1743 int
1744 llc_state_AWAIT_BUSY(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
1745 		     int cmdrsp, int pollfinal)
1746 {
1747 	int action = LLC_PASSITON;
1748 
1749 	switch(frame_kind + cmdrsp) {
1750 	case LLC_LOCAL_BUSY_CLEARED:
1751 		switch (LLC_GETFLAG(linkp, DATA)) {
1752 		case 1:
1753 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
1754 			LLC_START_REJ_TIMER(linkp);
1755 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1756 			action = 0;
1757 			break;
1758 		case 0:
1759 			llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1760 			LLC_NEWSTATE(linkp, AWAIT);
1761 			action = 0;
1762 			break;
1763 		case 2:
1764 			llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1765 			LLC_NEWSTATE(linkp, AWAIT_REJECT);
1766 			action = 0;
1767 			break;
1768 		}
1769 		break;
1770 	case LLC_INVALID_NS + LLC_CMD:
1771 	case LLC_INVALID_NS + LLC_RSP: {
1772 		register int p = LLC_GETFLAG(linkp, P);
1773 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1774 
1775 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1776 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1777 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1778 			LLC_SETFLAG(linkp, DATA, 1);
1779 			action = 0;
1780 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1781 			/* optionally */
1782 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1783 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1784 			linkp->llcl_vs = nr;
1785 			LLC_STOP_P_TIMER(linkp);
1786 			LLC_SETFLAG(linkp, DATA, 1);
1787 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1788 			llc_resend(linkp, LLC_CMD, 0);
1789 			LLC_NEWSTATE(linkp, BUSY);
1790 		} else if (pollfinal == 0) {
1791 			/* optionally */
1792 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1793 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1794 			LLC_SETFLAG(linkp, DATA, 1);
1795 			action = 0;
1796 		}
1797 	}
1798 	case LLCFT_INFO + LLC_CMD:
1799 	case LLCFT_INFO + LLC_RSP: {
1800 		register int p = LLC_GETFLAG(linkp, P);
1801 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1802 
1803 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1804 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1805 			LLC_INC(linkp->llcl_vr);
1806 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1807 			LLC_SETFLAG(linkp, DATA, 0);
1808 			action = LLC_DATA_INDICATION;
1809 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1810 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1811 			LLC_INC(linkp->llcl_vr);
1812 			LLC_START_P_TIMER(linkp);
1813 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1814 			linkp->llcl_vs = nr;
1815 			LLC_SETFLAG(linkp, DATA, 0);
1816 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1817 			llc_resend(linkp, LLC_CMD, 0);
1818 			LLC_NEWSTATE(linkp, BUSY);
1819 			action = LLC_DATA_INDICATION;
1820 		} else if (pollfinal == 0) {
1821 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1822 			LLC_INC(linkp->llcl_vr);
1823 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1824 			LLC_SETFLAG(linkp, DATA, 0);
1825 			action = LLC_DATA_INDICATION;
1826 		}
1827 		break;
1828 	}
1829 	case LLCFT_RR + LLC_CMD:
1830 	case LLCFT_REJ + LLC_CMD:
1831 	case LLCFT_RR + LLC_RSP:
1832 	case LLCFT_REJ + LLC_RSP: {
1833 		register int p = LLC_GETFLAG(linkp, P);
1834 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1835 
1836 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1837 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1838 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1839 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1840 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1841 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1842 			linkp->llcl_vs = nr;
1843 			LLC_STOP_P_TIMER(linkp);
1844 			llc_resend(linkp, LLC_CMD, 0);
1845 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1846 			LLC_NEWSTATE(linkp, BUSY);
1847 		} else if (pollfinal == 0) {
1848 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1849 			linkp->llcl_vs = nr;
1850 			LLC_STOP_P_TIMER(linkp);
1851 			llc_resend(linkp, LLC_CMD, 0);
1852 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1853 		}
1854 		break;
1855 	}
1856 	case LLCFT_RNR + LLC_CMD:
1857 	case LLCFT_RNR + LLC_RSP: {
1858 		register int p = LLC_GETFLAG(linkp, P);
1859 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1860 
1861 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1862 			llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
1863 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1864 			LLC_SET_REMOTE_BUSY(linkp, action);
1865 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1866 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1867 			linkp->llcl_vs = nr;
1868 			LLC_STOP_P_TIMER(linkp);
1869 			LLC_SET_REMOTE_BUSY(linkp, action);
1870 			LLC_NEWSTATE(linkp, BUSY);
1871 		} else if (pollfinal == 0) {
1872 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1873 			LLC_SET_REMOTE_BUSY(linkp, action);
1874 		}
1875 		break;
1876 	}
1877 	case LLC_P_TIMER_EXPIRED:
1878 		if (linkp->llcl_retry < llc_n2) {
1879 			llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
1880 			LLC_START_P_TIMER(linkp);
1881 			linkp->llcl_retry++;
1882 			action = 0;
1883 		}
1884 		break;
1885 	}
1886 	if (action == LLC_PASSITON)
1887 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
1888 					    cmdrsp, pollfinal);
1889 
1890 	return action;
1891 }
1892 
1893 /*
1894  * AWAIT_REJECT --- A data link connection exists between the local LLC service
1895  *                  access point and the remote LLC service access point. The
1896  *                  local connection component has requested that the remote
1897  *                  connection component re-transmit a specific I PDU that the
1898  *                  local connection component has detected as being out of
1899  *                  sequence. Before the local LLC entered this state it was
1900  *                  performing a timer recovery operation and had sent a
1901  *                  command PDU with the P bit set to ``1'', and is still
1902  *                  awaiting an acknowledgment from the remote LLC. I PDUs may
1903  *                  be received but not transmitted. Supervisory PDUs may be
1904  *                  both transmitted and received.
1905  */
1906 int
1907 llc_state_AWAIT_REJECT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
1908 		       int cmdrsp, int pollfinal)
1909 {
1910 	int action = LLC_PASSITON;
1911 
1912 	switch(frame_kind + cmdrsp) {
1913 	case LLC_LOCAL_BUSY_DETECTED:
1914 		llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
1915 		LLC_SETFLAG(linkp, DATA, 2);
1916 		LLC_NEWSTATE(linkp, AWAIT_BUSY);
1917 		action = 0;
1918 		break;
1919 	case LLC_INVALID_NS + LLC_CMD:
1920 	case LLC_INVALID_NS + LLC_RSP: {
1921 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1922 
1923 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1924 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1925 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1926 			action = 0;
1927 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1928 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1929 			linkp->llcl_vs = nr;
1930 			llc_resend(linkp, LLC_CMD, 1);
1931 			LLC_START_P_TIMER(linkp);
1932 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1933 			LLC_NEWSTATE(linkp, REJECT);
1934 		} else if (pollfinal == 0) {
1935 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1936 			action = 0;
1937 		}
1938 		break;
1939 	}
1940 	case LLCFT_INFO + LLC_CMD:
1941 	case LLCFT_INFO + LLC_RSP: {
1942 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1943 
1944 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1945 			LLC_INC(linkp->llcl_vr);
1946 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1947 			LLC_STOP_REJ_TIMER(linkp);
1948 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1949 			LLC_NEWSTATE(linkp, AWAIT);
1950 			action = LLC_DATA_INDICATION;
1951 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1952 			LLC_INC(linkp->llcl_vr);
1953 			LLC_STOP_P_TIMER(linkp);
1954 			LLC_STOP_REJ_TIMER(linkp);
1955 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1956 			linkp->llcl_vs = nr;
1957 			llc_resend(linkp, LLC_CMD, 0);
1958 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1959 			LLC_NEWSTATE(linkp, NORMAL);
1960 			action = LLC_DATA_INDICATION;
1961 		} else if (pollfinal == 0) {
1962 			LLC_INC(linkp->llcl_vr);
1963 			llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
1964 			LLC_STOP_REJ_TIMER(linkp);
1965 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1966 			LLC_NEWSTATE(linkp, AWAIT);
1967 			action = LLC_DATA_INDICATION;
1968 		}
1969 		break;
1970 	}
1971 	case LLCFT_RR + LLC_CMD:
1972 	case LLCFT_REJ + LLC_CMD:
1973 	case LLCFT_RR + LLC_RSP:
1974 	case LLCFT_REJ + LLC_RSP: {
1975 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1976 
1977 		if (cmdrsp == LLC_CMD && pollfinal ==  1) {
1978 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
1979 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1980 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1981 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
1982 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1983 			linkp->llcl_vs = nr;
1984 			llc_resend(linkp, LLC_CMD, 1);
1985 			LLC_START_P_TIMER(linkp);
1986 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1987 			LLC_NEWSTATE(linkp, REJECT);
1988 		} else if (pollfinal == 0) {
1989 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
1990 			LLC_CLEAR_REMOTE_BUSY(linkp, action);
1991 		}
1992 		break;
1993 	}
1994 	case LLCFT_RNR + LLC_CMD:
1995 	case LLCFT_RNR + LLC_RSP: {
1996 		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
1997 
1998 		if (cmdrsp == LLC_CMD && pollfinal == 1) {
1999 			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
2000 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
2001 			LLC_SET_REMOTE_BUSY(linkp, action);
2002 		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {
2003 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
2004 			linkp->llcl_vs = nr;
2005 			LLC_STOP_P_TIMER(linkp);
2006 			LLC_SET_REMOTE_BUSY(linkp, action);
2007 			LLC_NEWSTATE(linkp, REJECT);
2008 		} else if (pollfinal == 0) {
2009 			LLC_UPDATE_NR_RECEIVED(linkp, nr);
2010 			LLC_SET_REMOTE_BUSY(linkp, action);
2011 		}
2012 		break;
2013 	}
2014 	case LLC_P_TIMER_EXPIRED:
2015 		if (linkp->llcl_retry < llc_n2) {
2016 			llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
2017 			LLC_START_P_TIMER(linkp);
2018 			linkp->llcl_retry++;
2019 			action = 0;
2020 		}
2021 		break;
2022 	}
2023 	if (action == LLC_PASSITON)
2024 		action = llc_state_NBRAcore(linkp, frame, frame_kind,
2025 					    cmdrsp, pollfinal);
2026 
2027 	return action;
2028 }
2029 
2030 
2031 /*
2032  * llc_statehandler() --- Wrapper for llc_state_*() functions.
2033  *                         Deals with action codes and checks for
2034  *                         ``stuck'' links.
2035  */
2036 
2037 int
2038 llc_statehandler(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
2039 		 int cmdrsp, int pollfinal)
2040 {
2041 	register int action = 0;
2042 
2043 	/*
2044 	 * To check for ``zombie'' links each time llc_statehandler() gets called
2045 	 * the AGE timer of linkp is reset. If it expires llc_timer() will
2046 	 * take care of the link --- i.e. kill it 8=)
2047 	 */
2048 	LLC_STARTTIMER(linkp, AGE);
2049 
2050 	/*
2051 	 * Now call the current statehandler function.
2052 	 */
2053 	action = (*linkp->llcl_statehandler)(linkp, frame, frame_kind,
2054 					     cmdrsp, pollfinal);
2055 once_more_and_again:
2056 	switch (action) {
2057 	case LLC_CONNECT_INDICATION: {
2058 		int naction;
2059 
2060 		LLC_TRACE(linkp, LLCTR_INTERESTING, "CONNECT INDICATION");
2061 		linkp->llcl_nlnext =
2062 		     (*linkp->llcl_sapinfo->si_ctlinput)
2063 		      (PRC_CONNECT_INDICATION,
2064 		       (struct sockaddr *) &linkp->llcl_addr, (caddr_t) linkp);
2065 		if (linkp->llcl_nlnext == 0)
2066 			naction = NL_DISCONNECT_REQUEST;
2067 		else naction = NL_CONNECT_RESPONSE;
2068 		action = (*linkp->llcl_statehandler)(linkp, frame, naction, 0, 0);
2069 		goto once_more_and_again;
2070 	}
2071 	case LLC_CONNECT_CONFIRM:
2072 		/* llc_resend(linkp, LLC_CMD, 0); */
2073 		llc_start(linkp);
2074 		break;
2075 	case LLC_DISCONNECT_INDICATION:
2076 		LLC_TRACE(linkp, LLCTR_INTERESTING, "DISCONNECT INDICATION");
2077 		(*linkp->llcl_sapinfo->si_ctlinput)
2078 		  (PRC_DISCONNECT_INDICATION,
2079 		   (struct sockaddr *) &linkp->llcl_addr, linkp->llcl_nlnext);
2080 		break;
2081         /* internally visible only */
2082 	case LLC_RESET_CONFIRM:
2083 	case LLC_RESET_INDICATION_LOCAL:
2084 		/*
2085 		 * not much we can do here, the state machine either makes it or
2086 		 * brakes it ...
2087 		 */
2088 		break;
2089 	case LLC_RESET_INDICATION_REMOTE:
2090 		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "RESET INDICATION (REMOTE)");
2091 		action = (*linkp->llcl_statehandler)(linkp, frame,
2092 						     NL_RESET_RESPONSE, 0, 0);
2093 		goto once_more_and_again;
2094 	case LLC_FRMR_SENT:
2095 		LLC_TRACE(linkp, LLCTR_URGENT, "FRMR SENT");
2096 		break;
2097 	case LLC_FRMR_RECEIVED:
2098 		LLC_TRACE(linkp, LLCTR_URGEN, "FRMR RECEIVED");
2099 		action = (*linkp->llcl_statehandler)(linkp, frame,
2100 						     NL_RESET_REQUEST, 0, 0);
2101 
2102 		goto once_more_and_again;
2103 	case LLC_REMOTE_BUSY:
2104 		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY");
2105 		break;
2106 	case LLC_REMOTE_NOT_BUSY:
2107 		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY CLEARED");
2108 		/*
2109 		 * try to get queued frames out
2110 		 */
2111 		llc_start(linkp);
2112 		break;
2113 	}
2114 
2115 	/*
2116          * Only LLC_DATA_INDICATION is for the time being
2117 	 * passed up to the network layer entity.
2118 	 * The remaining action codes are for the time
2119 	 * being visible internally only.
2120          * However, this can/may be changed if necessary.
2121 	 */
2122 
2123 	return action;
2124 }
2125 
2126 
2127 /*
2128  * Core LLC2 routines
2129  */
2130 
2131 /*
2132  * The INIT call. This routine is called once after the system is booted.
2133  */
2134 
2135 llc_init()
2136 {
2137 	llcintrq.ifq_maxlen = IFQ_MAXLEN;
2138 }
2139 
2140 
2141 /*
2142  * In case of a link reset we need to shuffle the frames queued inside the
2143  * LLC2 window.
2144  */
2145 
2146 void
2147 llc_resetwindow(struct llc_linkcb *linkp)
2148 {
2149 	register struct mbuf *mptr = (struct mbuf *) 0;
2150 	register struct mbuf *anchor = (struct mbuf *)0;
2151 	register short i;
2152 
2153 	/* Pick up all queued frames and collect them in a linked mbuf list */
2154 	if (linkp->llcl_slotsfree != linkp->llcl_window) {
2155 		i = llc_seq2slot(linkp, linkp->llcl_nr_received);
2156 		anchor = mptr = linkp->llcl_output_buffers[i];
2157 		for (; i != linkp->llcl_freeslot;
2158 		     i = llc_seq2slot(linkp, i+1)) {
2159 			if (linkp->llcl_output_buffers[i]) {
2160 				mptr->m_nextpkt = linkp->llcl_output_buffers[i];
2161 				mptr = mptr->m_nextpkt;
2162 			} else panic("LLC2 window broken");
2163 		}
2164 	}
2165 	/* clean closure */
2166 	if (mptr)
2167 		mptr->m_nextpkt = (struct mbuf *) 0;
2168 
2169 	/* Now --- plug 'em in again */
2170 	if (anchor != (struct mbuf *)0) {
2171 		for (i = 0, mptr = anchor; mptr != (struct mbuf *) 0; i++) {
2172 			linkp->llcl_output_buffers[i] = mptr;
2173 			mptr = mptr->m_nextpkt;
2174 			linkp->llcl_output_buffers[i]->m_nextpkt = (struct mbuf *)0;
2175 		}
2176 		linkp->llcl_freeslot = i;
2177 	} else linkp->llcl_freeslot = 0;
2178 
2179 	/* We're resetting the link, the next frame to be acknowledged is 0 */
2180 	linkp->llcl_nr_received = 0;
2181 
2182 	/* set distance between LLC2 sequence number and the top of window to 0 */
2183 	linkp->llcl_projvs = linkp->llcl_freeslot;
2184 
2185 	return;
2186 }
2187 
2188 /*
2189  * llc_newlink() --- We allocate enough memory to contain a link control block
2190  *                   and initialize it properly. We don't intiate the actual setup
2191  *                   of the LLC2 link here.
2192  */
2193 struct llc_linkcb *
2194 llc_newlink(struct sockaddr_dl *dst, struct ifnet *ifp, struct rtentry *nlrt,
2195 	    caddr_t nlnext, struct rtentry *llrt)
2196 {
2197 	struct llc_linkcb *nlinkp;
2198 	u_char sap = LLSAPADDR(dst);
2199 	short llcwindow;
2200 
2201 
2202 	/* allocate memory for link control block */
2203 	MALLOC(nlinkp, struct llc_linkcb *, sizeof(struct llc_linkcb),
2204 	       M_PCB, M_DONTWAIT);
2205 	if (nlinkp == 0)
2206 		return (NULL);
2207 	bzero((caddr_t)nlinkp, sizeof(struct llc_linkcb));
2208 
2209 	/* copy link address */
2210 	sdl_copy(dst, &nlinkp->llcl_addr);
2211 
2212 	/* hold on to the network layer route entry */
2213 	nlinkp->llcl_nlrt = nlrt;
2214 
2215 	/* likewise the network layer control block */
2216 	nlinkp->llcl_nlnext = nlnext;
2217 
2218 	/* jot down the link layer route entry */
2219 	nlinkp->llcl_llrt = llrt;
2220 
2221 	/* reset writeq */
2222 	nlinkp->llcl_writeqh = nlinkp->llcl_writeqt = NULL;
2223 
2224 	/* setup initial state handler function */
2225 	nlinkp->llcl_statehandler = llc_state_ADM;
2226 
2227 	/* hold on to interface pointer */
2228 	nlinkp->llcl_if = ifp;
2229 
2230 	/* get service access point information */
2231 	nlinkp->llcl_sapinfo = llc_getsapinfo(sap, ifp);
2232 
2233 	/* get window size from SAP info block */
2234 	if ((llcwindow = nlinkp->llcl_sapinfo->si_window) == 0)
2235 		llcwindow = LLC_MAX_WINDOW;
2236 
2237 	/* allocate memory for window buffer */
2238 	MALLOC(nlinkp->llcl_output_buffers, struct mbuf **,
2239 	       llcwindow*sizeof(struct mbuf *), M_PCB, M_DONTWAIT);
2240 	if (nlinkp->llcl_output_buffers == 0) {
2241 		FREE(nlinkp, M_PCB);
2242 		return(NULL);
2243 	}
2244 	bzero((caddr_t)nlinkp->llcl_output_buffers,
2245 	      llcwindow*sizeof(struct mbuf *));
2246 
2247 	/* set window size & slotsfree */
2248 	nlinkp->llcl_slotsfree = nlinkp->llcl_window = llcwindow;
2249 
2250 	/* enter into linked listed of link control blocks */
2251 	insque(nlinkp, &llccb_q);
2252 
2253 	return(nlinkp);
2254 }
2255 
2256 /*
2257  * llc_dellink() --- farewell to link control block
2258  */
2259 llc_dellink(struct llc_linkcb *linkp)
2260 {
2261 	register struct mbuf *m;
2262 	register struct mbuf *n;
2263 	register struct npaidbentry *sapinfo = linkp->llcl_sapinfo;
2264 	register i;
2265 
2266 	/* notify upper layer of imminent death */
2267 	if (linkp->llcl_nlnext && sapinfo->si_ctlinput)
2268 		(*sapinfo->si_ctlinput)
2269 		   (PRC_DISCONNECT_INDICATION,
2270 		    (struct sockaddr *)&linkp->llcl_addr, linkp->llcl_nlnext);
2271 
2272 	/* pull the plug */
2273 	if (linkp->llcl_llrt)
2274 		((struct npaidbentry *)(linkp->llcl_llrt->rt_llinfo))->np_link
2275 			= (struct llc_linkcb *) 0;
2276 
2277 	/* leave link control block queue */
2278 	remque(linkp);
2279 
2280 	/* drop queued packets */
2281 	for (m = linkp->llcl_writeqh; m;) {
2282 		n = m->m_act;
2283 		m_freem(m);
2284 		m = n;
2285 	}
2286 
2287 	/* drop packets in the window */
2288 	for(i = 0; i < linkp->llcl_window; i++)
2289 		if (linkp->llcl_output_buffers[i])
2290 			m_freem(linkp->llcl_output_buffers[i]);
2291 
2292 	/* return the window space */
2293 	FREE((caddr_t)linkp->llcl_output_buffers, M_PCB);
2294 
2295 	/* return the control block space --- now it's gone ... */
2296 	FREE((caddr_t)linkp, M_PCB);
2297 }
2298 
2299 llc_decode(struct llc* frame, struct llc_linkcb * linkp)
2300 {
2301 	register int ft = LLC_BAD_PDU;
2302 
2303 	if ((frame->llc_control & 01) == 0) {
2304 		ft = LLCFT_INFO;
2305 	/* S or U frame ? */
2306 	} else switch (frame->llc_control) {
2307 
2308 	/* U frames */
2309 	case LLC_UI:
2310 	case LLC_UI_P:     ft = LLC_UI; break;
2311 	case LLC_DM:
2312 	case LLC_DM_P:     ft =LLCFT_DM; break;
2313 	case LLC_DISC:
2314 	case LLC_DISC_P:   ft = LLCFT_DISC; break;
2315 	case LLC_UA:
2316 	case LLC_UA_P:     ft = LLCFT_UA; break;
2317 	case LLC_SABME:
2318 	case LLC_SABME_P:  ft = LLCFT_SABME; break;
2319 	case LLC_FRMR:
2320 	case LLC_FRMR_P:   ft = LLCFT_FRMR; break;
2321 	case LLC_XID:
2322 	case LLC_XID_P:    ft = LLCFT_XID; break;
2323 	case LLC_TEST:
2324 	case LLC_TEST_P:   ft = LLCFT_TEST; break;
2325 
2326 	/* S frames */
2327 	case LLC_RR:       ft = LLCFT_RR; break;
2328 	case LLC_RNR:      ft = LLCFT_RNR; break;
2329 	case LLC_REJ:      ft = LLCFT_REJ; break;
2330 	} /* switch */
2331 
2332 	if (linkp) {
2333 		switch (ft) {
2334 		case LLCFT_INFO:
2335 			if (LLCGBITS(frame->llc_control, i_ns) != linkp->llcl_vr) {
2336 				ft = LLC_INVALID_NS;
2337 				break;
2338 			}
2339 			/* fall thru --- yeeeeeee */
2340 		case LLCFT_RR:
2341 		case LLCFT_RNR:
2342 		case LLCFT_REJ:
2343 			/* splash! */
2344 			if (LLC_NR_VALID(linkp, LLCGBITS(frame->llc_control_ext,
2345 							 s_nr)) == 0)
2346 				ft = LLC_INVALID_NR;
2347 			break;
2348 		}
2349 	}
2350 
2351 	return ft;
2352 }
2353 
2354 /*
2355  * llc_anytimersup() --- Checks if at least one timer is still up and running.
2356  */
2357 int
2358 llc_anytimersup(struct llc_linkcb * linkp)
2359 {
2360 	register int i;
2361 
2362 	FOR_ALL_LLC_TIMERS(i)
2363 		if (linkp->llcl_timers[i] > 0)
2364 			break;
2365 	if (i == LLC_AGE_SHIFT)
2366 		return 0;
2367 	else return 1;
2368 }
2369 
2370 /*
2371  * llc_link_dump() - dump link info
2372  */
2373 
2374 #define SAL(s) ((struct sockaddr_dl *)&(s)->llcl_addr)
2375 #define CHECK(l, s) if (LLC_STATEEQ(l, s)) return #s
2376 
2377 char *timer_names[] = {"ACK", "P", "BUSY", "REJ", "AGE"};
2378 
2379 char *
2380 llc_getstatename(struct llc_linkcb *linkp)
2381 {
2382 	CHECK(linkp, ADM);
2383 	CHECK(linkp, CONN);
2384 	CHECK(linkp, RESET_WAIT);
2385 	CHECK(linkp, RESET_CHECK);
2386 	CHECK(linkp, SETUP);
2387 	CHECK(linkp, RESET);
2388 	CHECK(linkp, D_CONN);
2389 	CHECK(linkp, ERROR);
2390 	CHECK(linkp, NORMAL);
2391 	CHECK(linkp, BUSY);
2392 	CHECK(linkp, REJECT);
2393 	CHECK(linkp, AWAIT);
2394 	CHECK(linkp, AWAIT_BUSY);
2395 	CHECK(linkp, AWAIT_REJECT);
2396 
2397 	return "UNKNOWN - eh?";
2398 }
2399 
2400 void
2401 llc_link_dump(struct llc_linkcb* linkp, const char *message)
2402 {
2403 	register int i;
2404 	register char *state;
2405 
2406 	/* print interface */
2407 	printf("if %s%d\n", linkp->llcl_if->if_name, linkp->llcl_if->if_unit);
2408 
2409 	/* print message */
2410 	printf(">> %s <<\n", message);
2411 
2412 	/* print MAC and LSAP */
2413 	printf("llc addr ");
2414 	for (i = 0; i < (SAL(linkp)->sdl_alen)-2; i++)
2415 		printf("%x:", (char)*(LLADDR(SAL(linkp))+i) & 0xff);
2416 	printf("%x,", (char)*(LLADDR(SAL(linkp))+i) & 0xff);
2417 	printf("%x\n", (char)*(LLADDR(SAL(linkp))+i+1) & 0xff);
2418 
2419 	/* print state we're in and timers */
2420         printf("state %s, ", llc_getstatename(linkp));
2421         for (i = LLC_ACK_SHIFT; i < LLC_AGE_SHIFT; i++)
2422 		printf("%s-%c %d/", timer_names[i],
2423 		       (linkp->llcl_timerflags & (1<<i) ? 'R' : 'S'),
2424 		       linkp->llcl_timers[i]);
2425 	printf("%s-%c %d\n", timer_names[i], (linkp->llcl_timerflags & (1<<i) ?
2426 					     'R' : 'S'), linkp->llcl_timers[i]);
2427 
2428 	/* print flag values */
2429 	printf("flags P %d/F %d/S %d/DATA %d/REMOTE_BUSY %d\n",
2430 	       LLC_GETFLAG(linkp, P), LLC_GETFLAG(linkp, S),
2431 	       LLC_GETFLAG(linkp, DATA), LLC_GETFLAG(linkp, REMOTE_BUSY));
2432 
2433 	/* print send and receive state variables, ack, and window */
2434 	printf("V(R) %d/V(S) %d/N(R) received %d/window %d/freeslot %d\n",
2435 	       linkp->llcl_vs, linkp->llcl_vr, linkp->llcl_nr_received,
2436 	       linkp->llcl_window, linkp->llcl_freeslot);
2437 
2438 	/* further expansions can follow here */
2439 
2440 }
2441 
2442 void
2443 llc_trace(struct llc_linkcb *linkp, int level, const char *message)
2444 {
2445 	if (linkp->llcl_sapinfo->si_trace && level > llc_tracelevel)
2446 		llc_link_dump(linkp, message);
2447 
2448 	return;
2449 }
2450