kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / unisig_vc_state.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/netatm/uni/unisig_vc_state.c,v 1.6.2.1 2001/07/25 20:53:44 pirzyk Exp $
d2438d69 27 * @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_vc_state.c,v 1.4 2003/08/07 21:54:34 dillon Exp $
984263bc
MD
28 */
29
30/*
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
33 *
34 * VC state machine
35 *
36 */
37
d2438d69 38#include <netproto/atm/kern_include.h>
984263bc 39
1f2de5d4
MD
40#include "unisig_var.h"
41#include "unisig_msg.h"
984263bc 42
984263bc
MD
43/*
44 * Local functions
45 */
46static int unisig_vc_invalid __P((struct unisig *, struct unisig_vccb *,
47 struct unisig_msg *));
48static int unisig_vc_act01 __P((struct unisig *, struct unisig_vccb *,
49 struct unisig_msg *));
50static int unisig_vc_act02 __P((struct unisig *, struct unisig_vccb *,
51 struct unisig_msg *));
52static int unisig_vc_act03 __P((struct unisig *, struct unisig_vccb *,
53 struct unisig_msg *));
54static int unisig_vc_act04 __P((struct unisig *, struct unisig_vccb *,
55 struct unisig_msg *));
56static int unisig_vc_act05 __P((struct unisig *, struct unisig_vccb *,
57 struct unisig_msg *));
58static int unisig_vc_act06 __P((struct unisig *, struct unisig_vccb *,
59 struct unisig_msg *));
60static int unisig_vc_act07 __P((struct unisig *, struct unisig_vccb *,
61 struct unisig_msg *));
62static int unisig_vc_act08 __P((struct unisig *, struct unisig_vccb *,
63 struct unisig_msg *));
64static int unisig_vc_act09 __P((struct unisig *, struct unisig_vccb *,
65 struct unisig_msg *));
66static int unisig_vc_act10 __P((struct unisig *, struct unisig_vccb *,
67 struct unisig_msg *));
68static int unisig_vc_act11 __P((struct unisig *, struct unisig_vccb *,
69 struct unisig_msg *));
70static int unisig_vc_act12 __P((struct unisig *, struct unisig_vccb *,
71 struct unisig_msg *));
72static int unisig_vc_act13 __P((struct unisig *, struct unisig_vccb *,
73 struct unisig_msg *));
74static int unisig_vc_act14 __P((struct unisig *, struct unisig_vccb *,
75 struct unisig_msg *));
76static int unisig_vc_act15 __P((struct unisig *, struct unisig_vccb *,
77 struct unisig_msg *));
78static int unisig_vc_act16 __P((struct unisig *, struct unisig_vccb *,
79 struct unisig_msg *));
80static int unisig_vc_act17 __P((struct unisig *, struct unisig_vccb *,
81 struct unisig_msg *));
82static int unisig_vc_act18 __P((struct unisig *, struct unisig_vccb *,
83 struct unisig_msg *));
84static int unisig_vc_act19 __P((struct unisig *, struct unisig_vccb *,
85 struct unisig_msg *));
86static int unisig_vc_act20 __P((struct unisig *, struct unisig_vccb *,
87 struct unisig_msg *));
88static int unisig_vc_act21 __P((struct unisig *, struct unisig_vccb *,
89 struct unisig_msg *));
90static int unisig_vc_act22 __P((struct unisig *, struct unisig_vccb *,
91 struct unisig_msg *));
92static int unisig_vc_act23 __P((struct unisig *, struct unisig_vccb *,
93 struct unisig_msg *));
94static int unisig_vc_act24 __P((struct unisig *, struct unisig_vccb *,
95 struct unisig_msg *));
96static int unisig_vc_act25 __P((struct unisig *, struct unisig_vccb *,
97 struct unisig_msg *));
98static int unisig_vc_act26 __P((struct unisig *, struct unisig_vccb *,
99 struct unisig_msg *));
100static int unisig_vc_act27 __P((struct unisig *, struct unisig_vccb *,
101 struct unisig_msg *));
102static int unisig_vc_act28 __P((struct unisig *, struct unisig_vccb *,
103 struct unisig_msg *));
104static int unisig_vc_act29 __P((struct unisig *, struct unisig_vccb *,
105 struct unisig_msg *));
106static int unisig_vc_act30 __P((struct unisig *, struct unisig_vccb *,
107 struct unisig_msg *));
108static int unisig_vc_act31 __P((struct unisig *, struct unisig_vccb *,
109 struct unisig_msg *));
110static int unisig_vc_clear_call __P((struct unisig *,
111 struct unisig_vccb *,
112 struct unisig_msg *,
113 int));
114
115
116/*
117 * State table
118 */
119static int unisig_vc_states[21][17] = {
120/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
121{ 0, 2, 99, 5, 99, 99, 0, 99, 12, 99, 0, 14, 0, 3, 0, 0, 0 },
122{ 29, 4, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
123{ 29, 6, 99, 6, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
124{ 29, 17, 99, 17, 99, 99, 17, 99, 10, 99, 17, 17, 17, 0, 0, 0, 0 },
125{ 8, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
126{ 29, 7, 99, 15, 99, 99, 15, 99, 15, 99, 15, 16, 17, 0, 0, 0, 0 },
127{ 19, 3, 99, 3, 99, 99, 3, 99, 3, 99, 3, 13, 3, 0, 0, 0, 0 },
128{ 21, 21, 99, 21, 99, 99, 21, 99, 21, 99, 21, 21, 21, 0, 0, 0, 0 },
129{ 22, 22, 99, 22, 99, 99, 22, 99, 22, 99, 22, 22, 22, 0, 0, 0, 0 },
130{ 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 23, 17, 17, 0, 0, 0, 0 },
131{ 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
132{ 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
133{ 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
134{ 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
135{ 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 },
136{ 99, 25, 99, 25, 99, 99, 9, 99, 25, 99, 25, 25, 25, 25, 31, 25, 25 },
137{ 99, 25, 99, 25, 99, 99, 11, 99, 25, 99, 25, 25, 25, 25, 19, 25, 25 },
138{ 99, 12, 99, 12, 99, 99, 25, 99, 12, 99, 12, 19, 19, 30, 19, 99, 99 },
139{ 99, 12, 99, 12, 99, 99, 12, 99, 12, 99, 12, 3, 3, 3, 24, 26, 26 },
140{ 99, 3, 99, 3, 99, 99, 30, 99, 3, 99, 18, 3, 3, 0, 19, 27, 19 },
141{ 99, 7, 99, 7, 99, 99, 30, 99, 7, 99, 19, 19, 19, 20, 19, 19, 28 }
142};
143
144
145/*
146 * Action vector
147 *
148 * A given state, action pair selects an action number from the
149 * state table. This vector holds the address of the action routine
150 * for each action number.
151 */
152#define MAX_ACTION 32
153static int (*unisig_vc_act_vec[MAX_ACTION])
154 __P((struct unisig *, struct unisig_vccb *,
155 struct unisig_msg *)) = {
156 unisig_vc_invalid,
157 unisig_vc_act01,
158 unisig_vc_act02,
159 unisig_vc_act03,
160 unisig_vc_act04,
161 unisig_vc_act05,
162 unisig_vc_act06,
163 unisig_vc_act07,
164 unisig_vc_act08,
165 unisig_vc_act09,
166 unisig_vc_act10,
167 unisig_vc_act11,
168 unisig_vc_act12,
169 unisig_vc_act13,
170 unisig_vc_act14,
171 unisig_vc_act15,
172 unisig_vc_act16,
173 unisig_vc_act17,
174 unisig_vc_act18,
175 unisig_vc_act19,
176 unisig_vc_act20,
177 unisig_vc_act21,
178 unisig_vc_act22,
179 unisig_vc_act23,
180 unisig_vc_act24,
181 unisig_vc_act25,
182 unisig_vc_act26,
183 unisig_vc_act27,
184 unisig_vc_act28,
185 unisig_vc_act29,
186 unisig_vc_act30,
187 unisig_vc_act31
188};
189
190
191/*
192 * Process an event on a VC
193 *
194 * Arguments:
195 * usp pointer to the UNISIG instance
196 * uvp pointer to the VCCB for the affected VCC
197 * event a numeric indication of which event has occured
198 * msg pointer to a signalling message structure
199 *
200 * Returns:
201 * 0 success
202 * errno error encountered
203 *
204 */
205int
206unisig_vc_state(usp, uvp, event, msg)
207 struct unisig *usp;
208 struct unisig_vccb *uvp;
209 int event;
210 struct unisig_msg *msg;
211{
212 int action, rc, state;
213
214 /*
215 * Select an action from the state table
216 */
217 if (uvp)
218 state = uvp->uv_sstate;
219 else
220 state = UNI_NULL;
221 action = unisig_vc_states[event][state];
222 if (action >= MAX_ACTION || action < 0)
223 panic("unisig_vc_state: invalid action\n");
224
225 /*
226 * Perform the requested action
227 */
228 ATM_DEBUG4("unisig_vc_state: uvp=%p, state=%d, event=%d, action=%d\n",
229 uvp, state, event, action);
230 rc = unisig_vc_act_vec[action](usp, uvp, msg);
231
232 return(rc);
233}
234
235
236/*
237 * VC state machine action 0
238 * Unexpected action - log an error message
239 *
240 * Arguments:
241 * usp pointer to protocol instance block
242 * uvp pointer to the VCCB for the affected connection (may
243 be null)
244 * msg pointer to a UNISIG message structure
245 *
246 * Returns:
247 * 0 success
248 * errno error encountered
249 *
250 */
251static int
252unisig_vc_invalid(usp, uvp, msg)
253 struct unisig *usp;
254 struct unisig_vccb *uvp;
255 struct unisig_msg *msg;
256{
257 log(LOG_ERR, "unisig_vc_state: unexpected action\n");
258 return(EINVAL);
259}
260
261
262/*
263 * VC state machine action 1
264 * Setup handler called
265 *
266 * Send SETUP, start timer T303, go to UNI_CALL_INITIATED state
267 *
268 * Arguments:
269 * usp pointer to protocol instance block
270 * uvp pointer to the VCCB for the affected connection
271 * msg pointer to a UNISIG message structure
272 *
273 * Returns:
274 * 0 success
275 * errno error encountered
276 *
277 */
278static int
279unisig_vc_act01(usp, uvp, msg)
280 struct unisig *usp;
281 struct unisig_vccb *uvp;
282 struct unisig_msg *msg;
283{
284 int rc;
285
286 /*
287 * Send the setup message
288 */
289 rc = unisig_send_setup(usp, uvp);
290 if (rc)
291 return(rc);
292
293 /*
294 * Set timer T303
295 */
296 uvp->uv_retry = 0;
297 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
298
299 /*
300 * Set the new state
301 */
302 uvp->uv_sstate = UNI_CALL_INITIATED;
303
304 /*
305 * Mark the time
306 */
307 uvp->uv_tstamp = time_second;
308
309 return(0);
310}
311
312
313/*
314 * VC state machine action 2
315 * Timeout while waiting for CALL PROCEEDING or CONNECT
316 *
317 * If this is the second expiration, clear the call. Otherwise,
318 * retransmit the SETUP message and restart T303.
319 *
320 * Arguments:
321 * usp pointer to protocol instance block
322 * uvp pointer to the VCCB for the affected connection
323 * msg pointer to a UNISIG message structure
324 *
325 * Returns:
326 * 0 success
327 * errno error encountered
328 *
329 */
330static int
331unisig_vc_act02(usp, uvp, msg)
332 struct unisig *usp;
333 struct unisig_vccb *uvp;
334 struct unisig_msg *msg;
335{
336 int rc = 0;
337
338 if (uvp->uv_retry) {
339 /*
340 * Clear the call
341 */
342 rc = unisig_clear_vcc(usp, uvp,
343 T_ATM_CAUSE_NO_ROUTE_TO_DESTINATION);
344 } else {
345 uvp->uv_retry++;
346 (void) unisig_send_setup(usp, uvp);
347 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
348 }
349
350 return(rc);
351}
352
353
354/*
355 * VC state machine action 3
356 *
357 * Clear the call internally
358 *
359 * Arguments:
360 * usp pointer to protocol instance block
361 * uvp pointer to the VCCB for the affected connection
362 * msg pointer to a UNISIG message structure
363 *
364 * Returns:
365 * 0 success
366 * errno error encountered
367 *
368 */
369static int
370unisig_vc_act03(usp, uvp, msg)
371 struct unisig *usp;
372 struct unisig_vccb *uvp;
373 struct unisig_msg *msg;
374{
375 int rc, cause;
376
377 /*
378 * Set cause code
379 */
380 if ((msg != NULL) && (msg->msg_ie_caus != NULL)) {
381 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
382 msg->msg_ie_caus);
383 cause = T_ATM_ABSENT;
384 } else
385 cause = T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER;
386
387 /*
388 * Clear the VCCB
389 */
390 rc = unisig_clear_vcc(usp, uvp, cause);
391
392 return(rc);
393}
394
395
396/*
397 * VC state machine action 4
398 * Received CALL PROCEEDING
399 *
400 * Start timer T310, go to UNI_CALL_OUT_PROC
401 *
402 * Arguments:
403 * usp pointer to protocol instance block
404 * uvp pointer to the VCCB for the affected connection
405 * msg pointer to a UNISIG message structure
406 *
407 * Returns:
408 * 0 success
409 * errno error encountered
410 *
411 */
412static int
413unisig_vc_act04(usp, uvp, msg)
414 struct unisig *usp;
415 struct unisig_vccb *uvp;
416 struct unisig_msg *msg;
417{
418 int cause, rc, vpi, vci;
419 struct atm_pif *pip = usp->us_pif;
420 struct ie_generic *iep;
421
422 /*
423 * Clear any running timer
424 */
425 UNISIG_VC_CANCEL((struct vccb *) uvp);
426
427 /*
428 * Make sure a Connection ID is part of the message
429 */
430 if (msg->msg_ie_cnid) {
431 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
432 vci = msg->msg_ie_cnid->ie_cnid_vci;
433 } else {
434 iep = (struct ie_generic *)atm_allocate(&unisig_iepool);
435 if (!iep)
436 return(ENOMEM);
437 iep->ie_ident = UNI_IE_CNID;
438 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
439 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
440 cause = UNI_IE_CAUS_MISSING;
441 ATM_DEBUG0("unisig_vc_act04: no CNID in Call Proc\n");
442 goto response04;
443 }
444
445 /*
446 * Make sure we can handle the specified VPI and VCI
447 */
448 if (vpi > pip->pif_maxvpi || vci > pip->pif_maxvci ||
449 vci < UNI_IE_CNID_MIN_VCI) {
450 cause = UNI_IE_CAUS_BAD_VCC;
451 ATM_DEBUG0("unisig_vc_act04: VPI/VCI invalid\n");
452 goto response04;
453 }
454
455 /*
456 * Make sure the specified VPI and VCI are not in use
457 */
458 if (unisig_find_vpvc(usp, vpi, vci, VCC_OUT)) {
459 cause = UNI_IE_CAUS_NA_VCC;
460 ATM_DEBUG0("unisig_vc_act04: VPI/VCI in use\n");
461 goto response04;
462 }
463
464 /*
465 * Start timer T310
466 */
467 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T310);
468
469 /*
470 * Save the specified VPI and VCI
471 */
472 uvp->uv_vpi = vpi;
473 uvp->uv_vci = vci;
474
475 /*
476 * Set the state
477 */
478 uvp->uv_sstate = UNI_CALL_OUT_PROC;
479
480 /*
481 * Mark the time
482 */
483 uvp->uv_tstamp = time_second;
484
485 return(0);
486
487response04:
488 /*
489 * Initiate call clearing
490 */
491 rc = unisig_vc_clear_call(usp, uvp, msg, cause);
492
493 return(rc);
494}
495
496
497/*
498 * VC state machine action 5
499 * Timeout in UNI_CALL_OUT_PROC
500 *
501 * Clear call towards network
502 *
503 * Arguments:
504 * usp pointer to protocol instance block
505 * uvp pointer to the VCCB for the affected connection
506 * msg pointer to a UNISIG message structure
507 *
508 * Returns:
509 * 0 success
510 * errno error encountered
511 *
512 */
513static int
514unisig_vc_act05(usp, uvp, msg)
515 struct unisig *usp;
516 struct unisig_vccb *uvp;
517 struct unisig_msg *msg;
518{
519 int rc;
520 struct unisig_msg *rls_msg;
521 struct ie_generic *cause_ie;
522
523 /*
524 * Send a RELEASE message
525 */
526 rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
527 if (rls_msg == NULL)
528 return(ENOMEM);
529 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
530 if (cause_ie == NULL) {
531 atm_free(rls_msg);
532 return(ENOMEM);
533 }
534
535 /*
536 * Fill out the RELEASE message
537 */
538 rls_msg->msg_call_ref = uvp->uv_call_ref;
539 rls_msg->msg_type = UNI_MSG_RLSE;
540 rls_msg->msg_type_flag = 0;
541 rls_msg->msg_type_action = 0;
542 rls_msg->msg_ie_caus = cause_ie;
543
544 /*
545 * Fill out the cause IE
546 */
547 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
548 cause_ie->ie_caus_cause = UNI_IE_CAUS_TIMER;
549 KM_COPY("310", cause_ie->ie_caus_diagnostic, 3);
550
551 /*
552 * Send the RELEASE message.
553 */
554 rc = unisig_send_msg(usp, rls_msg);
555 unisig_free_msg(rls_msg);
556
557 /*
558 * Start timer T308
559 */
560 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
561
562 /*
563 * Set the new state
564 */
565 uvp->uv_sstate = UNI_RELEASE_REQUEST;
566 uvp->uv_ustate = VCCU_CLOSED;
567
568 /*
569 * Mark the time
570 */
571 uvp->uv_tstamp = time_second;
572
573 return(rc);
574}
575
576
577/*
578 * VC state machine action 6
579 * Received CONNECT
580 *
581 * Send CONNECT ACK, go to UNI_ACTIVE state
582 *
583 * Arguments:
584 * usp pointer to protocol instance block
585 * uvp pointer to the VCCB for the affected connection
586 * msg pointer to a UNISIG message structure
587 *
588 * Returns:
589 * 0 success
590 * errno error encountered
591 *
592 */
593static int
594unisig_vc_act06(usp, uvp, msg)
595 struct unisig *usp;
596 struct unisig_vccb *uvp;
597 struct unisig_msg *msg;
598{
599 int cause, rc, vci, vpi;
600 struct atm_pif *pip = usp->us_pif;
601 struct unisig_msg *cack_msg;
602 struct ie_generic *iep;
603 Atm_attributes *ap;
604
605 /*
606 * Clear any running timer
607 */
608 UNISIG_VC_CANCEL((struct vccb *) uvp);
609
610 ap = &uvp->uv_connvc->cvc_attr;
611
612 /*
613 * See if a VPI/VCI is specified
614 */
615 if (msg->msg_ie_cnid) {
616 /*
617 * Yes--VPI/VCI must be the first specification or must
618 * match what was specified before
619 */
620 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
621 vci = msg->msg_ie_cnid->ie_cnid_vci;
622 if ((uvp->uv_vpi || uvp->uv_vci) &&
623 (vpi != uvp->uv_vpi ||
624 vci != uvp->uv_vci)) {
625 cause = UNI_IE_CAUS_BAD_VCC;
626 ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
627 goto response06;
628 }
629
630 /*
631 * Specified VPI/VCI must be within range
632 */
633 if (vpi > pip->pif_maxvpi || vci > pip->pif_maxvci ||
634 vci < UNI_IE_CNID_MIN_VCI) {
635 cause = UNI_IE_CAUS_BAD_VCC;
636 ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
637 goto response06;
638 }
639 uvp->uv_vpi = vpi;
640 uvp->uv_vci = vci;
641 } else {
642 /*
643 * No--VCI must have been specified earlier
644 */
645 if (!uvp->uv_vci) {
646 iep = (struct ie_generic *)atm_allocate(
647 &unisig_iepool);
648 if (!iep)
649 return(ENOMEM);
650 iep->ie_ident = UNI_IE_CNID;
651 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
652 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
653 cause = UNI_IE_CAUS_MISSING;
654 ATM_DEBUG0("unisig_vc_act06: CNID missing\n");
655 goto response06;
656 }
657 }
658
659 /*
660 * Handle AAL parameters negotiation
661 */
662 if (msg->msg_ie_aalp) {
663 struct ie_generic *aalp = msg->msg_ie_aalp;
664
665 /*
666 * AAL parameters must have been sent in SETUP
667 */
668 if ((ap->aal.tag != T_ATM_PRESENT) ||
669 (ap->aal.type != aalp->ie_aalp_aal_type)) {
670 cause = UNI_IE_CAUS_IECONTENT;
671 goto response06;
672 }
673
674 switch (aalp->ie_aalp_aal_type) {
675
676 case UNI_IE_AALP_AT_AAL3:
677 /*
678 * Maximum SDU size negotiation
679 */
680 if (aalp->ie_aalp_4_fwd_max_sdu == T_ATM_ABSENT)
681 break;
682 if ((ap->aal.v.aal4.forward_max_SDU_size <
683 aalp->ie_aalp_4_fwd_max_sdu) ||
684 (ap->aal.v.aal4.backward_max_SDU_size <
685 aalp->ie_aalp_4_bkwd_max_sdu)) {
686 cause = UNI_IE_CAUS_IECONTENT;
687 goto response06;
688 } else {
689 ap->aal.v.aal4.forward_max_SDU_size =
690 aalp->ie_aalp_4_fwd_max_sdu;
691 ap->aal.v.aal4.backward_max_SDU_size =
692 aalp->ie_aalp_4_bkwd_max_sdu;
693 }
694 break;
695
696 case UNI_IE_AALP_AT_AAL5:
697 /*
698 * Maximum SDU size negotiation
699 */
700 if (aalp->ie_aalp_5_fwd_max_sdu == T_ATM_ABSENT)
701 break;
702 if ((ap->aal.v.aal5.forward_max_SDU_size <
703 aalp->ie_aalp_5_fwd_max_sdu) ||
704 (ap->aal.v.aal5.backward_max_SDU_size <
705 aalp->ie_aalp_5_bkwd_max_sdu)) {
706 cause = UNI_IE_CAUS_IECONTENT;
707 goto response06;
708 } else {
709 ap->aal.v.aal5.forward_max_SDU_size =
710 aalp->ie_aalp_5_fwd_max_sdu;
711 ap->aal.v.aal5.backward_max_SDU_size =
712 aalp->ie_aalp_5_bkwd_max_sdu;
713 }
714 break;
715 }
716 }
717
718 /*
719 * Get memory for a CONNECT ACK message
720 */
721 cack_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
722 if (cack_msg == NULL)
723 return(ENOMEM);
724
725 /*
726 * Fill out the CONNECT ACK message
727 */
728 cack_msg->msg_call_ref = uvp->uv_call_ref;
729 cack_msg->msg_type = UNI_MSG_CACK;
730 cack_msg->msg_type_flag = 0;
731 cack_msg->msg_type_action = 0;
732
733 /*
734 * Send the CONNECT ACK message
735 */
736 rc = unisig_send_msg(usp, cack_msg);
737 unisig_free_msg(cack_msg);
738
739 /*
740 * Set the new state
741 */
742 uvp->uv_sstate = UNI_ACTIVE;
743 uvp->uv_ustate = VCCU_OPEN;
744
745 /*
746 * Mark the time
747 */
748 uvp->uv_tstamp = time_second;
749
750 /*
751 * Notify the user that the connection is now active
752 */
753 atm_cm_connected(uvp->uv_connvc);
754
755 return(0);
756
757response06:
758 /*
759 * Initiate call clearing
760 */
761 rc = unisig_vc_clear_call(usp, uvp, msg, cause);
762
763 return(rc);
764}
765
766
767/*
768 * VC state machine action 7
769 * Abort routine called or signalling SAAL session reset while in
770 * one of the call setup states
771 *
772 * Clear the call, send RELEASE COMPLETE, notify the user.
773 *
774 * Arguments:
775 * usp pointer to protocol instance block
776 * uvp pointer to the VCCB for the affected connection
777 * msg pointer to a UNISIG message structure
778 *
779 * Returns:
780 * 0 success
781 * errno error encountered
782 *
783 */
784static int
785unisig_vc_act07(usp, uvp, msg)
786 struct unisig *usp;
787 struct unisig_vccb *uvp;
788 struct unisig_msg *msg;
789{
790 int rc;
791
792 /*
793 * Clear any running timer
794 */
795 UNISIG_VC_CANCEL((struct vccb *) uvp);
796
797 /*
798 * Send a RELEASE COMPLETE message rejecting the connection
799 */
800 rc = unisig_send_release_complete(usp, uvp, msg,
801 UNI_IE_CAUS_TEMP);
802
803 /*
804 * Clear the call VCCB
805 */
806 uvp->uv_sstate = UNI_FREE;
807 uvp->uv_ustate = VCCU_CLOSED;
808
809 /*
810 * Mark the time
811 */
812 uvp->uv_tstamp = time_second;
813
814 /*
815 * Notify the user
816 */
817 if ((msg != NULL) && (msg->msg_ie_caus != NULL))
818 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
819 msg->msg_ie_caus);
820 else
821 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
822 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
823 atm_cm_cleared(uvp->uv_connvc);
824
825 return(rc);
826}
827
828
829/*
830 * VC state machine action 8
831 * Received SETUP
832 *
833 * Check call paramaters, notify user that a call has been received,
834 * set UNI_CALL_PRESENT state
835 *
836 * Arguments:
837 * usp pointer to protocol instance block
838 * uvp pointer to the VCCB for the affected connection
839 * msg pointer to a UNISIG message structure
840 *
841 * Returns:
842 * 0 success
843 * errno error encountered
844 *
845 */
846static int
847unisig_vc_act08(usp, uvp, msg)
848 struct unisig *usp;
849 struct unisig_vccb *uvp;
850 struct unisig_msg *msg;
851{
852 int cause = 0, rc, vpi, vci;
853 struct atm_pif *pip = usp->us_pif;
854 struct atm_nif *nip;
855 Atm_addr_nsap *nap;
856 Atm_attributes attr;
857
858 ATM_DEBUG3("unisig_vc_act08: usp=%p, uvp=%p, msg=%p\n",
859 usp, uvp, msg);
860
861 /*
862 * Make sure that the called address is the right format
863 */
864 if (msg->msg_ie_cdad->ie_cdad_plan != UNI_IE_CDAD_PLAN_NSAP) {
865 cause = UNI_IE_CAUS_IECONTENT;
866 ATM_DEBUG0("unisig_vc_act08: bad address format\n");
867 goto response08;
868 }
869
870 /*
871 * Make sure that the called address is ours
872 */
873 nap = (Atm_addr_nsap *) msg->msg_ie_cdad->ie_cdad_addr.address;
874 if (bcmp(usp->us_addr.address, nap, /* XXX */
875 sizeof(Atm_addr_nsap)-1)) {
876 cause = UNI_IE_CAUS_IECONTENT;
877 ATM_DEBUG0("unisig_vc_act08: address not mine\n");
878 goto response08;
879 }
880
881 /*
882 * Find the right NIF for the given selector byte
883 */
884 nip = pip->pif_nif;
885 while (nip && nip->nif_sel != nap->aan_sel) {
886 nip = nip->nif_pnext;
887 }
888 if (!nip) {
889 cause = UNI_IE_CAUS_IECONTENT;
890 ATM_DEBUG0("unisig_vc_act08: bad selector byte\n");
891 goto response08;
892 }
893
894 /*
895 * See if we recognize the specified AAL
896 */
897 if (msg->msg_ie_aalp->ie_aalp_aal_type != UNI_IE_AALP_AT_AAL3 &&
898 msg->msg_ie_aalp->ie_aalp_aal_type !=
899 UNI_IE_AALP_AT_AAL5) {
900 cause = UNI_IE_CAUS_UAAL;
901 ATM_DEBUG0("unisig_vc_act08: bad AAL\n");
902 goto response08;
903 }
904
905 /*
906 * Should verify that we can handle requested
907 * connection QOS
908 */
909
910 /*
911 * Make sure the specified VPI/VCI is valid
912 */
913 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
914 vci = msg->msg_ie_cnid->ie_cnid_vci;
915 if (vpi > pip->pif_maxvpi ||
916 vci > pip->pif_maxvci ||
917 vci < UNI_IE_CNID_MIN_VCI) {
918 cause = UNI_IE_CAUS_BAD_VCC;
919 ATM_DEBUG0("unisig_vc_act08: VPI/VCI invalid\n");
920 goto response08;
921 }
922
923 /*
924 * Make sure the specified VPI/VCI isn't in use already
925 */
926 if (unisig_find_vpvc(usp, vpi, vci, VCC_IN)) {
927 cause = UNI_IE_CAUS_NA_VCC;
928 ATM_DEBUG0("unisig_vc_act08: VPI/VCI in use\n");
929 goto response08;
930 }
931
932 /*
933 * Make sure it's a point-to-point connection
934 */
935 if (msg->msg_ie_bbcp->ie_bbcp_conn_config !=
936 UNI_IE_BBCP_CC_PP) {
937 cause = UNI_IE_CAUS_NI_BC;
938 ATM_DEBUG0("unisig_vc_act08: conn not pt-pt\n");
939 goto response08;
940 }
941
942 /*
943 * Fill in the VCCB fields that we can at this point
944 */
945 uvp->uv_type = VCC_SVC | VCC_IN | VCC_OUT;
946 uvp->uv_proto = pip->pif_sigmgr->sm_proto;
947 uvp->uv_sstate = UNI_CALL_PRESENT;
948 uvp->uv_ustate = VCCU_POPEN;
949 uvp->uv_pif = pip;
950 uvp->uv_nif = nip;
951 uvp->uv_vpi = msg->msg_ie_cnid->ie_cnid_vpci;
952 uvp->uv_vci = msg->msg_ie_cnid->ie_cnid_vci;
953 uvp->uv_tstamp = time_second;
954
955 /*
956 * Copy the connection attributes from the SETUP message
957 * to an attribute block
958 */
959 KM_ZERO(&attr, sizeof(attr));
960 attr.nif = nip;
961 attr.aal.tag = T_ATM_ABSENT;
962 attr.traffic.tag = T_ATM_ABSENT;
963 attr.bearer.tag = T_ATM_ABSENT;
964 attr.bhli.tag = T_ATM_ABSENT;
965 attr.blli.tag_l2 = T_ATM_ABSENT;
966 attr.blli.tag_l3 = T_ATM_ABSENT;
967 attr.llc.tag = T_ATM_ABSENT;
968 attr.called.tag = T_ATM_ABSENT;
969 attr.calling.tag = T_ATM_ABSENT;
970 attr.qos.tag = T_ATM_ABSENT;
971 attr.transit.tag = T_ATM_ABSENT;
972 attr.cause.tag = T_ATM_ABSENT;
973 unisig_save_attrs(usp, msg, &attr);
974
975 /*
976 * Notify the connection manager of the new VCC
977 */
978 ATM_DEBUG0("unisig_vc_act08: notifying user of connection\n");
979 rc = atm_cm_incoming((struct vccb *)uvp, &attr);
980 if (rc)
981 goto response08;
982
983 /*
984 * Wait for the connection recipient to issue an accept
985 * or reject
986 */
987 return(0);
988
989response08:
990 ATM_DEBUG1("unisig_vc_act08: reject with cause=%d\n", cause);
991
992 /*
993 * Clear the VCCB state
994 */
995 uvp->uv_sstate = UNI_NULL;
996
997 /*
998 * Mark the time
999 */
1000 uvp->uv_tstamp = time_second;
1001
1002 /*
1003 * Some problem was detected with the request. Send a Q.2931
1004 * message rejecting the connection.
1005 */
1006 rc = unisig_send_release_complete(usp, uvp, msg, cause);
1007
1008 return(rc);
1009}
1010
1011
1012/*
1013 * VC state machine action 9
1014 * Accept routine called by user
1015 *
1016 * Send CONNECT, start timer T313, go to UNI_CONNECT_REQUEST state
1017 *
1018 * Arguments:
1019 * usp pointer to protocol instance block
1020 * uvp pointer to the VCCB for the affected connection
1021 * msg pointer to a UNISIG message structure
1022 *
1023 * Returns:
1024 * 0 success
1025 * errno error encountered
1026 *
1027 */
1028static int
1029unisig_vc_act09(usp, uvp, msg)
1030 struct unisig *usp;
1031 struct unisig_vccb *uvp;
1032 struct unisig_msg *msg;
1033{
1034 int rc;
1035 struct unisig_msg *conn_msg;
1036
1037 conn_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1038 if (conn_msg == NULL)
1039 return(ENOMEM);
1040
1041 /*
1042 * Fill out the response
1043 */
1044 conn_msg->msg_call_ref = uvp->uv_call_ref;
1045 conn_msg->msg_type = UNI_MSG_CONN;
1046 conn_msg->msg_type_flag = 0;
1047 conn_msg->msg_type_action = 0;
1048
1049 /*
1050 * Send the CONNECT message. If the send fails, the other
1051 * side will eventually time out and close the connection.
1052 */
1053 rc = unisig_send_msg(usp, conn_msg);
1054 unisig_free_msg(conn_msg);
1055 if (rc) {
1056 return(rc);
1057 }
1058
1059 /*
1060 * Start timer T313
1061 */
1062 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T313);
1063
1064 /*
1065 * Set the new state
1066 */
1067 uvp->uv_sstate = UNI_CONNECT_REQUEST;
1068
1069 /*
1070 * Mark the time
1071 */
1072 uvp->uv_tstamp = time_second;
1073
1074 return(0);
1075}
1076
1077
1078/*
1079 * VC state machine action 10
1080 * Received CONNECT ACK
1081 *
1082 * Go to UNI_ACTIVE state
1083 *
1084 * Arguments:
1085 * usp pointer to protocol instance block
1086 * uvp pointer to the VCCB for the affected connection
1087 * msg pointer to a UNISIG message structure
1088 *
1089 * Returns:
1090 * 0 success
1091 * errno error encountered
1092 *
1093 */
1094static int
1095unisig_vc_act10(usp, uvp, msg)
1096 struct unisig *usp;
1097 struct unisig_vccb *uvp;
1098 struct unisig_msg *msg;
1099{
1100 /*
1101 * Clear any running timer
1102 */
1103 UNISIG_VC_CANCEL((struct vccb *) uvp);
1104
1105 /*
1106 * Set the state
1107 */
1108 uvp->uv_sstate = UNI_ACTIVE;
1109 uvp->uv_ustate = VCCU_OPEN;
1110
1111 /*
1112 * Mark the time
1113 */
1114 uvp->uv_tstamp = time_second;
1115
1116 /*
1117 * Notify the user that the call is up
1118 */
1119 atm_cm_connected(uvp->uv_connvc);
1120
1121 return (0);
1122}
1123
1124
1125/*
1126 * VC state machine action 11
1127 * Reject handler called
1128 *
1129 * Send RELEASE COMPLETE, clear the call
1130 *
1131 * Arguments:
1132 * usp pointer to protocol instance block
1133 * uvp pointer to the VCCB for the affected connection
1134 * msg pointer to a UNISIG message structure
1135 *
1136 * Returns:
1137 * 0 success
1138 * errno error encountered
1139 *
1140 */
1141static int
1142unisig_vc_act11(usp, uvp, msg)
1143 struct unisig *usp;
1144 struct unisig_vccb *uvp;
1145 struct unisig_msg *msg;
1146{
1147 int rc, cause;
1148
1149 /*
1150 * Send generic cause code if one is not already set
1151 */
1152 if (uvp->uv_connvc->cvc_attr.cause.tag == T_ATM_PRESENT)
1153 cause = T_ATM_ABSENT;
1154 else
1155 cause = T_ATM_CAUSE_CALL_REJECTED;
1156
1157 /*
1158 * Send a RELEASE COMPLETE message
1159 */
1160 rc = unisig_send_release_complete(usp, uvp, msg, cause);
1161
1162 /*
1163 * Clear the call VCCB
1164 */
1165 uvp->uv_sstate = UNI_FREE;
1166 uvp->uv_ustate = VCCU_CLOSED;
1167
1168 /*
1169 * Mark the time
1170 */
1171 uvp->uv_tstamp = time_second;
1172
1173 return(rc);
1174}
1175
1176
1177/*
1178 * VC state machine action 12
1179 * Release or abort routine called
1180 *
1181 * Send RELEASE, start timer T308, go to UNI_RELEASE_REQUEST state
1182 *
1183 * Arguments:
1184 * usp pointer to protocol instance block
1185 * uvp pointer to the VCCB for the affected connection
1186 * msg pointer to a UNISIG message structure
1187 *
1188 * Returns:
1189 * 0 success
1190 * errno error encountered
1191 *
1192 */
1193static int
1194unisig_vc_act12(usp, uvp, msg)
1195 struct unisig *usp;
1196 struct unisig_vccb *uvp;
1197 struct unisig_msg *msg;
1198{
1199 int rc;
1200
1201 /*
1202 * Clear any running timer
1203 */
1204 UNISIG_VC_CANCEL((struct vccb *) uvp);
1205
1206 /*
1207 * Send the RELEASE message
1208 */
1209 rc = unisig_vc_clear_call(usp, uvp, (struct unisig_msg *)NULL,
1210 T_ATM_ABSENT);
1211
1212 return(rc);
1213}
1214
1215
1216/*
1217 * VC state machine action 13
1218 * RELEASE COMPLETE received
1219 *
1220 * Clear the call
1221 *
1222 * Arguments:
1223 * usp pointer to protocol instance block
1224 * uvp pointer to the VCCB for the affected connection
1225 * msg pointer to a UNISIG message structure
1226 *
1227 * Returns:
1228 * 0 success
1229 * errno error encountered
1230 *
1231 */
1232static int
1233unisig_vc_act13(usp, uvp, msg)
1234 struct unisig *usp;
1235 struct unisig_vccb *uvp;
1236 struct unisig_msg *msg;
1237{
1238 /*
1239 * Clear any running timer
1240 */
1241 UNISIG_VC_CANCEL((struct vccb *) uvp);
1242
1243 /*
1244 * Set the state
1245 */
1246 uvp->uv_sstate = UNI_FREE;
1247 if (uvp->uv_ustate != VCCU_ABORT)
1248 uvp->uv_ustate = VCCU_CLOSED;
1249
1250 /*
1251 * Mark the time
1252 */
1253 uvp->uv_tstamp = time_second;
1254
1255 /*
1256 * Notify the user that the call is now closed
1257 */
1258 if (msg->msg_ie_caus != NULL)
1259 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1260 msg->msg_ie_caus);
1261 atm_cm_cleared(uvp->uv_connvc);
1262
1263 return(0);
1264}
1265
1266
1267/*
1268 * VC state machine action 14
1269 * Timer expired while waiting for RELEASE COMPLETE
1270 *
1271 * If this is the second expiration, just clear the call. Otherwise,
1272 * retransmit the RELEASE message and restart timer T308.
1273 *
1274 * Arguments:
1275 * usp pointer to protocol instance block
1276 * uvp pointer to the VCCB for the affected connection
1277 * msg pointer to a UNISIG message structure
1278 *
1279 * Returns:
1280 * 0 success
1281 * errno error encountered
1282 *
1283 */
1284static int
1285unisig_vc_act14(usp, uvp, msg)
1286 struct unisig *usp;
1287 struct unisig_vccb *uvp;
1288 struct unisig_msg *msg;
1289{
1290 int rc;
1291
1292 /*
1293 * Check the retry count
1294 */
1295 if (uvp->uv_retry) {
1296 /*
1297 * Clear the connection
1298 */
1299 rc = unisig_clear_vcc(usp, uvp,
1300 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1301 } else {
1302 /*
1303 * Increment the retry count
1304 */
1305 uvp->uv_retry++;
1306
1307 /*
1308 * Resend the RELEASE message
1309 */
1310 rc = unisig_send_release(usp, uvp,
1311 (struct unisig_msg *)0, T_ATM_ABSENT);
1312 if (rc)
1313 return(rc);
1314
1315 /*
1316 * Restart timer T308
1317 */
1318 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
1319 }
1320
1321 return(0);
1322}
1323
1324
1325/*
1326 * VC state machine action 15
1327 * RELEASE received in UNI_ACTIVE state
1328 *
1329 * Send RELEASE COMPLETE, go to UNI_FREE, notify the user
1330 *
1331 * Arguments:
1332 * usp pointer to protocol instance block
1333 * uvp pointer to the VCCB for the affected connection
1334 * msg pointer to a UNISIG message structure
1335 *
1336 * Returns:
1337 * 0 success
1338 * errno error encountered
1339 *
1340 */
1341static int
1342unisig_vc_act15(usp, uvp, msg)
1343 struct unisig *usp;
1344 struct unisig_vccb *uvp;
1345 struct unisig_msg *msg;
1346{
1347 int cause, rc;
1348 struct ie_generic *iep;
1349
1350 /*
1351 * Clear any running timer
1352 */
1353 UNISIG_VC_CANCEL((struct vccb *) uvp);
1354
1355 /*
1356 * If there was no Cause IE, flag an error
1357 */
1358 if (!msg->msg_ie_caus) {
1359 cause = UNI_IE_CAUS_MISSING;
1360 for (iep=msg->msg_ie_err; iep; iep=iep->ie_next) {
1361 if (iep->ie_ident == UNI_IE_CAUS &&
1362 iep->ie_err_cause ==
1363 UNI_IE_CAUS_IECONTENT) {
1364 cause = UNI_IE_CAUS_IECONTENT;
1365 }
1366 }
1367 if (cause == UNI_IE_CAUS_MISSING) {
1368 iep = (struct ie_generic *)atm_allocate(
1369 &unisig_iepool);
1370 if (!iep)
1371 return(ENOMEM);
1372 iep->ie_ident = UNI_IE_CNID;
1373 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
1374 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
1375 }
1376 } else {
1377 cause = UNI_IE_CAUS_NORM_UNSP;
1378 }
1379
1380 /*
1381 * Send a RELEASE COMPLETE message
1382 */
1383 rc = unisig_send_release_complete(usp, uvp, msg, cause);
1384
1385 /*
1386 * Set the state
1387 */
1388 uvp->uv_sstate = UNI_FREE;
1389 uvp->uv_ustate = VCCU_CLOSED;
1390
1391 /*
1392 * Mark the time
1393 */
1394 uvp->uv_tstamp = time_second;
1395
1396 /*
1397 * Notify the user that the call is cleared
1398 */
1399 if (msg->msg_ie_caus != NULL)
1400 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1401 msg->msg_ie_caus);
1402 else
1403 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1404 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
1405 atm_cm_cleared(uvp->uv_connvc);
1406
1407 return(rc);
1408}
1409
1410
1411/*
1412 * VC state machine action 16
1413 * RELEASE received in UNI_RELEASE_REQUEST state
1414 *
1415 * Clear the call
1416 *
1417 * Arguments:
1418 * usp pointer to protocol instance block
1419 * uvp pointer to the VCCB for the affected connection
1420 * msg pointer to a UNISIG message structure
1421 *
1422 * Returns:
1423 * 0 success
1424 * errno error encountered
1425 *
1426 */
1427static int
1428unisig_vc_act16(usp, uvp, msg)
1429 struct unisig *usp;
1430 struct unisig_vccb *uvp;
1431 struct unisig_msg *msg;
1432{
1433 int rc;
1434
1435 /*
1436 * Clear any running timer
1437 */
1438 UNISIG_VC_CANCEL((struct vccb *) uvp);
1439
1440 /*
1441 * Clear the VCCB
1442 */
1443 rc = unisig_clear_vcc(usp, uvp, T_ATM_ABSENT);
1444
1445 return(rc);
1446}
1447
1448
1449/*
1450 * VC state machine action 17
1451 * Protocol error
1452 *
1453 * Send a STATUS message with cause 101, "message not compatible with
1454 * call state"
1455 *
1456 * Arguments:
1457 * usp pointer to protocol instance block
1458 * uvp pointer to the VCCB for the affected connection
1459 * msg pointer to a UNISIG message structure
1460 *
1461 * Returns:
1462 * 0 success
1463 * errno error encountered
1464 *
1465 */
1466static int
1467unisig_vc_act17(usp, uvp, msg)
1468 struct unisig *usp;
1469 struct unisig_vccb *uvp;
1470 struct unisig_msg *msg;
1471{
1472 int rc;
1473
1474 ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1475 usp, uvp, msg);
1476
1477 /*
1478 * Clear any running timer
1479 */
1480 UNISIG_VC_CANCEL((struct vccb *) uvp);
1481
1482 /*
1483 * Send a STATUS message
1484 */
1485 rc = unisig_send_status(usp, uvp, msg, UNI_IE_CAUS_STATE);
1486
1487 return(rc ? rc : EINVAL);
1488}
1489
1490
1491/*
1492 * VC state machine action 18
1493 * Signalling AAL connection has been lost
1494 *
1495 * Start timer T309. If the timer expires before the SAAL connection
1496 * comes back, the VCC will be cleared.
1497 *
1498 * Arguments:
1499 * usp pointer to protocol instance block
1500 * uvp pointer to the VCCB for the affected connection
1501 * msg pointer to a UNISIG message structure
1502 *
1503 * Returns:
1504 * 0 success
1505 * errno error encountered
1506 *
1507 */
1508static int
1509unisig_vc_act18(usp, uvp, msg)
1510 struct unisig *usp;
1511 struct unisig_vccb *uvp;
1512 struct unisig_msg *msg;
1513{
1514 /*
1515 * Clear any running timer
1516 */
1517 UNISIG_VC_CANCEL((struct vccb *) uvp);
1518
1519 /*
1520 * Start timer T309
1521 */
1522 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T309);
1523
1524 /*
1525 * Set new state
1526 */
1527 uvp->uv_sstate = UNI_SSCF_RECOV;
1528
1529 return(0);
1530}
1531
1532
1533/*
1534 * VC state machine action 19
1535 * Ignore the event
1536 *
1537 * Arguments:
1538 * usp pointer to protocol instance block
1539 * uvp pointer to the VCCB for the affected connection
1540 * msg pointer to a UNISIG message structure
1541 *
1542 * Returns:
1543 * 0 success
1544 * errno error encountered
1545 *
1546 */
1547static int
1548unisig_vc_act19(usp, uvp, msg)
1549 struct unisig *usp;
1550 struct unisig_vccb *uvp;
1551 struct unisig_msg *msg;
1552{
1553 return(0);
1554}
1555
1556
1557/*
1558 * VC state machine action 20
1559 * SSCF establish indication in UNI_SSCF_RECOV state -- signalling
1560 * AAL has come up after an outage
1561 *
1562 * Send STATUS ENQ to make sure we're in compatible state with other end
1563 *
1564 * Arguments:
1565 * usp pointer to protocol instance block
1566 * uvp pointer to the VCCB for the affected connection
1567 * msg pointer to a UNISIG message structure
1568 *
1569 * Returns:
1570 * 0 success
1571 * errno error encountered
1572 *
1573 */
1574static int
1575unisig_vc_act20(usp, uvp, msg)
1576 struct unisig *usp;
1577 struct unisig_vccb *uvp;
1578 struct unisig_msg *msg;
1579{
1580 int rc;
1581 struct unisig_msg *stat_msg;
1582
1583 /*
1584 * Clear any running timer
1585 */
1586 UNISIG_VC_CANCEL((struct vccb *) uvp);
1587
1588 /*
1589 * Get memory for a STATUS ENQUIRY message
1590 */
1591 stat_msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
1592 if (stat_msg == NULL)
1593 return(ENOMEM);
1594
1595 /*
1596 * Fill out the message
1597 */
1598 stat_msg->msg_call_ref = uvp->uv_call_ref;
1599 stat_msg->msg_type = UNI_MSG_SENQ;
1600 stat_msg->msg_type_flag = 0;
1601 stat_msg->msg_type_action = 0;
1602
1603 /*
1604 * Send the STATUS ENQUIRY message
1605 */
1606 rc = unisig_send_msg(usp, stat_msg);
1607 unisig_free_msg(stat_msg);
1608
1609 /*
1610 * Return to active state
1611 */
1612 uvp->uv_sstate = UNI_ACTIVE;
1613
1614 return(rc);
1615}
1616
1617
1618/*
1619 * VC state machine action 21
1620 * STATUS received
1621 *
1622 * Arguments:
1623 * usp pointer to protocol instance block
1624 * uvp pointer to the VCCB for the affected connection (may
1625 * be NULL)
1626 * msg pointer to a UNISIG message structure
1627 *
1628 * Returns:
1629 * 0 success
1630 * errno error encountered
1631 *
1632 */
1633static int
1634unisig_vc_act21(usp, uvp, msg)
1635 struct unisig *usp;
1636 struct unisig_vccb *uvp;
1637 struct unisig_msg *msg;
1638{
1639 int cause, rc;
1640
1641 /*
1642 * Ignore a STATUS message with the global call reference
1643 */
1644 if (GLOBAL_CREF(msg->msg_call_ref)) {
1645 return(0);
1646 }
1647
1648 /*
1649 * If the network thinks we're in NULL state, clear the VCC
1650 */
1651 if (msg->msg_ie_clst->ie_clst_state == UNI_NULL) {
1652 if (uvp) {
1653 (void)unisig_clear_vcc(usp, uvp,
1654 T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER);
1655 }
1656 return(0);
1657 }
1658
1659 /*
1660 * If we are in NULL state, send a RELEASE COMPLETE
1661 */
1662 if (!uvp || (uvp->uv_sstate == UNI_FREE) ||
1663 (uvp->uv_sstate == UNI_NULL)) {
1664 rc = unisig_send_release_complete(usp,
1665 uvp, msg, UNI_IE_CAUS_STATE);
1666 return(rc);
1667 }
1668
1669 /*
1670 * If the reported state doesn't match our state, close the VCC
1671 * unless we're in UNI_RELEASE_REQUEST or UNI_RELEASE_IND
1672 */
1673 if (msg->msg_ie_clst->ie_clst_state != uvp->uv_sstate) {
1674 if (uvp->uv_sstate == UNI_RELEASE_REQUEST ||
1675 uvp->uv_sstate == UNI_RELEASE_IND) {
1676 return(0);
1677 }
1678 rc = unisig_clear_vcc(usp, uvp,
1679 T_ATM_CAUSE_MESSAGE_INCOMPATIBLE_WITH_CALL_STATE);
1680 }
1681
1682 /*
1683 * States match, check for an error on one of our messages
1684 */
1685 cause = msg->msg_ie_caus->ie_caus_cause;
1686 if (cause == UNI_IE_CAUS_MISSING ||
1687 cause == UNI_IE_CAUS_MTEXIST ||
1688 cause == UNI_IE_CAUS_IEEXIST ||
1689 cause == UNI_IE_CAUS_IECONTENT ||
1690 cause == UNI_IE_CAUS_STATE) {
1691 ATM_DEBUG2("unisig_vc_act21: error %d on message 0x%x\n",
1692 cause,
1693 msg->msg_ie_caus->ie_caus_diagnostic[0]);
1694 if (uvp) {
1695 (void)unisig_clear_vcc(usp, uvp, cause);
1696 }
1697 }
1698
1699 return(0);
1700}
1701
1702
1703/*
1704 * VC state machine action 22
1705 * Received STATUS ENQ
1706 *
1707 * Send STATUS with cause 30 "response to STATUS ENQUIRY" and
1708 * current state
1709 *
1710 * Arguments:
1711 * usp pointer to protocol instance block
1712 * uvp pointer to the VCCB for the affected connection (may
1713 * be NULL)
1714 * msg pointer to a UNISIG message structure
1715 *
1716 * Returns:
1717 * 0 success
1718 * errno error encountered
1719 *
1720 */
1721static int
1722unisig_vc_act22(usp, uvp, msg)
1723 struct unisig *usp;
1724 struct unisig_vccb *uvp;
1725 struct unisig_msg *msg;
1726{
1727 int rc;
1728 struct unisig_msg *status;
1729 struct ie_generic *callst_ie, *cause_ie;
1730
1731 ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1732 usp, uvp, msg);
1733
1734 /*
1735 * Get memory for a STATUS message
1736 */
1737 status = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1738 if (status == NULL)
1739 return(ENOMEM);
1740 callst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1741 if (callst_ie == NULL) {
1742 atm_free(status);
1743 return(ENOMEM);
1744 }
1745 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1746 if (cause_ie == NULL) {
1747 atm_free(status);
1748 atm_free(callst_ie);
1749 return(ENOMEM);
1750 }
1751
1752 /*
1753 * Fill out the response
1754 */
1755 if (uvp) {
1756 status->msg_call_ref = uvp->uv_call_ref;
1757 } else if (msg) {
1758 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1759 status->msg_call_ref = msg->msg_call_ref &
1760 UNI_MSG_CALL_REF_MASK;
1761 else
1762 status->msg_call_ref = msg->msg_call_ref |
1763 UNI_MSG_CALL_REF_RMT;
1764 } else {
1765 status->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
1766 }
1767 status->msg_type = UNI_MSG_STAT;
1768 status->msg_type_flag = 0;
1769 status->msg_type_action = 0;
1770 status->msg_ie_clst = callst_ie;
1771 status->msg_ie_caus = cause_ie;
1772
1773 /*
1774 * Fill out the call state IE
1775 */
1776 callst_ie->ie_ident = UNI_IE_CLST;
1777 callst_ie->ie_coding = 0;
1778 callst_ie->ie_flag = 0;
1779 callst_ie->ie_action = 0;
1780 if (uvp) {
1781 switch(uvp->uv_sstate) {
1782 case UNI_FREE:
1783 callst_ie->ie_clst_state = UNI_NULL;
1784 break;
1785 default:
1786 callst_ie->ie_clst_state = uvp->uv_sstate;
1787 }
1788 } else {
1789 callst_ie->ie_clst_state = UNI_NULL;
1790 }
1791
1792 /*
1793 * Fill out the cause IE
1794 */
1795 cause_ie->ie_ident = UNI_IE_CAUS;
1796 cause_ie->ie_coding = 0;
1797 cause_ie->ie_flag = 0;
1798 cause_ie->ie_action = 0;
1799 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
1800 cause_ie->ie_caus_cause = UNI_IE_CAUS_SENQ;
1801
1802 /*
1803 * Send the STATUS message
1804 */
1805 rc = unisig_send_msg(usp, status);
1806 unisig_free_msg(status);
1807 return(rc);
1808}
1809
1810
1811/*
1812 * VC state machine action 23
1813 * Received ADD PARTY
1814 *
1815 * We don't support multipoint connections, so send an ADD PARTY REJECT
1816 *
1817 * Arguments:
1818 * usp pointer to protocol instance block
1819 * uvp pointer to the VCCB for the affected connection
1820 * msg pointer to a UNISIG message structure
1821 *
1822 * Returns:
1823 * 0 success
1824 * errno error encountered
1825 *
1826 */
1827static int
1828unisig_vc_act23(usp, uvp, msg)
1829 struct unisig *usp;
1830 struct unisig_vccb *uvp;
1831 struct unisig_msg *msg;
1832{
1833 int rc;
1834 struct unisig_msg *apr_msg;
1835
1836 /*
1837 * Get memory for the ADD PARTY REJECT message
1838 */
1839 apr_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1840 if (apr_msg == NULL)
1841 return(ENOMEM);
1842
1843 /*
1844 * Fill out the message
1845 */
1846 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1847 apr_msg->msg_call_ref = msg->msg_call_ref &
1848 UNI_MSG_CALL_REF_MASK;
1849 else
1850 apr_msg->msg_call_ref = msg->msg_call_ref |
1851 UNI_MSG_CALL_REF_RMT;
1852 apr_msg->msg_type = UNI_MSG_ADPR;
1853 apr_msg->msg_type_flag = 0;
1854 apr_msg->msg_type_action = 0;
1855
1856 /*
1857 * Use the endpoint reference IE from the received message
1858 */
1859 apr_msg->msg_ie_eprf = msg->msg_ie_eprf;
1860
1861 /*
1862 * Send the ADD PARTY REJECT message
1863 */
1864 rc = unisig_send_msg(usp, apr_msg);
1865 apr_msg->msg_ie_eprf = NULL;
1866 unisig_free_msg(apr_msg);
1867
1868 return(rc);
1869}
1870
1871
1872/*
1873 * VC state machine action 24
1874 * User error
1875 *
1876 * Return EALREADY
1877 *
1878 * Arguments:
1879 * usp pointer to protocol instance block
1880 * uvp pointer to the VCCB for the affected connection
1881 * msg pointer to a UNISIG message structure
1882 *
1883 * Returns:
1884 * 0 success
1885 * errno error encountered
1886 *
1887 */
1888static int
1889unisig_vc_act24(usp, uvp, msg)
1890 struct unisig *usp;
1891 struct unisig_vccb *uvp;
1892 struct unisig_msg *msg;
1893{
1894 return(EALREADY);
1895}
1896
1897
1898/*
1899 * VC state machine action 25
1900 * User error
1901 *
1902 * Return EINVAL
1903 *
1904 * Arguments:
1905 * usp pointer to protocol instance block
1906 * uvp pointer to the VCCB for the affected connection
1907 * msg pointer to a UNISIG message structure
1908 *
1909 * Returns:
1910 * 0 success
1911 * errno error encountered
1912 *
1913 */
1914static int
1915unisig_vc_act25(usp, uvp, msg)
1916 struct unisig *usp;
1917 struct unisig_vccb *uvp;
1918 struct unisig_msg *msg;
1919{
1920 return(EINVAL);
1921}
1922
1923
1924/*
1925 * VC state machine action 26
1926 * PVC abort
1927 *
1928 * The abort handler was called to abort a PVC. Clear the VCCB and
1929 * notify the user.
1930 *
1931 * Arguments:
1932 * usp pointer to protocol instance block
1933 * uvp pointer to the VCCB for the affected connection
1934 * msg pointer to a UNISIG message structure
1935 *
1936 * Returns:
1937 * 0 success
1938 * errno error encountered
1939 *
1940 */
1941static int
1942unisig_vc_act26(usp, uvp, msg)
1943 struct unisig *usp;
1944 struct unisig_vccb *uvp;
1945 struct unisig_msg *msg;
1946{
1947 int rc;
1948
1949 /*
1950 * Clear any running timer
1951 */
1952 UNISIG_VC_CANCEL((struct vccb *) uvp);
1953
1954 /*
1955 * Close the VCCB
1956 */
1957 rc = unisig_close_vcc(usp, uvp);
1958 if (rc)
1959 return(rc);
1960
1961 /*
1962 * Notify the user
1963 */
1964 if (uvp->uv_connvc->cvc_attr.cause.tag != T_ATM_PRESENT)
1965 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1966 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1967
1968 atm_cm_cleared(uvp->uv_connvc);
1969
1970 return(0);
1971}
1972
1973
1974/*
1975 * VC state machine action 27
1976 * Signalling AAL failure
1977 *
1978 * Change PVC state to UNI_PVC_ACT_DOWN.
1979 *
1980 * Arguments:
1981 * usp pointer to protocol instance block
1982 * uvp pointer to the VCCB for the affected connection
1983 * msg pointer to a UNISIG message structure
1984 *
1985 * Returns:
1986 * 0 success
1987 * errno error encountered
1988 *
1989 */
1990static int
1991unisig_vc_act27(usp, uvp, msg)
1992 struct unisig *usp;
1993 struct unisig_vccb *uvp;
1994 struct unisig_msg *msg;
1995{
1996 /*
1997 * Set the state
1998 */
1999 uvp->uv_sstate = UNI_PVC_ACT_DOWN;
2000
2001 /*
2002 * Mark the time
2003 */
2004 uvp->uv_tstamp = time_second;
2005
2006 return(0);
2007}
2008
2009
2010/*
2011 * VC state machine action 28
2012 * Signalling AAL established
2013 *
2014 * Set PVC state to UNI_PVC_ACTIVE.
2015 *
2016 * Arguments:
2017 * usp pointer to protocol instance block
2018 * uvp pointer to the VCCB for the affected connection
2019 * msg pointer to a UNISIG message structure
2020 *
2021 * Returns:
2022 * 0 success
2023 * errno error encountered
2024 *
2025 */
2026static int
2027unisig_vc_act28(usp, uvp, msg)
2028 struct unisig *usp;
2029 struct unisig_vccb *uvp;
2030 struct unisig_msg *msg;
2031{
2032 /*
2033 * Set the state
2034 */
2035 uvp->uv_sstate = UNI_PVC_ACTIVE;
2036
2037 /*
2038 * Mark the time
2039 */
2040 uvp->uv_tstamp = time_second;
2041
2042 return(0);
2043}
2044
2045
2046/*
2047 * VC state machine action 29
2048 * Protocol error
2049 *
2050 * Send a RELEASE COMPLETE message with cause 81, "invalid call
2051 * reference value"
2052 *
2053 * Arguments:
2054 * usp pointer to protocol instance block
2055 * uvp pointer to the VCCB for the affected connection (may
2056 * be NULL)
2057 * msg pointer to a UNISIG message structure
2058 *
2059 * Returns:
2060 * 0 success
2061 * errno error encountered
2062 *
2063 */
2064static int
2065unisig_vc_act29(usp, uvp, msg)
2066 struct unisig *usp;
2067 struct unisig_vccb *uvp;
2068 struct unisig_msg *msg;
2069{
2070 int rc;
2071
2072 /*
2073 * Send a RELEASE COMPLETE message
2074 */
2075 rc = unisig_send_release_complete(usp, uvp, msg,
2076 UNI_IE_CAUS_CREF);
2077
2078 return(rc);
2079}
2080
2081
2082/*
2083 * VC state machine action 30
2084 * Release routine called while SSCF session down, or SSCF session
2085 * reset or lost while in UNI_CALL_PRESENT
2086 *
2087 * Go to UNI_FREE state
2088 *
2089 * Arguments:
2090 * usp pointer to protocol instance block
2091 * uvp pointer to the VCCB for the affected connection
2092 * msg pointer to a UNISIG message structure
2093 *
2094 * Returns:
2095 * 0 success
2096 * errno error encountered
2097 *
2098 */
2099static int
2100unisig_vc_act30(usp, uvp, msg)
2101 struct unisig *usp;
2102 struct unisig_vccb *uvp;
2103 struct unisig_msg *msg;
2104{
2105 /*
2106 * Clear any running timer
2107 */
2108 UNISIG_VC_CANCEL((struct vccb *) uvp);
2109
2110 /*
2111 * Clear the call state
2112 */
2113 uvp->uv_sstate = UNI_FREE;
2114 uvp->uv_ustate = VCCU_CLOSED;
2115
2116 /*
2117 * Mark the time
2118 */
2119 uvp->uv_tstamp = time_second;
2120
2121 return(0);
2122}
2123
2124
2125/*
2126 * VC state machine action 31
2127 * Accept handler called in UNI_FREE state.
2128 *
2129 * The call was in UNI_CALL_PRESENT state when it was closed because
2130 * of an SSCF failure. Return an error indication. The accept
2131 * handler will free the VCCB and return the proper code to the
2132 * caller.
2133 *
2134 * Arguments:
2135 * usp pointer to protocol instance block
2136 * uvp pointer to the VCCB for the affected connection
2137 * msg pointer to a UNISIG message structure
2138 *
2139 * Returns:
2140 * 0 success
2141 * errno error encountered
2142 *
2143 */
2144static int
2145unisig_vc_act31(usp, uvp, msg)
2146 struct unisig *usp;
2147 struct unisig_vccb *uvp;
2148 struct unisig_msg *msg;
2149{
2150 return(ENETDOWN);
2151}
2152
2153
2154/*
2155 * Initiate clearing a call by sending a RELEASE message.
2156 *
2157 * Arguments:
2158 * usp pointer to protocol instance block
2159 * uvp pointer to the VCCB for the affected connection
2160 * msg pointer to UNI signalling message that the RELEASE
2161 * responds to (may be NULL)
2162 * cause the reason for clearing the call; a value of
2163 * T_ATM_ABSENT indicates that the cause code is
2164 * in the VCC's ATM attributes block
2165 *
2166 * Returns:
2167 * 0 success
2168 * errno error encountered
2169 *
2170 */
2171static int
2172unisig_vc_clear_call(usp, uvp, msg, cause)
2173 struct unisig *usp;
2174 struct unisig_vccb *uvp;
2175 struct unisig_msg *msg;
2176 int cause;
2177{
2178 int rc;
2179
2180 /*
2181 * Clear the retry count
2182 */
2183 uvp->uv_retry = 0;
2184
2185 /*
2186 * Make sure the ATM attributes block has a valid cause code,
2187 * if needed
2188 */
2189 if (cause == T_ATM_ABSENT &&
2190 uvp->uv_connvc->cvc_attr.cause.tag !=
2191 T_ATM_PRESENT) {
2192 uvp->uv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
2193 uvp->uv_connvc->cvc_attr.cause.v.coding_standard =
2194 T_ATM_ITU_CODING;
2195 uvp->uv_connvc->cvc_attr.cause.v.location =
2196 T_ATM_LOC_USER;
2197 uvp->uv_connvc->cvc_attr.cause.v.cause_value =
2198 usp->us_proto == ATM_SIG_UNI30 ?
2199 T_ATM_CAUSE_UNSPECIFIED_NORMAL :
2200 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
2201 }
2202
2203 /*
2204 * Send a RELEASE message
2205 */
2206 rc = unisig_send_release(usp, uvp, msg, cause);
2207 if (rc)
2208 return(rc);
2209
2210 /*
2211 * Start timer T308
2212 */
2213 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
2214
2215 /*
2216 * Set the VCCB state
2217 */
2218 uvp->uv_sstate = UNI_RELEASE_REQUEST;
2219 if (uvp->uv_ustate != VCCU_ABORT)
2220 uvp->uv_ustate = VCCU_CLOSED;
2221
2222 /*
2223 * Mark the time
2224 */
2225 uvp->uv_tstamp = time_second;
2226
2227 return(0);
2228}