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