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_msg.c,v 1.6 2000/01/17 20:49:56 mks Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * Message handling module
38 #include <netatm/kern_include.h>
40 #include <netatm/uni/unisig_var.h>
41 #include <netatm/uni/unisig_msg.h>
42 #include <netatm/uni/unisig_mbuf.h>
43 #include <netatm/uni/unisig_print.h>
46 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/unisig_msg.c,v 1.6 2000/01/17 20:49:56 mks Exp $");
53 static void unisig_rcv_restart __P((struct unisig *, struct unisig_msg *));
54 static void unisig_rcv_setup __P((struct unisig *, struct unisig_msg *));
61 static int unisig_print_msg = 0;
66 * Set a Cause IE based on information in an ATM attribute block
69 * iep pointer to a cause IE
70 * aap pointer to attribute block
74 * errno error encountered
78 unisig_cause_from_attr(iep, aap)
79 struct ie_generic *iep;
83 * Copy cause info from attribute block to IE
85 iep->ie_ident = UNI_IE_CAUS;
86 iep->ie_coding = aap->cause.v.coding_standard;
87 iep->ie_caus_loc = aap->cause.v.location;
88 iep->ie_caus_cause = aap->cause.v.cause_value;
93 * Set a Cause IE based on information in a UNI signalling message
96 * iep pointer to a cause IE
97 * msg pointer to message
98 * cause cause code for the error
102 * errno error encountered
106 unisig_cause_from_msg(iep, msg, cause)
107 struct ie_generic *iep;
108 struct unisig_msg *msg;
111 struct ie_generic *ie1;
115 * Fill out the cause IE fixed fields
117 iep->ie_ident = UNI_IE_CAUS;
118 iep->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
119 iep->ie_caus_cause = cause;
122 * Set diagnostics if indicated
125 case UNI_IE_CAUS_IECONTENT:
126 iep->ie_caus_diag_len = 0;
127 for (i = 0, ie1 = msg->msg_ie_err;
128 ie1 && i < UNI_IE_CAUS_MAX_ID;
129 ie1 = ie1->ie_next) {
130 if (ie1->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
131 iep->ie_caus_diagnostic[i] =
133 iep->ie_caus_diag_len++;
138 case UNI_IE_CAUS_REJECT:
139 iep->ie_caus_diag_len = 2;
140 iep->ie_caus_diagnostic[0] = UNI_IE_EXT_BIT +
141 (UNI_IE_CAUS_RR_USER << UNI_IE_CAUS_RR_SHIFT) +
142 UNI_IE_CAUS_RC_TRANS;
143 iep->ie_caus_diagnostic[1] = 0;
145 case UNI_IE_CAUS_MISSING:
146 iep->ie_caus_diag_len = 0;
147 for (i = 0, ie1 = msg->msg_ie_err;
148 ie1 && i < UNI_IE_CAUS_MAX_ID;
149 ie1 = ie1->ie_next) {
150 if (ie1->ie_err_cause == UNI_IE_CAUS_MISSING) {
151 iep->ie_caus_diagnostic[i] =
153 iep->ie_caus_diag_len++;
162 * Send a UNISIG signalling message
164 * Called to send a Q.2931 message. This routine encodes the message
165 * and hands it to SSCF for transmission.
168 * usp pointer to UNISIG protocol instance block
169 * msg pointer to message
173 * errno error encountered
177 unisig_send_msg(usp, msg)
179 struct unisig_msg *msg;
184 ATM_DEBUG2("unisig_send_msg: msg=%p, type=%d\n", msg,
188 * Make sure the network is up
190 if (usp->us_state != UNISIG_ACTIVE)
195 * Print the message we're sending.
197 if (unisig_print_msg)
198 usp_print_msg(msg, UNISIG_MSG_OUT);
202 * Convert message to network order
204 err = usf_init(&usf, usp, (KBuffer *) 0, USF_ENCODE,
209 err = usf_enc_msg(&usf, msg);
211 ATM_DEBUG1("unisig_send_msg: encode failed with %d\n",
213 KB_FREEALL(usf.usf_m_base);
219 * Print the converted message
221 if (unisig_print_msg > 1)
222 unisig_print_mbuf(usf.usf_m_base);
228 err = atm_cm_saal_data(usp->us_conn, usf.usf_m_base);
230 KB_FREEALL(usf.usf_m_base);
237 * Send a SETUP request
239 * Build and send a Q.2931 SETUP message.
242 * usp pointer to UNISIG protocol instance block
243 * uvp pointer to VCCB for which the request is being sent
250 unisig_send_setup(usp, uvp)
252 struct unisig_vccb *uvp;
255 struct unisig_msg *setup;
256 Atm_attributes *ap = &uvp->uv_connvc->cvc_attr;
258 ATM_DEBUG1("unisig_send_setup: uvp=%p\n", uvp);
261 * Make sure required connection attriutes are set
263 if (ap->aal.tag != T_ATM_PRESENT ||
264 ap->traffic.tag != T_ATM_PRESENT ||
265 ap->bearer.tag != T_ATM_PRESENT ||
266 ap->called.tag != T_ATM_PRESENT ||
267 ap->qos.tag != T_ATM_PRESENT) {
274 * Get memory for a SETUP message
276 setup = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
283 * Fill in the SETUP message
285 if (!uvp->uv_call_ref)
286 uvp->uv_call_ref = unisig_alloc_call_ref(usp);
287 setup->msg_call_ref = uvp->uv_call_ref;
288 setup->msg_type = UNI_MSG_SETU;
291 * Set IEs from connection attributes
293 err = unisig_set_attrs(usp, setup, ap);
298 * Attach a Calling Party Number IE if the user didn't
299 * specify one in the attribute block
301 if (ap->calling.tag != T_ATM_PRESENT) {
302 setup->msg_ie_cgad = (struct ie_generic *)
303 atm_allocate(&unisig_iepool);
304 if (setup->msg_ie_cgad == NULL) {
308 setup->msg_ie_cgad->ie_ident = UNI_IE_CGAD;
309 ATM_ADDR_COPY(&usp->us_addr,
310 &setup->msg_ie_cgad->ie_cgad_addr);
311 ATM_ADDR_SEL_COPY(&usp->us_addr,
312 uvp->uv_nif ? uvp->uv_nif->nif_sel : 0,
313 &setup->msg_ie_cgad->ie_cgad_addr);
317 * Send the SETUP message
319 err = unisig_send_msg(usp, setup);
323 unisig_free_msg(setup);
330 * Send a RELEASE message
333 * usp pointer to UNISIG protocol instance block
334 * uvp pointer to VCCB for which the RELEASE is being sent
335 * msg pointer to UNI signalling message that the RELEASE
336 * responds to (may be NULL)
337 * cause the reason for the RELEASE; a value of
338 * T_ATM_ABSENT indicates that the cause code is
339 * in the VCC's ATM attributes block
346 unisig_send_release(usp, uvp, msg, cause)
348 struct unisig_vccb *uvp;
349 struct unisig_msg *msg;
353 struct unisig_msg *rls_msg;
354 struct ie_generic *cause_ie;
356 ATM_DEBUG2("unisig_send_release: usp=%p, uvp=%p\n",
360 * Get memory for a RELEASE message
362 rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
363 if (rls_msg == NULL) {
366 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
367 if (cause_ie == NULL) {
373 * Fill in the RELEASE message
375 rls_msg->msg_call_ref = uvp->uv_call_ref;
376 rls_msg->msg_type = UNI_MSG_RLSE;
377 rls_msg->msg_type_flag = 0;
378 rls_msg->msg_type_action = 0;
379 rls_msg->msg_ie_caus = cause_ie;
382 * Fill out the cause IE
384 cause_ie->ie_ident = UNI_IE_CAUS;
385 if (cause == T_ATM_ABSENT) {
386 unisig_cause_from_attr(cause_ie,
387 &uvp->uv_connvc->cvc_attr);
389 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
390 unisig_cause_from_msg(cause_ie, msg, cause);
396 err = unisig_send_msg(usp, rls_msg);
397 unisig_free_msg(rls_msg);
404 * Send a RELEASE COMPLETE message
407 * usp pointer to UNISIG protocol instance block
408 * uvp pointer to VCCB for which the RELEASE is being sent.
409 * NULL indicates that a VCCB wasn't found for a call
411 * msg pointer to the message which triggered the send
412 * cause the cause code for the message; a value of
413 * T_ATM_ABSENT indicates that the cause code is
414 * in the VCC's ATM attributes block
418 * errno error encountered
422 unisig_send_release_complete(usp, uvp, msg, cause)
424 struct unisig_vccb *uvp;
425 struct unisig_msg *msg;
429 struct unisig_msg *rls_cmp;
430 struct ie_generic *cause_ie;
432 ATM_DEBUG4("unisig_send_release_complete usp=%p, uvp=%p, msg=%p, cause=%d\n",
433 usp, uvp, msg, cause);
436 * Get memory for a RELEASE COMPLETE message
438 rls_cmp = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
439 if (rls_cmp == NULL) {
442 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
443 if (cause_ie == NULL) {
449 * Fill in the RELEASE COMPLETE message
452 rls_cmp->msg_call_ref = uvp->uv_call_ref;
454 rls_cmp->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
456 rls_cmp->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
458 rls_cmp->msg_type = UNI_MSG_RLSC;
459 rls_cmp->msg_type_flag = 0;
460 rls_cmp->msg_type_action = 0;
461 rls_cmp->msg_ie_caus = cause_ie;
464 * Fill out the cause IE
466 cause_ie->ie_ident = UNI_IE_CAUS;
467 if (cause == T_ATM_ABSENT) {
468 unisig_cause_from_attr(cause_ie,
469 &uvp->uv_connvc->cvc_attr);
471 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
472 unisig_cause_from_msg(cause_ie, msg, cause);
476 * Send the RELEASE COMPLETE
478 err = unisig_send_msg(usp, rls_cmp);
479 unisig_free_msg(rls_cmp);
486 * Send a STATUS message
489 * usp pointer to UNISIG protocol instance block
490 * uvp pointer to VCCB for which the STATUS is being sent.
491 * NULL indicates that a VCCB wasn't found for a call
493 * msg pointer to the message which triggered the send
494 * cause the cause code to include in the message
501 unisig_send_status(usp, uvp, msg, cause)
503 struct unisig_vccb *uvp;
504 struct unisig_msg *msg;
508 struct unisig_msg *stat_msg;
509 struct ie_generic *cause_ie, *clst_ie, *iep;
511 ATM_DEBUG4("unisig_send_status: usp=%p, uvp=%p, msg=%p, cause=%d\n",
512 usp, uvp, msg, cause);
515 * Get memory for a STATUS message
517 stat_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
518 if (stat_msg == NULL) {
521 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
522 if (cause_ie == NULL) {
526 clst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
527 if (clst_ie == NULL) {
534 * Fill in the STATUS message
537 stat_msg->msg_call_ref = uvp->uv_call_ref;
539 stat_msg->msg_call_ref =
540 EXTRACT_CREF(msg->msg_call_ref);
542 stat_msg->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
544 stat_msg->msg_type = UNI_MSG_STAT;
545 stat_msg->msg_type_flag = 0;
546 stat_msg->msg_type_action = 0;
547 stat_msg->msg_ie_clst = clst_ie;
548 stat_msg->msg_ie_caus = cause_ie;
551 * Fill out the call state IE
553 clst_ie->ie_ident = UNI_IE_CLST;
554 clst_ie->ie_coding = 0;
555 clst_ie->ie_flag = 0;
556 clst_ie->ie_action = 0;
558 clst_ie->ie_clst_state = uvp->uv_sstate;
560 clst_ie->ie_clst_state = UNI_NULL;
564 * Fill out the cause IE
566 cause_ie->ie_ident = UNI_IE_CAUS;
567 cause_ie->ie_coding = 0;
568 cause_ie->ie_flag = 0;
569 cause_ie->ie_action = 0;
570 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
571 cause_ie->ie_caus_cause = cause;
573 case UNI_IE_CAUS_MTEXIST:
574 case UNI_IE_CAUS_STATE:
576 cause_ie->ie_caus_diagnostic[0] = msg->msg_type;
579 case UNI_IE_CAUS_MISSING:
580 case UNI_IE_CAUS_IECONTENT:
581 case UNI_IE_CAUS_IEEXIST:
582 for (i=0, iep=msg->msg_ie_err;
583 iep && i<UNI_MSG_IE_CNT;
584 i++, iep = iep->ie_next) {
585 if (iep->ie_err_cause == cause) {
586 cause_ie->ie_caus_diagnostic[i] =
593 * Send the STATUS message
595 err = unisig_send_msg(usp, stat_msg);
596 unisig_free_msg(stat_msg);
603 * Process a RESTART message
606 * usp pointer to UNISIG protocol instance block
607 * msg pointer to the RESTART message
614 unisig_rcv_restart(usp, msg)
616 struct unisig_msg *msg;
618 struct unisig_vccb *uvp, *uvnext;
619 struct unisig_msg *rsta_msg;
622 ATM_DEBUG2("unisig_rcv_restart: usp=%p, msg=%p\n",
626 * Check what class of VCCs we're supposed to restart
628 if (msg->msg_ie_rsti->ie_rsti_class == UNI_IE_RSTI_IND_VC) {
630 * Just restart the indicated VCC
632 if (msg->msg_ie_cnid) {
633 uvp = unisig_find_vpvc(usp,
634 msg->msg_ie_cnid->ie_cnid_vpci,
635 msg->msg_ie_cnid->ie_cnid_vci,
637 if (uvp && uvp->uv_type & VCC_SVC) {
638 (void) unisig_clear_vcc(usp, uvp,
639 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
647 for (uvp=Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
649 uvnext = Q_NEXT(uvp, struct unisig_vccb,
651 if (uvp->uv_type & VCC_SVC) {
652 (void) unisig_clear_vcc(usp, uvp,
653 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
660 * Get memory for a RESTART ACKNOWLEDGE message
662 rsta_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
663 if (rsta_msg == NULL) {
668 * Fill out the message
670 rsta_msg->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
671 rsta_msg->msg_type = UNI_MSG_RSTA;
672 rsta_msg->msg_type_flag = 0;
673 rsta_msg->msg_type_action = 0;
674 rsta_msg->msg_ie_rsti = msg->msg_ie_rsti;
675 if (msg->msg_ie_cnid) {
676 rsta_msg->msg_ie_cnid = msg->msg_ie_cnid;
682 (void) unisig_send_msg(usp, rsta_msg);
683 rsta_msg->msg_ie_rsti = NULL;
684 rsta_msg->msg_ie_cnid = NULL;
685 unisig_free_msg(rsta_msg);
692 * Process a SETUP message
695 * usp pointer to UNISIG protocol instance block
696 * msg pointer to the SETUP message
703 unisig_rcv_setup(usp, msg)
705 struct unisig_msg *msg;
707 struct unisig_vccb *uvp = NULL;
708 struct ie_generic *iep;
710 ATM_DEBUG2("unisig_rcv_setup: usp=%p, msg=%p\n", usp, msg);
713 * If we already have a VCC with the call reference,
714 * ignore the SETUP message
716 uvp = unisig_find_conn(usp, EXTRACT_CREF(msg->msg_call_ref));
721 * If the call reference flag is incorrectly set,
722 * ignore the SETUP message
724 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
728 * If there are missing mandatory IEs, send a
729 * RELEASE COMPLETE message and ignore the SETUP
731 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
732 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
733 (void) unisig_send_release_complete(usp,
734 uvp, msg, UNI_IE_CAUS_MISSING);
740 * If there are mandatory IEs with invalid content, send a
741 * RELEASE COMPLETE message and ignore the SETUP
743 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
744 if (iep->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
745 (void) unisig_send_release_complete(usp,
747 UNI_IE_CAUS_IECONTENT);
753 * Get a new VCCB for the connection
755 uvp = (struct unisig_vccb *)atm_allocate(&unisig_vcpool);
761 * Put the VCCB on the UNISIG queue
763 ENQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
766 * Set the state and call reference value
768 uvp->uv_sstate = UNI_NULL;
769 uvp->uv_call_ref = EXTRACT_CREF(msg->msg_call_ref);
772 * Pass the VCCB and message to the VC state machine
774 (void) unisig_vc_state(usp, uvp, UNI_VC_SETUP_MSG, msg);
777 * If the VCCB state is NULL, the open failed and the
778 * VCCB should be released
780 if (uvp->uv_sstate == UNI_NULL) {
781 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem,
791 * Process a UNISIG signalling message
793 * Called when a UNISIG message is received. The message is decoded
794 * and passed to the UNISIG state machine. Unrecognized and
795 * unexpected messages are logged.
798 * usp pointer to UNISIG protocol instance block
799 * m pointer to a buffer chain containing the UNISIG message
806 unisig_rcv_msg(usp, m)
813 struct unisig_msg *msg = 0;
814 struct unisig_vccb *uvp = 0;
815 struct ie_generic *iep;
817 ATM_DEBUG2("unisig_rcv_msg: bfr=%p, len=%d\n", m, KB_LEN(m));
820 unisig_print_mbuf(m);
824 * Get storage for the message
826 msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
833 * Convert the message from network order to internal format
835 err = usf_init(&usf, usp, m, USF_DECODE, 0);
838 panic("unisig_rcv_msg: invalid parameter\n");
839 ATM_DEBUG1("unisig_rcv_msg: decode init failed with %d\n",
844 err = usf_dec_msg(&usf, msg);
846 ATM_DEBUG1("unisig_rcv_msg: decode failed with %d\n",
853 * Debug--print some information about the message
855 if (unisig_print_msg)
856 usp_print_msg(msg, UNISIG_MSG_IN);
860 * Get the call reference value
862 cref = EXTRACT_CREF(msg->msg_call_ref);
865 * Any message with the global call reference value except
866 * RESTART, RESTART ACK, or STATUS is in error
868 if (GLOBAL_CREF(cref) &&
869 msg->msg_type != UNI_MSG_RSTR &&
870 msg->msg_type != UNI_MSG_RSTA &&
871 msg->msg_type != UNI_MSG_STAT) {
873 * Send STATUS message indicating the error
875 err = unisig_send_status(usp, (struct unisig_vccb *) 0,
876 msg, UNI_IE_CAUS_CREF);
881 * Check for missing mandatory IEs. Checks for SETUP,
882 * RELEASE, and RELEASE COMPLETE are handled elsewhere.
884 if (msg->msg_type != UNI_MSG_SETU &&
885 msg->msg_type != UNI_MSG_RLSE &&
886 msg->msg_type != UNI_MSG_RLSC) {
887 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
888 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
889 err = unisig_send_status(usp,
891 UNI_IE_CAUS_MISSING);
898 * Find the VCCB associated with the message
900 uvp = unisig_find_conn(usp, cref);
903 * Process the message based on its type
905 switch(msg->msg_type) {
907 (void) unisig_vc_state(usp, uvp,
908 UNI_VC_CALLP_MSG, msg);
911 (void) unisig_vc_state(usp, uvp,
912 UNI_VC_CONNECT_MSG, msg);
915 (void) unisig_vc_state(usp, uvp,
916 UNI_VC_CNCTACK_MSG, msg);
919 unisig_rcv_setup(usp, msg);
922 (void) unisig_vc_state(usp, uvp,
923 UNI_VC_RELEASE_MSG, msg);
927 * Ignore a RELEASE COMPLETE with an unrecognized
928 * call reference value
931 (void) unisig_vc_state(usp, uvp,
932 UNI_VC_RLSCMP_MSG, msg);
936 unisig_rcv_restart(usp, msg);
941 (void) unisig_vc_state(usp, uvp,
942 UNI_VC_STATUS_MSG, msg);
945 (void) unisig_vc_state(usp, uvp,
946 UNI_VC_STATUSENQ_MSG, msg);
949 (void) unisig_vc_state(usp, uvp,
950 UNI_VC_ADDP_MSG, msg);
953 (void) unisig_vc_state(usp, uvp,
954 UNI_VC_ADDPACK_MSG, msg);
957 (void) unisig_vc_state(usp, uvp,
958 UNI_VC_ADDPREJ_MSG, msg);
961 (void) unisig_vc_state(usp, uvp,
962 UNI_VC_DROP_MSG, msg);
965 (void) unisig_vc_state(usp, uvp,
966 UNI_VC_DROPACK_MSG, msg);
970 * Message size didn't match size received
972 err = unisig_send_status(usp, uvp, msg,
973 UNI_IE_CAUS_MTEXIST);
978 * Handle message errors that require a response
983 * Message size didn't match size received
985 err = unisig_send_status(usp, uvp, msg,
991 * Free the incoming message (both buffer and internal format)
995 unisig_free_msg(msg);