3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/unisig_vc_state.c,v 1.6.2.1 2001/07/25 20:53:44 pirzyk Exp $
30 * ATM Forum UNI 3.0/3.1 Signalling Manager
31 * ----------------------------------------
37 #include <netproto/atm/kern_include.h>
39 #include "unisig_var.h"
40 #include "unisig_msg.h"
45 static int unisig_vc_invalid (struct unisig *, struct unisig_vccb *,
47 static int unisig_vc_act01 (struct unisig *, struct unisig_vccb *,
49 static int unisig_vc_act02 (struct unisig *, struct unisig_vccb *,
51 static int unisig_vc_act03 (struct unisig *, struct unisig_vccb *,
53 static int unisig_vc_act04 (struct unisig *, struct unisig_vccb *,
55 static int unisig_vc_act05 (struct unisig *, struct unisig_vccb *,
57 static int unisig_vc_act06 (struct unisig *, struct unisig_vccb *,
59 static int unisig_vc_act07 (struct unisig *, struct unisig_vccb *,
61 static int unisig_vc_act08 (struct unisig *, struct unisig_vccb *,
63 static int unisig_vc_act09 (struct unisig *, struct unisig_vccb *,
65 static int unisig_vc_act10 (struct unisig *, struct unisig_vccb *,
67 static int unisig_vc_act11 (struct unisig *, struct unisig_vccb *,
69 static int unisig_vc_act12 (struct unisig *, struct unisig_vccb *,
71 static int unisig_vc_act13 (struct unisig *, struct unisig_vccb *,
73 static int unisig_vc_act14 (struct unisig *, struct unisig_vccb *,
75 static int unisig_vc_act15 (struct unisig *, struct unisig_vccb *,
77 static int unisig_vc_act16 (struct unisig *, struct unisig_vccb *,
79 static int unisig_vc_act17 (struct unisig *, struct unisig_vccb *,
81 static int unisig_vc_act18 (struct unisig *, struct unisig_vccb *,
83 static int unisig_vc_act19 (struct unisig *, struct unisig_vccb *,
85 static int unisig_vc_act20 (struct unisig *, struct unisig_vccb *,
87 static int unisig_vc_act21 (struct unisig *, struct unisig_vccb *,
89 static int unisig_vc_act22 (struct unisig *, struct unisig_vccb *,
91 static int unisig_vc_act23 (struct unisig *, struct unisig_vccb *,
93 static int unisig_vc_act24 (struct unisig *, struct unisig_vccb *,
95 static int unisig_vc_act25 (struct unisig *, struct unisig_vccb *,
97 static int unisig_vc_act26 (struct unisig *, struct unisig_vccb *,
99 static int unisig_vc_act27 (struct unisig *, struct unisig_vccb *,
100 struct unisig_msg *);
101 static int unisig_vc_act28 (struct unisig *, struct unisig_vccb *,
102 struct unisig_msg *);
103 static int unisig_vc_act29 (struct unisig *, struct unisig_vccb *,
104 struct unisig_msg *);
105 static int unisig_vc_act30 (struct unisig *, struct unisig_vccb *,
106 struct unisig_msg *);
107 static int unisig_vc_act31 (struct unisig *, struct unisig_vccb *,
108 struct unisig_msg *);
109 static int unisig_vc_clear_call (struct unisig *,
110 struct unisig_vccb *,
118 static int unisig_vc_states[21][17] = {
119 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
120 { 0, 2, 99, 5, 99, 99, 0, 99, 12, 99, 0, 14, 0, 3, 0, 0, 0 },
121 { 29, 4, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
122 { 29, 6, 99, 6, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
123 { 29, 17, 99, 17, 99, 99, 17, 99, 10, 99, 17, 17, 17, 0, 0, 0, 0 },
124 { 8, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17, 0, 0, 0, 0 },
125 { 29, 7, 99, 15, 99, 99, 15, 99, 15, 99, 15, 16, 17, 0, 0, 0, 0 },
126 { 19, 3, 99, 3, 99, 99, 3, 99, 3, 99, 3, 13, 3, 0, 0, 0, 0 },
127 { 21, 21, 99, 21, 99, 99, 21, 99, 21, 99, 21, 21, 21, 0, 0, 0, 0 },
128 { 22, 22, 99, 22, 99, 99, 22, 99, 22, 99, 22, 22, 22, 0, 0, 0, 0 },
129 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 23, 17, 17, 0, 0, 0, 0 },
130 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 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 { 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 },
135 { 99, 25, 99, 25, 99, 99, 9, 99, 25, 99, 25, 25, 25, 25, 31, 25, 25 },
136 { 99, 25, 99, 25, 99, 99, 11, 99, 25, 99, 25, 25, 25, 25, 19, 25, 25 },
137 { 99, 12, 99, 12, 99, 99, 25, 99, 12, 99, 12, 19, 19, 30, 19, 99, 99 },
138 { 99, 12, 99, 12, 99, 99, 12, 99, 12, 99, 12, 3, 3, 3, 24, 26, 26 },
139 { 99, 3, 99, 3, 99, 99, 30, 99, 3, 99, 18, 3, 3, 0, 19, 27, 19 },
140 { 99, 7, 99, 7, 99, 99, 30, 99, 7, 99, 19, 19, 19, 20, 19, 19, 28 }
147 * A given state, action pair selects an action number from the
148 * state table. This vector holds the address of the action routine
149 * for each action number.
151 #define MAX_ACTION 32
152 static int (*unisig_vc_act_vec[MAX_ACTION])
153 (struct unisig *, struct unisig_vccb *,
154 struct unisig_msg *) = {
191 * Process an event on a VC
194 * usp pointer to the UNISIG instance
195 * uvp pointer to the VCCB for the affected VCC
196 * event a numeric indication of which event has occured
197 * msg pointer to a signalling message structure
201 * errno error encountered
205 unisig_vc_state(struct unisig *usp, struct unisig_vccb *uvp, int event,
206 struct unisig_msg *msg)
208 int action, rc, state;
211 * Select an action from the state table
214 state = uvp->uv_sstate;
217 action = unisig_vc_states[event][state];
218 if (action >= MAX_ACTION || action < 0)
219 panic("unisig_vc_state: invalid action");
222 * Perform the requested action
224 ATM_DEBUG4("unisig_vc_state: uvp=%p, state=%d, event=%d, action=%d\n",
225 uvp, state, event, action);
226 rc = unisig_vc_act_vec[action](usp, uvp, msg);
233 * VC state machine action 0
234 * Unexpected action - log an error message
237 * usp pointer to protocol instance block
238 * uvp pointer to the VCCB for the affected connection (may
240 * msg pointer to a UNISIG message structure
244 * errno error encountered
248 unisig_vc_invalid(struct unisig *usp, struct unisig_vccb *uvp,
249 struct unisig_msg *msg)
251 log(LOG_ERR, "unisig_vc_state: unexpected action\n");
257 * VC state machine action 1
258 * Setup handler called
260 * Send SETUP, start timer T303, go to UNI_CALL_INITIATED state
263 * usp pointer to protocol instance block
264 * uvp pointer to the VCCB for the affected connection
265 * msg pointer to a UNISIG message structure
269 * errno error encountered
273 unisig_vc_act01(struct unisig *usp, struct unisig_vccb *uvp,
274 struct unisig_msg *msg)
279 * Send the setup message
281 rc = unisig_send_setup(usp, uvp);
289 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
294 uvp->uv_sstate = UNI_CALL_INITIATED;
299 uvp->uv_tstamp = time_second;
306 * VC state machine action 2
307 * Timeout while waiting for CALL PROCEEDING or CONNECT
309 * If this is the second expiration, clear the call. Otherwise,
310 * retransmit the SETUP message and restart T303.
313 * usp pointer to protocol instance block
314 * uvp pointer to the VCCB for the affected connection
315 * msg pointer to a UNISIG message structure
319 * errno error encountered
323 unisig_vc_act02(struct unisig *usp, struct unisig_vccb *uvp,
324 struct unisig_msg *msg)
332 rc = unisig_clear_vcc(usp, uvp,
333 T_ATM_CAUSE_NO_ROUTE_TO_DESTINATION);
336 unisig_send_setup(usp, uvp);
337 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
345 * VC state machine action 3
347 * Clear the call internally
350 * usp pointer to protocol instance block
351 * uvp pointer to the VCCB for the affected connection
352 * msg pointer to a UNISIG message structure
356 * errno error encountered
360 unisig_vc_act03(struct unisig *usp, struct unisig_vccb *uvp,
361 struct unisig_msg *msg)
368 if ((msg != NULL) && (msg->msg_ie_caus != NULL)) {
369 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
371 cause = T_ATM_ABSENT;
373 cause = T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER;
378 rc = unisig_clear_vcc(usp, uvp, cause);
385 * VC state machine action 4
386 * Received CALL PROCEEDING
388 * Start timer T310, go to UNI_CALL_OUT_PROC
391 * usp pointer to protocol instance block
392 * uvp pointer to the VCCB for the affected connection
393 * msg pointer to a UNISIG message structure
397 * errno error encountered
401 unisig_vc_act04(struct unisig *usp, struct unisig_vccb *uvp,
402 struct unisig_msg *msg)
404 int cause, rc, vpi, vci;
405 struct atm_pif *pip = usp->us_pif;
406 struct ie_generic *iep;
409 * Clear any running timer
411 UNISIG_VC_CANCEL((struct vccb *) uvp);
414 * Make sure a Connection ID is part of the message
416 if (msg->msg_ie_cnid) {
417 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
418 vci = msg->msg_ie_cnid->ie_cnid_vci;
420 iep = (struct ie_generic *)atm_allocate(&unisig_iepool);
423 iep->ie_ident = UNI_IE_CNID;
424 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
425 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
426 cause = UNI_IE_CAUS_MISSING;
427 ATM_DEBUG0("unisig_vc_act04: no CNID in Call Proc\n");
432 * Make sure we can handle the specified VPI and VCI
434 if (vpi > pip->pif_maxvpi || vci > pip->pif_maxvci ||
435 vci < UNI_IE_CNID_MIN_VCI) {
436 cause = UNI_IE_CAUS_BAD_VCC;
437 ATM_DEBUG0("unisig_vc_act04: VPI/VCI invalid\n");
442 * Make sure the specified VPI and VCI are not in use
444 if (unisig_find_vpvc(usp, vpi, vci, VCC_OUT)) {
445 cause = UNI_IE_CAUS_NA_VCC;
446 ATM_DEBUG0("unisig_vc_act04: VPI/VCI in use\n");
453 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T310);
456 * Save the specified VPI and VCI
464 uvp->uv_sstate = UNI_CALL_OUT_PROC;
469 uvp->uv_tstamp = time_second;
475 * Initiate call clearing
477 rc = unisig_vc_clear_call(usp, uvp, msg, cause);
484 * VC state machine action 5
485 * Timeout in UNI_CALL_OUT_PROC
487 * Clear call towards network
490 * usp pointer to protocol instance block
491 * uvp pointer to the VCCB for the affected connection
492 * msg pointer to a UNISIG message structure
496 * errno error encountered
500 unisig_vc_act05(struct unisig *usp, struct unisig_vccb *uvp,
501 struct unisig_msg *msg)
504 struct unisig_msg *rls_msg;
505 struct ie_generic *cause_ie;
508 * Send a RELEASE message
510 rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
513 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
514 if (cause_ie == NULL) {
520 * Fill out the RELEASE message
522 rls_msg->msg_call_ref = uvp->uv_call_ref;
523 rls_msg->msg_type = UNI_MSG_RLSE;
524 rls_msg->msg_type_flag = 0;
525 rls_msg->msg_type_action = 0;
526 rls_msg->msg_ie_caus = cause_ie;
529 * Fill out the cause IE
531 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
532 cause_ie->ie_caus_cause = UNI_IE_CAUS_TIMER;
533 KM_COPY("310", cause_ie->ie_caus_diagnostic, 3);
536 * Send the RELEASE message.
538 rc = unisig_send_msg(usp, rls_msg);
539 unisig_free_msg(rls_msg);
544 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
549 uvp->uv_sstate = UNI_RELEASE_REQUEST;
550 uvp->uv_ustate = VCCU_CLOSED;
555 uvp->uv_tstamp = time_second;
562 * VC state machine action 6
565 * Send CONNECT ACK, go to UNI_ACTIVE state
568 * usp pointer to protocol instance block
569 * uvp pointer to the VCCB for the affected connection
570 * msg pointer to a UNISIG message structure
574 * errno error encountered
578 unisig_vc_act06(struct unisig *usp, struct unisig_vccb *uvp,
579 struct unisig_msg *msg)
581 int cause, rc, vci, vpi;
582 struct atm_pif *pip = usp->us_pif;
583 struct unisig_msg *cack_msg;
584 struct ie_generic *iep;
588 * Clear any running timer
590 UNISIG_VC_CANCEL((struct vccb *) uvp);
592 ap = &uvp->uv_connvc->cvc_attr;
595 * See if a VPI/VCI is specified
597 if (msg->msg_ie_cnid) {
599 * Yes--VPI/VCI must be the first specification or must
600 * match what was specified before
602 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
603 vci = msg->msg_ie_cnid->ie_cnid_vci;
604 if ((uvp->uv_vpi || uvp->uv_vci) &&
605 (vpi != uvp->uv_vpi ||
606 vci != uvp->uv_vci)) {
607 cause = UNI_IE_CAUS_BAD_VCC;
608 ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
613 * Specified VPI/VCI must be within range
615 if (vpi > pip->pif_maxvpi || vci > pip->pif_maxvci ||
616 vci < UNI_IE_CNID_MIN_VCI) {
617 cause = UNI_IE_CAUS_BAD_VCC;
618 ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
625 * No--VCI must have been specified earlier
628 iep = (struct ie_generic *)atm_allocate(
632 iep->ie_ident = UNI_IE_CNID;
633 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
634 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
635 cause = UNI_IE_CAUS_MISSING;
636 ATM_DEBUG0("unisig_vc_act06: CNID missing\n");
642 * Handle AAL parameters negotiation
644 if (msg->msg_ie_aalp) {
645 struct ie_generic *aalp = msg->msg_ie_aalp;
648 * AAL parameters must have been sent in SETUP
650 if ((ap->aal.tag != T_ATM_PRESENT) ||
651 (ap->aal.type != aalp->ie_aalp_aal_type)) {
652 cause = UNI_IE_CAUS_IECONTENT;
656 switch (aalp->ie_aalp_aal_type) {
658 case UNI_IE_AALP_AT_AAL3:
660 * Maximum SDU size negotiation
662 if (aalp->ie_aalp_4_fwd_max_sdu == T_ATM_ABSENT)
664 if ((ap->aal.v.aal4.forward_max_SDU_size <
665 aalp->ie_aalp_4_fwd_max_sdu) ||
666 (ap->aal.v.aal4.backward_max_SDU_size <
667 aalp->ie_aalp_4_bkwd_max_sdu)) {
668 cause = UNI_IE_CAUS_IECONTENT;
671 ap->aal.v.aal4.forward_max_SDU_size =
672 aalp->ie_aalp_4_fwd_max_sdu;
673 ap->aal.v.aal4.backward_max_SDU_size =
674 aalp->ie_aalp_4_bkwd_max_sdu;
678 case UNI_IE_AALP_AT_AAL5:
680 * Maximum SDU size negotiation
682 if (aalp->ie_aalp_5_fwd_max_sdu == T_ATM_ABSENT)
684 if ((ap->aal.v.aal5.forward_max_SDU_size <
685 aalp->ie_aalp_5_fwd_max_sdu) ||
686 (ap->aal.v.aal5.backward_max_SDU_size <
687 aalp->ie_aalp_5_bkwd_max_sdu)) {
688 cause = UNI_IE_CAUS_IECONTENT;
691 ap->aal.v.aal5.forward_max_SDU_size =
692 aalp->ie_aalp_5_fwd_max_sdu;
693 ap->aal.v.aal5.backward_max_SDU_size =
694 aalp->ie_aalp_5_bkwd_max_sdu;
701 * Get memory for a CONNECT ACK message
703 cack_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
704 if (cack_msg == NULL)
708 * Fill out the CONNECT ACK message
710 cack_msg->msg_call_ref = uvp->uv_call_ref;
711 cack_msg->msg_type = UNI_MSG_CACK;
712 cack_msg->msg_type_flag = 0;
713 cack_msg->msg_type_action = 0;
716 * Send the CONNECT ACK message
718 rc = unisig_send_msg(usp, cack_msg);
719 unisig_free_msg(cack_msg);
724 uvp->uv_sstate = UNI_ACTIVE;
725 uvp->uv_ustate = VCCU_OPEN;
730 uvp->uv_tstamp = time_second;
733 * Notify the user that the connection is now active
735 atm_cm_connected(uvp->uv_connvc);
741 * Initiate call clearing
743 rc = unisig_vc_clear_call(usp, uvp, msg, cause);
750 * VC state machine action 7
751 * Abort routine called or signalling SAAL session reset while in
752 * one of the call setup states
754 * Clear the call, send RELEASE COMPLETE, notify the user.
757 * usp pointer to protocol instance block
758 * uvp pointer to the VCCB for the affected connection
759 * msg pointer to a UNISIG message structure
763 * errno error encountered
767 unisig_vc_act07(struct unisig *usp, struct unisig_vccb *uvp,
768 struct unisig_msg *msg)
773 * Clear any running timer
775 UNISIG_VC_CANCEL((struct vccb *) uvp);
778 * Send a RELEASE COMPLETE message rejecting the connection
780 rc = unisig_send_release_complete(usp, uvp, msg,
784 * Clear the call VCCB
786 uvp->uv_sstate = UNI_FREE;
787 uvp->uv_ustate = VCCU_CLOSED;
792 uvp->uv_tstamp = time_second;
797 if ((msg != NULL) && (msg->msg_ie_caus != NULL))
798 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
801 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
802 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
803 atm_cm_cleared(uvp->uv_connvc);
810 * VC state machine action 8
813 * Check call paramaters, notify user that a call has been received,
814 * set UNI_CALL_PRESENT state
817 * usp pointer to protocol instance block
818 * uvp pointer to the VCCB for the affected connection
819 * msg pointer to a UNISIG message structure
823 * errno error encountered
827 unisig_vc_act08(struct unisig *usp, struct unisig_vccb *uvp,
828 struct unisig_msg *msg)
830 int cause = 0, rc, vpi, vci;
831 struct atm_pif *pip = usp->us_pif;
836 ATM_DEBUG3("unisig_vc_act08: usp=%p, uvp=%p, msg=%p\n",
840 * Make sure that the called address is the right format
842 if (msg->msg_ie_cdad->ie_cdad_plan != UNI_IE_CDAD_PLAN_NSAP) {
843 cause = UNI_IE_CAUS_IECONTENT;
844 ATM_DEBUG0("unisig_vc_act08: bad address format\n");
849 * Make sure that the called address is ours
851 nap = (Atm_addr_nsap *) msg->msg_ie_cdad->ie_cdad_addr.address;
852 if (bcmp(usp->us_addr.address, nap, /* XXX */
853 sizeof(Atm_addr_nsap)-1)) {
854 cause = UNI_IE_CAUS_IECONTENT;
855 ATM_DEBUG0("unisig_vc_act08: address not mine\n");
860 * Find the right NIF for the given selector byte
863 while (nip && nip->nif_sel != nap->aan_sel) {
864 nip = nip->nif_pnext;
867 cause = UNI_IE_CAUS_IECONTENT;
868 ATM_DEBUG0("unisig_vc_act08: bad selector byte\n");
873 * See if we recognize the specified AAL
875 if (msg->msg_ie_aalp->ie_aalp_aal_type != UNI_IE_AALP_AT_AAL3 &&
876 msg->msg_ie_aalp->ie_aalp_aal_type !=
877 UNI_IE_AALP_AT_AAL5) {
878 cause = UNI_IE_CAUS_UAAL;
879 ATM_DEBUG0("unisig_vc_act08: bad AAL\n");
884 * Should verify that we can handle requested
889 * Make sure the specified VPI/VCI is valid
891 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
892 vci = msg->msg_ie_cnid->ie_cnid_vci;
893 if (vpi > pip->pif_maxvpi ||
894 vci > pip->pif_maxvci ||
895 vci < UNI_IE_CNID_MIN_VCI) {
896 cause = UNI_IE_CAUS_BAD_VCC;
897 ATM_DEBUG0("unisig_vc_act08: VPI/VCI invalid\n");
902 * Make sure the specified VPI/VCI isn't in use already
904 if (unisig_find_vpvc(usp, vpi, vci, VCC_IN)) {
905 cause = UNI_IE_CAUS_NA_VCC;
906 ATM_DEBUG0("unisig_vc_act08: VPI/VCI in use\n");
911 * Make sure it's a point-to-point connection
913 if (msg->msg_ie_bbcp->ie_bbcp_conn_config !=
915 cause = UNI_IE_CAUS_NI_BC;
916 ATM_DEBUG0("unisig_vc_act08: conn not pt-pt\n");
921 * Fill in the VCCB fields that we can at this point
923 uvp->uv_type = VCC_SVC | VCC_IN | VCC_OUT;
924 uvp->uv_proto = pip->pif_sigmgr->sm_proto;
925 uvp->uv_sstate = UNI_CALL_PRESENT;
926 uvp->uv_ustate = VCCU_POPEN;
929 uvp->uv_vpi = msg->msg_ie_cnid->ie_cnid_vpci;
930 uvp->uv_vci = msg->msg_ie_cnid->ie_cnid_vci;
931 uvp->uv_tstamp = time_second;
934 * Copy the connection attributes from the SETUP message
935 * to an attribute block
937 KM_ZERO(&attr, sizeof(attr));
939 attr.aal.tag = T_ATM_ABSENT;
940 attr.traffic.tag = T_ATM_ABSENT;
941 attr.bearer.tag = T_ATM_ABSENT;
942 attr.bhli.tag = T_ATM_ABSENT;
943 attr.blli.tag_l2 = T_ATM_ABSENT;
944 attr.blli.tag_l3 = T_ATM_ABSENT;
945 attr.llc.tag = T_ATM_ABSENT;
946 attr.called.tag = T_ATM_ABSENT;
947 attr.calling.tag = T_ATM_ABSENT;
948 attr.qos.tag = T_ATM_ABSENT;
949 attr.transit.tag = T_ATM_ABSENT;
950 attr.cause.tag = T_ATM_ABSENT;
951 unisig_save_attrs(usp, msg, &attr);
954 * Notify the connection manager of the new VCC
956 ATM_DEBUG0("unisig_vc_act08: notifying user of connection\n");
957 rc = atm_cm_incoming((struct vccb *)uvp, &attr);
962 * Wait for the connection recipient to issue an accept
968 ATM_DEBUG1("unisig_vc_act08: reject with cause=%d\n", cause);
971 * Clear the VCCB state
973 uvp->uv_sstate = UNI_NULL;
978 uvp->uv_tstamp = time_second;
981 * Some problem was detected with the request. Send a Q.2931
982 * message rejecting the connection.
984 rc = unisig_send_release_complete(usp, uvp, msg, cause);
991 * VC state machine action 9
992 * Accept routine called by user
994 * Send CONNECT, start timer T313, go to UNI_CONNECT_REQUEST state
997 * usp pointer to protocol instance block
998 * uvp pointer to the VCCB for the affected connection
999 * msg pointer to a UNISIG message structure
1003 * errno error encountered
1007 unisig_vc_act09(struct unisig *usp, struct unisig_vccb *uvp,
1008 struct unisig_msg *msg)
1011 struct unisig_msg *conn_msg;
1013 conn_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1014 if (conn_msg == NULL)
1018 * Fill out the response
1020 conn_msg->msg_call_ref = uvp->uv_call_ref;
1021 conn_msg->msg_type = UNI_MSG_CONN;
1022 conn_msg->msg_type_flag = 0;
1023 conn_msg->msg_type_action = 0;
1026 * Send the CONNECT message. If the send fails, the other
1027 * side will eventually time out and close the connection.
1029 rc = unisig_send_msg(usp, conn_msg);
1030 unisig_free_msg(conn_msg);
1038 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T313);
1043 uvp->uv_sstate = UNI_CONNECT_REQUEST;
1048 uvp->uv_tstamp = time_second;
1055 * VC state machine action 10
1056 * Received CONNECT ACK
1058 * Go to UNI_ACTIVE state
1061 * usp pointer to protocol instance block
1062 * uvp pointer to the VCCB for the affected connection
1063 * msg pointer to a UNISIG message structure
1067 * errno error encountered
1071 unisig_vc_act10(struct unisig *usp, struct unisig_vccb *uvp,
1072 struct unisig_msg *msg)
1075 * Clear any running timer
1077 UNISIG_VC_CANCEL((struct vccb *) uvp);
1082 uvp->uv_sstate = UNI_ACTIVE;
1083 uvp->uv_ustate = VCCU_OPEN;
1088 uvp->uv_tstamp = time_second;
1091 * Notify the user that the call is up
1093 atm_cm_connected(uvp->uv_connvc);
1100 * VC state machine action 11
1101 * Reject handler called
1103 * Send RELEASE COMPLETE, clear the call
1106 * usp pointer to protocol instance block
1107 * uvp pointer to the VCCB for the affected connection
1108 * msg pointer to a UNISIG message structure
1112 * errno error encountered
1116 unisig_vc_act11(struct unisig *usp, struct unisig_vccb *uvp,
1117 struct unisig_msg *msg)
1122 * Send generic cause code if one is not already set
1124 if (uvp->uv_connvc->cvc_attr.cause.tag == T_ATM_PRESENT)
1125 cause = T_ATM_ABSENT;
1127 cause = T_ATM_CAUSE_CALL_REJECTED;
1130 * Send a RELEASE COMPLETE message
1132 rc = unisig_send_release_complete(usp, uvp, msg, cause);
1135 * Clear the call VCCB
1137 uvp->uv_sstate = UNI_FREE;
1138 uvp->uv_ustate = VCCU_CLOSED;
1143 uvp->uv_tstamp = time_second;
1150 * VC state machine action 12
1151 * Release or abort routine called
1153 * Send RELEASE, start timer T308, go to UNI_RELEASE_REQUEST state
1156 * usp pointer to protocol instance block
1157 * uvp pointer to the VCCB for the affected connection
1158 * msg pointer to a UNISIG message structure
1162 * errno error encountered
1166 unisig_vc_act12(struct unisig *usp, struct unisig_vccb *uvp,
1167 struct unisig_msg *msg)
1172 * Clear any running timer
1174 UNISIG_VC_CANCEL((struct vccb *) uvp);
1177 * Send the RELEASE message
1179 rc = unisig_vc_clear_call(usp, uvp, NULL, T_ATM_ABSENT);
1186 * VC state machine action 13
1187 * RELEASE COMPLETE received
1192 * usp pointer to protocol instance block
1193 * uvp pointer to the VCCB for the affected connection
1194 * msg pointer to a UNISIG message structure
1198 * errno error encountered
1202 unisig_vc_act13(struct unisig *usp, struct unisig_vccb *uvp,
1203 struct unisig_msg *msg)
1206 * Clear any running timer
1208 UNISIG_VC_CANCEL((struct vccb *) uvp);
1213 uvp->uv_sstate = UNI_FREE;
1214 if (uvp->uv_ustate != VCCU_ABORT)
1215 uvp->uv_ustate = VCCU_CLOSED;
1220 uvp->uv_tstamp = time_second;
1223 * Notify the user that the call is now closed
1225 if (msg->msg_ie_caus != NULL)
1226 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1228 atm_cm_cleared(uvp->uv_connvc);
1235 * VC state machine action 14
1236 * Timer expired while waiting for RELEASE COMPLETE
1238 * If this is the second expiration, just clear the call. Otherwise,
1239 * retransmit the RELEASE message and restart timer T308.
1242 * usp pointer to protocol instance block
1243 * uvp pointer to the VCCB for the affected connection
1244 * msg pointer to a UNISIG message structure
1248 * errno error encountered
1252 unisig_vc_act14(struct unisig *usp, struct unisig_vccb *uvp,
1253 struct unisig_msg *msg)
1258 * Check the retry count
1260 if (uvp->uv_retry) {
1262 * Clear the connection
1264 rc = unisig_clear_vcc(usp, uvp,
1265 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1268 * Increment the retry count
1273 * Resend the RELEASE message
1275 rc = unisig_send_release(usp, uvp, NULL, T_ATM_ABSENT);
1280 * Restart timer T308
1282 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
1290 * VC state machine action 15
1291 * RELEASE received in UNI_ACTIVE state
1293 * Send RELEASE COMPLETE, go to UNI_FREE, notify the user
1296 * usp pointer to protocol instance block
1297 * uvp pointer to the VCCB for the affected connection
1298 * msg pointer to a UNISIG message structure
1302 * errno error encountered
1306 unisig_vc_act15(struct unisig *usp, struct unisig_vccb *uvp,
1307 struct unisig_msg *msg)
1310 struct ie_generic *iep;
1313 * Clear any running timer
1315 UNISIG_VC_CANCEL((struct vccb *) uvp);
1318 * If there was no Cause IE, flag an error
1320 if (!msg->msg_ie_caus) {
1321 cause = UNI_IE_CAUS_MISSING;
1322 for (iep=msg->msg_ie_err; iep; iep=iep->ie_next) {
1323 if (iep->ie_ident == UNI_IE_CAUS &&
1324 iep->ie_err_cause ==
1325 UNI_IE_CAUS_IECONTENT) {
1326 cause = UNI_IE_CAUS_IECONTENT;
1329 if (cause == UNI_IE_CAUS_MISSING) {
1330 iep = (struct ie_generic *)atm_allocate(
1334 iep->ie_ident = UNI_IE_CNID;
1335 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
1336 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
1339 cause = UNI_IE_CAUS_NORM_UNSP;
1343 * Send a RELEASE COMPLETE message
1345 rc = unisig_send_release_complete(usp, uvp, msg, cause);
1350 uvp->uv_sstate = UNI_FREE;
1351 uvp->uv_ustate = VCCU_CLOSED;
1356 uvp->uv_tstamp = time_second;
1359 * Notify the user that the call is cleared
1361 if (msg->msg_ie_caus != NULL)
1362 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1365 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1366 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
1367 atm_cm_cleared(uvp->uv_connvc);
1374 * VC state machine action 16
1375 * RELEASE received in UNI_RELEASE_REQUEST state
1380 * usp pointer to protocol instance block
1381 * uvp pointer to the VCCB for the affected connection
1382 * msg pointer to a UNISIG message structure
1386 * errno error encountered
1390 unisig_vc_act16(struct unisig *usp, struct unisig_vccb *uvp,
1391 struct unisig_msg *msg)
1396 * Clear any running timer
1398 UNISIG_VC_CANCEL((struct vccb *) uvp);
1403 rc = unisig_clear_vcc(usp, uvp, T_ATM_ABSENT);
1410 * VC state machine action 17
1413 * Send a STATUS message with cause 101, "message not compatible with
1417 * usp pointer to protocol instance block
1418 * uvp pointer to the VCCB for the affected connection
1419 * msg pointer to a UNISIG message structure
1423 * errno error encountered
1427 unisig_vc_act17(struct unisig *usp, struct unisig_vccb *uvp,
1428 struct unisig_msg *msg)
1432 ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1436 * Clear any running timer
1438 UNISIG_VC_CANCEL((struct vccb *) uvp);
1441 * Send a STATUS message
1443 rc = unisig_send_status(usp, uvp, msg, UNI_IE_CAUS_STATE);
1445 return(rc ? rc : EINVAL);
1450 * VC state machine action 18
1451 * Signalling AAL connection has been lost
1453 * Start timer T309. If the timer expires before the SAAL connection
1454 * comes back, the VCC will be cleared.
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
1463 * errno error encountered
1467 unisig_vc_act18(struct unisig *usp, struct unisig_vccb *uvp,
1468 struct unisig_msg *msg)
1471 * Clear any running timer
1473 UNISIG_VC_CANCEL((struct vccb *) uvp);
1478 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T309);
1483 uvp->uv_sstate = UNI_SSCF_RECOV;
1490 * VC state machine action 19
1494 * usp pointer to protocol instance block
1495 * uvp pointer to the VCCB for the affected connection
1496 * msg pointer to a UNISIG message structure
1500 * errno error encountered
1504 unisig_vc_act19(struct unisig *usp, struct unisig_vccb *uvp,
1505 struct unisig_msg *msg)
1512 * VC state machine action 20
1513 * SSCF establish indication in UNI_SSCF_RECOV state -- signalling
1514 * AAL has come up after an outage
1516 * Send STATUS ENQ to make sure we're in compatible state with other end
1519 * usp pointer to protocol instance block
1520 * uvp pointer to the VCCB for the affected connection
1521 * msg pointer to a UNISIG message structure
1525 * errno error encountered
1529 unisig_vc_act20(struct unisig *usp, struct unisig_vccb *uvp,
1530 struct unisig_msg *msg)
1533 struct unisig_msg *stat_msg;
1536 * Clear any running timer
1538 UNISIG_VC_CANCEL((struct vccb *) uvp);
1541 * Get memory for a STATUS ENQUIRY message
1543 stat_msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
1544 if (stat_msg == NULL)
1548 * Fill out the message
1550 stat_msg->msg_call_ref = uvp->uv_call_ref;
1551 stat_msg->msg_type = UNI_MSG_SENQ;
1552 stat_msg->msg_type_flag = 0;
1553 stat_msg->msg_type_action = 0;
1556 * Send the STATUS ENQUIRY message
1558 rc = unisig_send_msg(usp, stat_msg);
1559 unisig_free_msg(stat_msg);
1562 * Return to active state
1564 uvp->uv_sstate = UNI_ACTIVE;
1571 * VC state machine action 21
1575 * usp pointer to protocol instance block
1576 * uvp pointer to the VCCB for the affected connection (may
1578 * msg pointer to a UNISIG message structure
1582 * errno error encountered
1586 unisig_vc_act21(struct unisig *usp, struct unisig_vccb *uvp,
1587 struct unisig_msg *msg)
1592 * Ignore a STATUS message with the global call reference
1594 if (GLOBAL_CREF(msg->msg_call_ref)) {
1599 * If the network thinks we're in NULL state, clear the VCC
1601 if (msg->msg_ie_clst->ie_clst_state == UNI_NULL) {
1603 unisig_clear_vcc(usp, uvp,
1604 T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER);
1610 * If we are in NULL state, send a RELEASE COMPLETE
1612 if (!uvp || (uvp->uv_sstate == UNI_FREE) ||
1613 (uvp->uv_sstate == UNI_NULL)) {
1614 rc = unisig_send_release_complete(usp,
1615 uvp, msg, UNI_IE_CAUS_STATE);
1620 * If the reported state doesn't match our state, close the VCC
1621 * unless we're in UNI_RELEASE_REQUEST or UNI_RELEASE_IND
1623 if (msg->msg_ie_clst->ie_clst_state != uvp->uv_sstate) {
1624 if (uvp->uv_sstate == UNI_RELEASE_REQUEST ||
1625 uvp->uv_sstate == UNI_RELEASE_IND) {
1628 rc = unisig_clear_vcc(usp, uvp,
1629 T_ATM_CAUSE_MESSAGE_INCOMPATIBLE_WITH_CALL_STATE);
1633 * States match, check for an error on one of our messages
1635 cause = msg->msg_ie_caus->ie_caus_cause;
1636 if (cause == UNI_IE_CAUS_MISSING ||
1637 cause == UNI_IE_CAUS_MTEXIST ||
1638 cause == UNI_IE_CAUS_IEEXIST ||
1639 cause == UNI_IE_CAUS_IECONTENT ||
1640 cause == UNI_IE_CAUS_STATE) {
1641 ATM_DEBUG2("unisig_vc_act21: error %d on message 0x%x\n",
1643 msg->msg_ie_caus->ie_caus_diagnostic[0]);
1645 unisig_clear_vcc(usp, uvp, cause);
1654 * VC state machine action 22
1655 * Received STATUS ENQ
1657 * Send STATUS with cause 30 "response to STATUS ENQUIRY" and
1661 * usp pointer to protocol instance block
1662 * uvp pointer to the VCCB for the affected connection (may
1664 * msg pointer to a UNISIG message structure
1668 * errno error encountered
1672 unisig_vc_act22(struct unisig *usp, struct unisig_vccb *uvp,
1673 struct unisig_msg *msg)
1676 struct unisig_msg *status;
1677 struct ie_generic *callst_ie, *cause_ie;
1679 ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1683 * Get memory for a STATUS message
1685 status = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1688 callst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1689 if (callst_ie == NULL) {
1693 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1694 if (cause_ie == NULL) {
1696 atm_free(callst_ie);
1701 * Fill out the response
1704 status->msg_call_ref = uvp->uv_call_ref;
1706 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1707 status->msg_call_ref = msg->msg_call_ref &
1708 UNI_MSG_CALL_REF_MASK;
1710 status->msg_call_ref = msg->msg_call_ref |
1711 UNI_MSG_CALL_REF_RMT;
1713 status->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
1715 status->msg_type = UNI_MSG_STAT;
1716 status->msg_type_flag = 0;
1717 status->msg_type_action = 0;
1718 status->msg_ie_clst = callst_ie;
1719 status->msg_ie_caus = cause_ie;
1722 * Fill out the call state IE
1724 callst_ie->ie_ident = UNI_IE_CLST;
1725 callst_ie->ie_coding = 0;
1726 callst_ie->ie_flag = 0;
1727 callst_ie->ie_action = 0;
1729 switch(uvp->uv_sstate) {
1731 callst_ie->ie_clst_state = UNI_NULL;
1734 callst_ie->ie_clst_state = uvp->uv_sstate;
1737 callst_ie->ie_clst_state = UNI_NULL;
1741 * Fill out the cause IE
1743 cause_ie->ie_ident = UNI_IE_CAUS;
1744 cause_ie->ie_coding = 0;
1745 cause_ie->ie_flag = 0;
1746 cause_ie->ie_action = 0;
1747 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
1748 cause_ie->ie_caus_cause = UNI_IE_CAUS_SENQ;
1751 * Send the STATUS message
1753 rc = unisig_send_msg(usp, status);
1754 unisig_free_msg(status);
1760 * VC state machine action 23
1761 * Received ADD PARTY
1763 * We don't support multipoint connections, so send an ADD PARTY REJECT
1766 * usp pointer to protocol instance block
1767 * uvp pointer to the VCCB for the affected connection
1768 * msg pointer to a UNISIG message structure
1772 * errno error encountered
1776 unisig_vc_act23(struct unisig *usp, struct unisig_vccb *uvp,
1777 struct unisig_msg *msg)
1780 struct unisig_msg *apr_msg;
1783 * Get memory for the ADD PARTY REJECT message
1785 apr_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1786 if (apr_msg == NULL)
1790 * Fill out the message
1792 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1793 apr_msg->msg_call_ref = msg->msg_call_ref &
1794 UNI_MSG_CALL_REF_MASK;
1796 apr_msg->msg_call_ref = msg->msg_call_ref |
1797 UNI_MSG_CALL_REF_RMT;
1798 apr_msg->msg_type = UNI_MSG_ADPR;
1799 apr_msg->msg_type_flag = 0;
1800 apr_msg->msg_type_action = 0;
1803 * Use the endpoint reference IE from the received message
1805 apr_msg->msg_ie_eprf = msg->msg_ie_eprf;
1808 * Send the ADD PARTY REJECT message
1810 rc = unisig_send_msg(usp, apr_msg);
1811 apr_msg->msg_ie_eprf = NULL;
1812 unisig_free_msg(apr_msg);
1819 * VC state machine action 24
1825 * usp pointer to protocol instance block
1826 * uvp pointer to the VCCB for the affected connection
1827 * msg pointer to a UNISIG message structure
1831 * errno error encountered
1835 unisig_vc_act24(struct unisig *usp, struct unisig_vccb *uvp,
1836 struct unisig_msg *msg)
1843 * VC state machine action 25
1849 * usp pointer to protocol instance block
1850 * uvp pointer to the VCCB for the affected connection
1851 * msg pointer to a UNISIG message structure
1855 * errno error encountered
1859 unisig_vc_act25(struct unisig *usp, struct unisig_vccb *uvp,
1860 struct unisig_msg *msg)
1867 * VC state machine action 26
1870 * The abort handler was called to abort a PVC. Clear the VCCB and
1874 * usp pointer to protocol instance block
1875 * uvp pointer to the VCCB for the affected connection
1876 * msg pointer to a UNISIG message structure
1880 * errno error encountered
1884 unisig_vc_act26(struct unisig *usp, struct unisig_vccb *uvp,
1885 struct unisig_msg *msg)
1890 * Clear any running timer
1892 UNISIG_VC_CANCEL((struct vccb *) uvp);
1897 rc = unisig_close_vcc(usp, uvp);
1904 if (uvp->uv_connvc->cvc_attr.cause.tag != T_ATM_PRESENT)
1905 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1906 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1908 atm_cm_cleared(uvp->uv_connvc);
1915 * VC state machine action 27
1916 * Signalling AAL failure
1918 * Change PVC state to UNI_PVC_ACT_DOWN.
1921 * usp pointer to protocol instance block
1922 * uvp pointer to the VCCB for the affected connection
1923 * msg pointer to a UNISIG message structure
1927 * errno error encountered
1931 unisig_vc_act27(struct unisig *usp, struct unisig_vccb *uvp,
1932 struct unisig_msg *msg)
1937 uvp->uv_sstate = UNI_PVC_ACT_DOWN;
1942 uvp->uv_tstamp = time_second;
1949 * VC state machine action 28
1950 * Signalling AAL established
1952 * Set PVC state to UNI_PVC_ACTIVE.
1955 * usp pointer to protocol instance block
1956 * uvp pointer to the VCCB for the affected connection
1957 * msg pointer to a UNISIG message structure
1961 * errno error encountered
1965 unisig_vc_act28(struct unisig *usp, struct unisig_vccb *uvp,
1966 struct unisig_msg *msg)
1971 uvp->uv_sstate = UNI_PVC_ACTIVE;
1976 uvp->uv_tstamp = time_second;
1983 * VC state machine action 29
1986 * Send a RELEASE COMPLETE message with cause 81, "invalid call
1990 * usp pointer to protocol instance block
1991 * uvp pointer to the VCCB for the affected connection (may
1993 * msg pointer to a UNISIG message structure
1997 * errno error encountered
2001 unisig_vc_act29(struct unisig *usp, struct unisig_vccb *uvp,
2002 struct unisig_msg *msg)
2007 * Send a RELEASE COMPLETE message
2009 rc = unisig_send_release_complete(usp, uvp, msg,
2017 * VC state machine action 30
2018 * Release routine called while SSCF session down, or SSCF session
2019 * reset or lost while in UNI_CALL_PRESENT
2021 * Go to UNI_FREE state
2024 * usp pointer to protocol instance block
2025 * uvp pointer to the VCCB for the affected connection
2026 * msg pointer to a UNISIG message structure
2030 * errno error encountered
2034 unisig_vc_act30(struct unisig *usp, struct unisig_vccb *uvp,
2035 struct unisig_msg *msg)
2038 * Clear any running timer
2040 UNISIG_VC_CANCEL((struct vccb *) uvp);
2043 * Clear the call state
2045 uvp->uv_sstate = UNI_FREE;
2046 uvp->uv_ustate = VCCU_CLOSED;
2051 uvp->uv_tstamp = time_second;
2058 * VC state machine action 31
2059 * Accept handler called in UNI_FREE state.
2061 * The call was in UNI_CALL_PRESENT state when it was closed because
2062 * of an SSCF failure. Return an error indication. The accept
2063 * handler will free the VCCB and return the proper code to the
2067 * usp pointer to protocol instance block
2068 * uvp pointer to the VCCB for the affected connection
2069 * msg pointer to a UNISIG message structure
2073 * errno error encountered
2077 unisig_vc_act31(struct unisig *usp, struct unisig_vccb *uvp,
2078 struct unisig_msg *msg)
2085 * Initiate clearing a call by sending a RELEASE message.
2088 * usp pointer to protocol instance block
2089 * uvp pointer to the VCCB for the affected connection
2090 * msg pointer to UNI signalling message that the RELEASE
2091 * responds to (may be NULL)
2092 * cause the reason for clearing the call; a value of
2093 * T_ATM_ABSENT indicates that the cause code is
2094 * in the VCC's ATM attributes block
2098 * errno error encountered
2102 unisig_vc_clear_call(struct unisig *usp, struct unisig_vccb *uvp,
2103 struct unisig_msg *msg, int cause)
2108 * Clear the retry count
2113 * Make sure the ATM attributes block has a valid cause code,
2116 if (cause == T_ATM_ABSENT &&
2117 uvp->uv_connvc->cvc_attr.cause.tag !=
2119 uvp->uv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
2120 uvp->uv_connvc->cvc_attr.cause.v.coding_standard =
2122 uvp->uv_connvc->cvc_attr.cause.v.location =
2124 uvp->uv_connvc->cvc_attr.cause.v.cause_value =
2125 usp->us_proto == ATM_SIG_UNI30 ?
2126 T_ATM_CAUSE_UNSPECIFIED_NORMAL :
2127 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
2131 * Send a RELEASE message
2133 rc = unisig_send_release(usp, uvp, msg, cause);
2140 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
2143 * Set the VCCB state
2145 uvp->uv_sstate = UNI_RELEASE_REQUEST;
2146 if (uvp->uv_ustate != VCCU_ABORT)
2147 uvp->uv_ustate = VCCU_CLOSED;
2152 uvp->uv_tstamp = time_second;