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 $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_msg.c,v 1.2 2003/06/17 04:28:49 dillon 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>
48 static void unisig_rcv_restart __P((struct unisig *, struct unisig_msg *));
49 static void unisig_rcv_setup __P((struct unisig *, struct unisig_msg *));
56 static int unisig_print_msg = 0;
61 * Set a Cause IE based on information in an ATM attribute block
64 * iep pointer to a cause IE
65 * aap pointer to attribute block
69 * errno error encountered
73 unisig_cause_from_attr(iep, aap)
74 struct ie_generic *iep;
78 * Copy cause info from attribute block to IE
80 iep->ie_ident = UNI_IE_CAUS;
81 iep->ie_coding = aap->cause.v.coding_standard;
82 iep->ie_caus_loc = aap->cause.v.location;
83 iep->ie_caus_cause = aap->cause.v.cause_value;
88 * Set a Cause IE based on information in a UNI signalling message
91 * iep pointer to a cause IE
92 * msg pointer to message
93 * cause cause code for the error
97 * errno error encountered
101 unisig_cause_from_msg(iep, msg, cause)
102 struct ie_generic *iep;
103 struct unisig_msg *msg;
106 struct ie_generic *ie1;
110 * Fill out the cause IE fixed fields
112 iep->ie_ident = UNI_IE_CAUS;
113 iep->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
114 iep->ie_caus_cause = cause;
117 * Set diagnostics if indicated
120 case UNI_IE_CAUS_IECONTENT:
121 iep->ie_caus_diag_len = 0;
122 for (i = 0, ie1 = msg->msg_ie_err;
123 ie1 && i < UNI_IE_CAUS_MAX_ID;
124 ie1 = ie1->ie_next) {
125 if (ie1->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
126 iep->ie_caus_diagnostic[i] =
128 iep->ie_caus_diag_len++;
133 case UNI_IE_CAUS_REJECT:
134 iep->ie_caus_diag_len = 2;
135 iep->ie_caus_diagnostic[0] = UNI_IE_EXT_BIT +
136 (UNI_IE_CAUS_RR_USER << UNI_IE_CAUS_RR_SHIFT) +
137 UNI_IE_CAUS_RC_TRANS;
138 iep->ie_caus_diagnostic[1] = 0;
140 case UNI_IE_CAUS_MISSING:
141 iep->ie_caus_diag_len = 0;
142 for (i = 0, ie1 = msg->msg_ie_err;
143 ie1 && i < UNI_IE_CAUS_MAX_ID;
144 ie1 = ie1->ie_next) {
145 if (ie1->ie_err_cause == UNI_IE_CAUS_MISSING) {
146 iep->ie_caus_diagnostic[i] =
148 iep->ie_caus_diag_len++;
157 * Send a UNISIG signalling message
159 * Called to send a Q.2931 message. This routine encodes the message
160 * and hands it to SSCF for transmission.
163 * usp pointer to UNISIG protocol instance block
164 * msg pointer to message
168 * errno error encountered
172 unisig_send_msg(usp, msg)
174 struct unisig_msg *msg;
179 ATM_DEBUG2("unisig_send_msg: msg=%p, type=%d\n", msg,
183 * Make sure the network is up
185 if (usp->us_state != UNISIG_ACTIVE)
190 * Print the message we're sending.
192 if (unisig_print_msg)
193 usp_print_msg(msg, UNISIG_MSG_OUT);
197 * Convert message to network order
199 err = usf_init(&usf, usp, (KBuffer *) 0, USF_ENCODE,
204 err = usf_enc_msg(&usf, msg);
206 ATM_DEBUG1("unisig_send_msg: encode failed with %d\n",
208 KB_FREEALL(usf.usf_m_base);
214 * Print the converted message
216 if (unisig_print_msg > 1)
217 unisig_print_mbuf(usf.usf_m_base);
223 err = atm_cm_saal_data(usp->us_conn, usf.usf_m_base);
225 KB_FREEALL(usf.usf_m_base);
232 * Send a SETUP request
234 * Build and send a Q.2931 SETUP message.
237 * usp pointer to UNISIG protocol instance block
238 * uvp pointer to VCCB for which the request is being sent
245 unisig_send_setup(usp, uvp)
247 struct unisig_vccb *uvp;
250 struct unisig_msg *setup;
251 Atm_attributes *ap = &uvp->uv_connvc->cvc_attr;
253 ATM_DEBUG1("unisig_send_setup: uvp=%p\n", uvp);
256 * Make sure required connection attriutes are set
258 if (ap->aal.tag != T_ATM_PRESENT ||
259 ap->traffic.tag != T_ATM_PRESENT ||
260 ap->bearer.tag != T_ATM_PRESENT ||
261 ap->called.tag != T_ATM_PRESENT ||
262 ap->qos.tag != T_ATM_PRESENT) {
269 * Get memory for a SETUP message
271 setup = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
278 * Fill in the SETUP message
280 if (!uvp->uv_call_ref)
281 uvp->uv_call_ref = unisig_alloc_call_ref(usp);
282 setup->msg_call_ref = uvp->uv_call_ref;
283 setup->msg_type = UNI_MSG_SETU;
286 * Set IEs from connection attributes
288 err = unisig_set_attrs(usp, setup, ap);
293 * Attach a Calling Party Number IE if the user didn't
294 * specify one in the attribute block
296 if (ap->calling.tag != T_ATM_PRESENT) {
297 setup->msg_ie_cgad = (struct ie_generic *)
298 atm_allocate(&unisig_iepool);
299 if (setup->msg_ie_cgad == NULL) {
303 setup->msg_ie_cgad->ie_ident = UNI_IE_CGAD;
304 ATM_ADDR_COPY(&usp->us_addr,
305 &setup->msg_ie_cgad->ie_cgad_addr);
306 ATM_ADDR_SEL_COPY(&usp->us_addr,
307 uvp->uv_nif ? uvp->uv_nif->nif_sel : 0,
308 &setup->msg_ie_cgad->ie_cgad_addr);
312 * Send the SETUP message
314 err = unisig_send_msg(usp, setup);
318 unisig_free_msg(setup);
325 * Send a RELEASE message
328 * usp pointer to UNISIG protocol instance block
329 * uvp pointer to VCCB for which the RELEASE is being sent
330 * msg pointer to UNI signalling message that the RELEASE
331 * responds to (may be NULL)
332 * cause the reason for the RELEASE; a value of
333 * T_ATM_ABSENT indicates that the cause code is
334 * in the VCC's ATM attributes block
341 unisig_send_release(usp, uvp, msg, cause)
343 struct unisig_vccb *uvp;
344 struct unisig_msg *msg;
348 struct unisig_msg *rls_msg;
349 struct ie_generic *cause_ie;
351 ATM_DEBUG2("unisig_send_release: usp=%p, uvp=%p\n",
355 * Get memory for a RELEASE message
357 rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
358 if (rls_msg == NULL) {
361 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
362 if (cause_ie == NULL) {
368 * Fill in the RELEASE message
370 rls_msg->msg_call_ref = uvp->uv_call_ref;
371 rls_msg->msg_type = UNI_MSG_RLSE;
372 rls_msg->msg_type_flag = 0;
373 rls_msg->msg_type_action = 0;
374 rls_msg->msg_ie_caus = cause_ie;
377 * Fill out the cause IE
379 cause_ie->ie_ident = UNI_IE_CAUS;
380 if (cause == T_ATM_ABSENT) {
381 unisig_cause_from_attr(cause_ie,
382 &uvp->uv_connvc->cvc_attr);
384 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
385 unisig_cause_from_msg(cause_ie, msg, cause);
391 err = unisig_send_msg(usp, rls_msg);
392 unisig_free_msg(rls_msg);
399 * Send a RELEASE COMPLETE message
402 * usp pointer to UNISIG protocol instance block
403 * uvp pointer to VCCB for which the RELEASE is being sent.
404 * NULL indicates that a VCCB wasn't found for a call
406 * msg pointer to the message which triggered the send
407 * cause the cause code for the message; a value of
408 * T_ATM_ABSENT indicates that the cause code is
409 * in the VCC's ATM attributes block
413 * errno error encountered
417 unisig_send_release_complete(usp, uvp, msg, cause)
419 struct unisig_vccb *uvp;
420 struct unisig_msg *msg;
424 struct unisig_msg *rls_cmp;
425 struct ie_generic *cause_ie;
427 ATM_DEBUG4("unisig_send_release_complete usp=%p, uvp=%p, msg=%p, cause=%d\n",
428 usp, uvp, msg, cause);
431 * Get memory for a RELEASE COMPLETE message
433 rls_cmp = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
434 if (rls_cmp == NULL) {
437 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
438 if (cause_ie == NULL) {
444 * Fill in the RELEASE COMPLETE message
447 rls_cmp->msg_call_ref = uvp->uv_call_ref;
449 rls_cmp->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
451 rls_cmp->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
453 rls_cmp->msg_type = UNI_MSG_RLSC;
454 rls_cmp->msg_type_flag = 0;
455 rls_cmp->msg_type_action = 0;
456 rls_cmp->msg_ie_caus = cause_ie;
459 * Fill out the cause IE
461 cause_ie->ie_ident = UNI_IE_CAUS;
462 if (cause == T_ATM_ABSENT) {
463 unisig_cause_from_attr(cause_ie,
464 &uvp->uv_connvc->cvc_attr);
466 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
467 unisig_cause_from_msg(cause_ie, msg, cause);
471 * Send the RELEASE COMPLETE
473 err = unisig_send_msg(usp, rls_cmp);
474 unisig_free_msg(rls_cmp);
481 * Send a STATUS message
484 * usp pointer to UNISIG protocol instance block
485 * uvp pointer to VCCB for which the STATUS is being sent.
486 * NULL indicates that a VCCB wasn't found for a call
488 * msg pointer to the message which triggered the send
489 * cause the cause code to include in the message
496 unisig_send_status(usp, uvp, msg, cause)
498 struct unisig_vccb *uvp;
499 struct unisig_msg *msg;
503 struct unisig_msg *stat_msg;
504 struct ie_generic *cause_ie, *clst_ie, *iep;
506 ATM_DEBUG4("unisig_send_status: usp=%p, uvp=%p, msg=%p, cause=%d\n",
507 usp, uvp, msg, cause);
510 * Get memory for a STATUS message
512 stat_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
513 if (stat_msg == NULL) {
516 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
517 if (cause_ie == NULL) {
521 clst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
522 if (clst_ie == NULL) {
529 * Fill in the STATUS message
532 stat_msg->msg_call_ref = uvp->uv_call_ref;
534 stat_msg->msg_call_ref =
535 EXTRACT_CREF(msg->msg_call_ref);
537 stat_msg->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
539 stat_msg->msg_type = UNI_MSG_STAT;
540 stat_msg->msg_type_flag = 0;
541 stat_msg->msg_type_action = 0;
542 stat_msg->msg_ie_clst = clst_ie;
543 stat_msg->msg_ie_caus = cause_ie;
546 * Fill out the call state IE
548 clst_ie->ie_ident = UNI_IE_CLST;
549 clst_ie->ie_coding = 0;
550 clst_ie->ie_flag = 0;
551 clst_ie->ie_action = 0;
553 clst_ie->ie_clst_state = uvp->uv_sstate;
555 clst_ie->ie_clst_state = UNI_NULL;
559 * Fill out the cause IE
561 cause_ie->ie_ident = UNI_IE_CAUS;
562 cause_ie->ie_coding = 0;
563 cause_ie->ie_flag = 0;
564 cause_ie->ie_action = 0;
565 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
566 cause_ie->ie_caus_cause = cause;
568 case UNI_IE_CAUS_MTEXIST:
569 case UNI_IE_CAUS_STATE:
571 cause_ie->ie_caus_diagnostic[0] = msg->msg_type;
574 case UNI_IE_CAUS_MISSING:
575 case UNI_IE_CAUS_IECONTENT:
576 case UNI_IE_CAUS_IEEXIST:
577 for (i=0, iep=msg->msg_ie_err;
578 iep && i<UNI_MSG_IE_CNT;
579 i++, iep = iep->ie_next) {
580 if (iep->ie_err_cause == cause) {
581 cause_ie->ie_caus_diagnostic[i] =
588 * Send the STATUS message
590 err = unisig_send_msg(usp, stat_msg);
591 unisig_free_msg(stat_msg);
598 * Process a RESTART message
601 * usp pointer to UNISIG protocol instance block
602 * msg pointer to the RESTART message
609 unisig_rcv_restart(usp, msg)
611 struct unisig_msg *msg;
613 struct unisig_vccb *uvp, *uvnext;
614 struct unisig_msg *rsta_msg;
617 ATM_DEBUG2("unisig_rcv_restart: usp=%p, msg=%p\n",
621 * Check what class of VCCs we're supposed to restart
623 if (msg->msg_ie_rsti->ie_rsti_class == UNI_IE_RSTI_IND_VC) {
625 * Just restart the indicated VCC
627 if (msg->msg_ie_cnid) {
628 uvp = unisig_find_vpvc(usp,
629 msg->msg_ie_cnid->ie_cnid_vpci,
630 msg->msg_ie_cnid->ie_cnid_vci,
632 if (uvp && uvp->uv_type & VCC_SVC) {
633 (void) unisig_clear_vcc(usp, uvp,
634 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
642 for (uvp=Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
644 uvnext = Q_NEXT(uvp, struct unisig_vccb,
646 if (uvp->uv_type & VCC_SVC) {
647 (void) unisig_clear_vcc(usp, uvp,
648 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
655 * Get memory for a RESTART ACKNOWLEDGE message
657 rsta_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
658 if (rsta_msg == NULL) {
663 * Fill out the message
665 rsta_msg->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
666 rsta_msg->msg_type = UNI_MSG_RSTA;
667 rsta_msg->msg_type_flag = 0;
668 rsta_msg->msg_type_action = 0;
669 rsta_msg->msg_ie_rsti = msg->msg_ie_rsti;
670 if (msg->msg_ie_cnid) {
671 rsta_msg->msg_ie_cnid = msg->msg_ie_cnid;
677 (void) unisig_send_msg(usp, rsta_msg);
678 rsta_msg->msg_ie_rsti = NULL;
679 rsta_msg->msg_ie_cnid = NULL;
680 unisig_free_msg(rsta_msg);
687 * Process a SETUP message
690 * usp pointer to UNISIG protocol instance block
691 * msg pointer to the SETUP message
698 unisig_rcv_setup(usp, msg)
700 struct unisig_msg *msg;
702 struct unisig_vccb *uvp = NULL;
703 struct ie_generic *iep;
705 ATM_DEBUG2("unisig_rcv_setup: usp=%p, msg=%p\n", usp, msg);
708 * If we already have a VCC with the call reference,
709 * ignore the SETUP message
711 uvp = unisig_find_conn(usp, EXTRACT_CREF(msg->msg_call_ref));
716 * If the call reference flag is incorrectly set,
717 * ignore the SETUP message
719 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
723 * If there are missing mandatory IEs, send a
724 * RELEASE COMPLETE message and ignore the SETUP
726 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
727 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
728 (void) unisig_send_release_complete(usp,
729 uvp, msg, UNI_IE_CAUS_MISSING);
735 * If there are mandatory IEs with invalid content, send a
736 * RELEASE COMPLETE message and ignore the SETUP
738 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
739 if (iep->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
740 (void) unisig_send_release_complete(usp,
742 UNI_IE_CAUS_IECONTENT);
748 * Get a new VCCB for the connection
750 uvp = (struct unisig_vccb *)atm_allocate(&unisig_vcpool);
756 * Put the VCCB on the UNISIG queue
758 ENQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
761 * Set the state and call reference value
763 uvp->uv_sstate = UNI_NULL;
764 uvp->uv_call_ref = EXTRACT_CREF(msg->msg_call_ref);
767 * Pass the VCCB and message to the VC state machine
769 (void) unisig_vc_state(usp, uvp, UNI_VC_SETUP_MSG, msg);
772 * If the VCCB state is NULL, the open failed and the
773 * VCCB should be released
775 if (uvp->uv_sstate == UNI_NULL) {
776 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem,
786 * Process a UNISIG signalling message
788 * Called when a UNISIG message is received. The message is decoded
789 * and passed to the UNISIG state machine. Unrecognized and
790 * unexpected messages are logged.
793 * usp pointer to UNISIG protocol instance block
794 * m pointer to a buffer chain containing the UNISIG message
801 unisig_rcv_msg(usp, m)
808 struct unisig_msg *msg = 0;
809 struct unisig_vccb *uvp = 0;
810 struct ie_generic *iep;
812 ATM_DEBUG2("unisig_rcv_msg: bfr=%p, len=%d\n", m, KB_LEN(m));
815 unisig_print_mbuf(m);
819 * Get storage for the message
821 msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
828 * Convert the message from network order to internal format
830 err = usf_init(&usf, usp, m, USF_DECODE, 0);
833 panic("unisig_rcv_msg: invalid parameter\n");
834 ATM_DEBUG1("unisig_rcv_msg: decode init failed with %d\n",
839 err = usf_dec_msg(&usf, msg);
841 ATM_DEBUG1("unisig_rcv_msg: decode failed with %d\n",
848 * Debug--print some information about the message
850 if (unisig_print_msg)
851 usp_print_msg(msg, UNISIG_MSG_IN);
855 * Get the call reference value
857 cref = EXTRACT_CREF(msg->msg_call_ref);
860 * Any message with the global call reference value except
861 * RESTART, RESTART ACK, or STATUS is in error
863 if (GLOBAL_CREF(cref) &&
864 msg->msg_type != UNI_MSG_RSTR &&
865 msg->msg_type != UNI_MSG_RSTA &&
866 msg->msg_type != UNI_MSG_STAT) {
868 * Send STATUS message indicating the error
870 err = unisig_send_status(usp, (struct unisig_vccb *) 0,
871 msg, UNI_IE_CAUS_CREF);
876 * Check for missing mandatory IEs. Checks for SETUP,
877 * RELEASE, and RELEASE COMPLETE are handled elsewhere.
879 if (msg->msg_type != UNI_MSG_SETU &&
880 msg->msg_type != UNI_MSG_RLSE &&
881 msg->msg_type != UNI_MSG_RLSC) {
882 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
883 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
884 err = unisig_send_status(usp,
886 UNI_IE_CAUS_MISSING);
893 * Find the VCCB associated with the message
895 uvp = unisig_find_conn(usp, cref);
898 * Process the message based on its type
900 switch(msg->msg_type) {
902 (void) unisig_vc_state(usp, uvp,
903 UNI_VC_CALLP_MSG, msg);
906 (void) unisig_vc_state(usp, uvp,
907 UNI_VC_CONNECT_MSG, msg);
910 (void) unisig_vc_state(usp, uvp,
911 UNI_VC_CNCTACK_MSG, msg);
914 unisig_rcv_setup(usp, msg);
917 (void) unisig_vc_state(usp, uvp,
918 UNI_VC_RELEASE_MSG, msg);
922 * Ignore a RELEASE COMPLETE with an unrecognized
923 * call reference value
926 (void) unisig_vc_state(usp, uvp,
927 UNI_VC_RLSCMP_MSG, msg);
931 unisig_rcv_restart(usp, msg);
936 (void) unisig_vc_state(usp, uvp,
937 UNI_VC_STATUS_MSG, msg);
940 (void) unisig_vc_state(usp, uvp,
941 UNI_VC_STATUSENQ_MSG, msg);
944 (void) unisig_vc_state(usp, uvp,
945 UNI_VC_ADDP_MSG, msg);
948 (void) unisig_vc_state(usp, uvp,
949 UNI_VC_ADDPACK_MSG, msg);
952 (void) unisig_vc_state(usp, uvp,
953 UNI_VC_ADDPREJ_MSG, msg);
956 (void) unisig_vc_state(usp, uvp,
957 UNI_VC_DROP_MSG, msg);
960 (void) unisig_vc_state(usp, uvp,
961 UNI_VC_DROPACK_MSG, msg);
965 * Message size didn't match size received
967 err = unisig_send_status(usp, uvp, msg,
968 UNI_IE_CAUS_MTEXIST);
973 * Handle message errors that require a response
978 * Message size didn't match size received
980 err = unisig_send_status(usp, uvp, msg,
986 * Free the incoming message (both buffer and internal format)
990 unisig_free_msg(msg);