HAMMER Utilities: MFC work to date.
[dragonfly.git] / sys / netproto / atm / uni / unisig_msg.c
blob0995a5044ec606bf22b06cedd541da133e3f3d81
1 /*
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.7 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * Message handling module
38 #include <netproto/atm/kern_include.h>
40 #include "unisig_var.h"
41 #include "unisig_msg.h"
42 #include "unisig_mbuf.h"
43 #include "unisig_print.h"
46 * Local functions
48 static void unisig_rcv_restart (struct unisig *, struct unisig_msg *);
49 static void unisig_rcv_setup (struct unisig *, struct unisig_msg *);
53 * Local variables
55 #ifdef DIAGNOSTIC
56 static int unisig_print_msg = 0;
57 #endif
61 * Set a Cause IE based on information in an ATM attribute block
63 * Arguments:
64 * iep pointer to a cause IE
65 * aap pointer to attribute block
67 * Returns:
68 * 0 message sent OK
69 * errno error encountered
72 void
73 unisig_cause_from_attr(struct ie_generic *iep, Atm_attributes *aap)
76 * Copy cause info from attribute block to IE
78 iep->ie_ident = UNI_IE_CAUS;
79 iep->ie_coding = aap->cause.v.coding_standard;
80 iep->ie_caus_loc = aap->cause.v.location;
81 iep->ie_caus_cause = aap->cause.v.cause_value;
86 * Set a Cause IE based on information in a UNI signalling message
88 * Arguments:
89 * iep pointer to a cause IE
90 * msg pointer to message
91 * cause cause code for the error
93 * Returns:
94 * 0 message sent OK
95 * errno error encountered
98 void
99 unisig_cause_from_msg(struct ie_generic *iep, struct unisig_msg *msg,
100 int cause)
102 struct ie_generic *ie1;
103 int i;
106 * Fill out the cause IE fixed fields
108 iep->ie_ident = UNI_IE_CAUS;
109 iep->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
110 iep->ie_caus_cause = cause;
113 * Set diagnostics if indicated
115 switch(cause) {
116 case UNI_IE_CAUS_IECONTENT:
117 iep->ie_caus_diag_len = 0;
118 for (i = 0, ie1 = msg->msg_ie_err;
119 ie1 && i < UNI_IE_CAUS_MAX_ID;
120 ie1 = ie1->ie_next) {
121 if (ie1->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
122 iep->ie_caus_diagnostic[i] =
123 ie1->ie_ident;
124 iep->ie_caus_diag_len++;
125 i++;
128 break;
129 case UNI_IE_CAUS_REJECT:
130 iep->ie_caus_diag_len = 2;
131 iep->ie_caus_diagnostic[0] = UNI_IE_EXT_BIT +
132 (UNI_IE_CAUS_RR_USER << UNI_IE_CAUS_RR_SHIFT) +
133 UNI_IE_CAUS_RC_TRANS;
134 iep->ie_caus_diagnostic[1] = 0;
135 break;
136 case UNI_IE_CAUS_MISSING:
137 iep->ie_caus_diag_len = 0;
138 for (i = 0, ie1 = msg->msg_ie_err;
139 ie1 && i < UNI_IE_CAUS_MAX_ID;
140 ie1 = ie1->ie_next) {
141 if (ie1->ie_err_cause == UNI_IE_CAUS_MISSING) {
142 iep->ie_caus_diagnostic[i] =
143 ie1->ie_ident;
144 iep->ie_caus_diag_len++;
145 i++;
153 * Send a UNISIG signalling message
155 * Called to send a Q.2931 message. This routine encodes the message
156 * and hands it to SSCF for transmission.
158 * Arguments:
159 * usp pointer to UNISIG protocol instance block
160 * msg pointer to message
162 * Returns:
163 * 0 message sent OK
164 * errno error encountered
168 unisig_send_msg(struct unisig *usp, struct unisig_msg *msg)
170 int err = 0;
171 struct usfmt usf;
173 ATM_DEBUG2("unisig_send_msg: msg=%p, type=%d\n", msg,
174 msg->msg_type);
177 * Make sure the network is up
179 if (usp->us_state != UNISIG_ACTIVE)
180 return(ENETDOWN);
182 #ifdef DIAGNOSTIC
184 * Print the message we're sending.
186 if (unisig_print_msg)
187 usp_print_msg(msg, UNISIG_MSG_OUT);
188 #endif
191 * Convert message to network order
193 err = usf_init(&usf, usp, (KBuffer *) 0, USF_ENCODE,
194 usp->us_headout);
195 if (err)
196 return(err);
198 err = usf_enc_msg(&usf, msg);
199 if (err) {
200 ATM_DEBUG1("unisig_send_msg: encode failed with %d\n",
201 err);
202 KB_FREEALL(usf.usf_m_base);
203 return(EIO);
206 #ifdef DIAGNOSTIC
208 * Print the converted message
210 if (unisig_print_msg > 1)
211 unisig_print_mbuf(usf.usf_m_base);
212 #endif
215 * Send the message
217 err = atm_cm_saal_data(usp->us_conn, usf.usf_m_base);
218 if (err)
219 KB_FREEALL(usf.usf_m_base);
221 return(err);
226 * Send a SETUP request
228 * Build and send a Q.2931 SETUP message.
230 * Arguments:
231 * usp pointer to UNISIG protocol instance block
232 * uvp pointer to VCCB for which the request is being sent
234 * Returns:
235 * none
239 unisig_send_setup(struct unisig *usp, struct unisig_vccb *uvp)
241 int err = 0;
242 struct unisig_msg *setup;
243 Atm_attributes *ap = &uvp->uv_connvc->cvc_attr;
245 ATM_DEBUG1("unisig_send_setup: uvp=%p\n", uvp);
248 * Make sure required connection attriutes are set
250 if (ap->aal.tag != T_ATM_PRESENT ||
251 ap->traffic.tag != T_ATM_PRESENT ||
252 ap->bearer.tag != T_ATM_PRESENT ||
253 ap->called.tag != T_ATM_PRESENT ||
254 ap->qos.tag != T_ATM_PRESENT) {
255 err = EINVAL;
256 setup = NULL;
257 goto done;
261 * Get memory for a SETUP message
263 setup = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
264 if (setup == NULL) {
265 err = ENOMEM;
266 goto done;
270 * Fill in the SETUP message
272 if (!uvp->uv_call_ref)
273 uvp->uv_call_ref = unisig_alloc_call_ref(usp);
274 setup->msg_call_ref = uvp->uv_call_ref;
275 setup->msg_type = UNI_MSG_SETU;
278 * Set IEs from connection attributes
280 err = unisig_set_attrs(usp, setup, ap);
281 if (err)
282 goto done;
285 * Attach a Calling Party Number IE if the user didn't
286 * specify one in the attribute block
288 if (ap->calling.tag != T_ATM_PRESENT) {
289 setup->msg_ie_cgad = (struct ie_generic *)
290 atm_allocate(&unisig_iepool);
291 if (setup->msg_ie_cgad == NULL) {
292 err = ENOMEM;
293 goto done;
295 setup->msg_ie_cgad->ie_ident = UNI_IE_CGAD;
296 ATM_ADDR_COPY(&usp->us_addr,
297 &setup->msg_ie_cgad->ie_cgad_addr);
298 ATM_ADDR_SEL_COPY(&usp->us_addr,
299 uvp->uv_nif ? uvp->uv_nif->nif_sel : 0,
300 &setup->msg_ie_cgad->ie_cgad_addr);
304 * Send the SETUP message
306 err = unisig_send_msg(usp, setup);
308 done:
309 if (setup)
310 unisig_free_msg(setup);
312 return(err);
317 * Send a RELEASE message
319 * Arguments:
320 * usp pointer to UNISIG protocol instance block
321 * uvp pointer to VCCB for which the RELEASE is being sent
322 * msg pointer to UNI signalling message that the RELEASE
323 * responds to (may be NULL)
324 * cause the reason for the RELEASE; a value of
325 * T_ATM_ABSENT indicates that the cause code is
326 * in the VCC's ATM attributes block
328 * Returns:
329 * none
333 unisig_send_release(struct unisig *usp, struct unisig_vccb *uvp,
334 struct unisig_msg *msg, int cause)
336 int err = 0;
337 struct unisig_msg *rls_msg;
338 struct ie_generic *cause_ie;
340 ATM_DEBUG2("unisig_send_release: usp=%p, uvp=%p\n",
341 usp, uvp);
344 * Get memory for a RELEASE message
346 rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
347 if (rls_msg == NULL) {
348 return(ENOMEM);
350 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
351 if (cause_ie == NULL) {
352 atm_free(rls_msg);
353 return(ENOMEM);
357 * Fill in the RELEASE message
359 rls_msg->msg_call_ref = uvp->uv_call_ref;
360 rls_msg->msg_type = UNI_MSG_RLSE;
361 rls_msg->msg_type_flag = 0;
362 rls_msg->msg_type_action = 0;
363 rls_msg->msg_ie_caus = cause_ie;
366 * Fill out the cause IE
368 cause_ie->ie_ident = UNI_IE_CAUS;
369 if (cause == T_ATM_ABSENT) {
370 unisig_cause_from_attr(cause_ie,
371 &uvp->uv_connvc->cvc_attr);
372 } else {
373 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
374 unisig_cause_from_msg(cause_ie, msg, cause);
378 * Send the RELEASE
380 err = unisig_send_msg(usp, rls_msg);
381 unisig_free_msg(rls_msg);
383 return(err);
388 * Send a RELEASE COMPLETE message
390 * Arguments:
391 * usp pointer to UNISIG protocol instance block
392 * uvp pointer to VCCB for which the RELEASE is being sent.
393 * NULL indicates that a VCCB wasn't found for a call
394 * reference value.
395 * msg pointer to the message which triggered the send
396 * cause the cause code for the message; a value of
397 * T_ATM_ABSENT indicates that the cause code is
398 * in the VCC's ATM attributes block
400 * Returns:
401 * 0 success
402 * errno error encountered
406 unisig_send_release_complete(struct unisig *usp, struct unisig_vccb *uvp,
407 struct unisig_msg *msg, int cause)
409 int err = 0;
410 struct unisig_msg *rls_cmp;
411 struct ie_generic *cause_ie;
413 ATM_DEBUG4("unisig_send_release_complete usp=%p, uvp=%p, msg=%p, cause=%d\n",
414 usp, uvp, msg, cause);
417 * Get memory for a RELEASE COMPLETE message
419 rls_cmp = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
420 if (rls_cmp == NULL) {
421 return(ENOMEM);
423 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
424 if (cause_ie == NULL) {
425 atm_free(rls_cmp);
426 return(ENOMEM);
430 * Fill in the RELEASE COMPLETE message
432 if (uvp) {
433 rls_cmp->msg_call_ref = uvp->uv_call_ref;
434 } else if (msg) {
435 rls_cmp->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
436 } else {
437 rls_cmp->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
439 rls_cmp->msg_type = UNI_MSG_RLSC;
440 rls_cmp->msg_type_flag = 0;
441 rls_cmp->msg_type_action = 0;
442 rls_cmp->msg_ie_caus = cause_ie;
445 * Fill out the cause IE
447 cause_ie->ie_ident = UNI_IE_CAUS;
448 if (cause == T_ATM_ABSENT) {
449 unisig_cause_from_attr(cause_ie,
450 &uvp->uv_connvc->cvc_attr);
451 } else {
452 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
453 unisig_cause_from_msg(cause_ie, msg, cause);
457 * Send the RELEASE COMPLETE
459 err = unisig_send_msg(usp, rls_cmp);
460 unisig_free_msg(rls_cmp);
462 return(err);
467 * Send a STATUS message
469 * Arguments:
470 * usp pointer to UNISIG protocol instance block
471 * uvp pointer to VCCB for which the STATUS is being sent.
472 * NULL indicates that a VCCB wasn't found for a call
473 * reference value.
474 * msg pointer to the message which triggered the send
475 * cause the cause code to include in the message
477 * Returns:
478 * none
482 unisig_send_status(struct unisig *usp, struct unisig_vccb *uvp,
483 struct unisig_msg *msg, int cause)
485 int err = 0, i;
486 struct unisig_msg *stat_msg;
487 struct ie_generic *cause_ie, *clst_ie, *iep;
489 ATM_DEBUG4("unisig_send_status: usp=%p, uvp=%p, msg=%p, cause=%d\n",
490 usp, uvp, msg, cause);
493 * Get memory for a STATUS message
495 stat_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
496 if (stat_msg == NULL) {
497 return(ENOMEM);
499 cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
500 if (cause_ie == NULL) {
501 atm_free(stat_msg);
502 return(ENOMEM);
504 clst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
505 if (clst_ie == NULL) {
506 atm_free(stat_msg);
507 atm_free(cause_ie);
508 return(ENOMEM);
512 * Fill in the STATUS message
514 if (uvp) {
515 stat_msg->msg_call_ref = uvp->uv_call_ref;
516 } else if (msg) {
517 stat_msg->msg_call_ref =
518 EXTRACT_CREF(msg->msg_call_ref);
519 } else {
520 stat_msg->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
522 stat_msg->msg_type = UNI_MSG_STAT;
523 stat_msg->msg_type_flag = 0;
524 stat_msg->msg_type_action = 0;
525 stat_msg->msg_ie_clst = clst_ie;
526 stat_msg->msg_ie_caus = cause_ie;
529 * Fill out the call state IE
531 clst_ie->ie_ident = UNI_IE_CLST;
532 clst_ie->ie_coding = 0;
533 clst_ie->ie_flag = 0;
534 clst_ie->ie_action = 0;
535 if (uvp) {
536 clst_ie->ie_clst_state = uvp->uv_sstate;
537 } else {
538 clst_ie->ie_clst_state = UNI_NULL;
542 * Fill out the cause IE
544 cause_ie->ie_ident = UNI_IE_CAUS;
545 cause_ie->ie_coding = 0;
546 cause_ie->ie_flag = 0;
547 cause_ie->ie_action = 0;
548 cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
549 cause_ie->ie_caus_cause = cause;
550 switch (cause) {
551 case UNI_IE_CAUS_MTEXIST:
552 case UNI_IE_CAUS_STATE:
553 if (msg) {
554 cause_ie->ie_caus_diagnostic[0] = msg->msg_type;
556 break;
557 case UNI_IE_CAUS_MISSING:
558 case UNI_IE_CAUS_IECONTENT:
559 case UNI_IE_CAUS_IEEXIST:
560 for (i=0, iep=msg->msg_ie_err;
561 iep && i<UNI_MSG_IE_CNT;
562 i++, iep = iep->ie_next) {
563 if (iep->ie_err_cause == cause) {
564 cause_ie->ie_caus_diagnostic[i] =
565 iep->ie_ident;
571 * Send the STATUS message
573 err = unisig_send_msg(usp, stat_msg);
574 unisig_free_msg(stat_msg);
576 return(err);
581 * Process a RESTART message
583 * Arguments:
584 * usp pointer to UNISIG protocol instance block
585 * msg pointer to the RESTART message
587 * Returns:
588 * none
591 static void
592 unisig_rcv_restart(struct unisig *usp, struct unisig_msg *msg)
594 struct unisig_vccb *uvp, *uvnext;
595 struct unisig_msg *rsta_msg;
597 ATM_DEBUG2("unisig_rcv_restart: usp=%p, msg=%p\n",
598 usp, msg);
601 * Check what class of VCCs we're supposed to restart
603 if (msg->msg_ie_rsti->ie_rsti_class == UNI_IE_RSTI_IND_VC) {
605 * Just restart the indicated VCC
607 if (msg->msg_ie_cnid) {
608 uvp = unisig_find_vpvc(usp,
609 msg->msg_ie_cnid->ie_cnid_vpci,
610 msg->msg_ie_cnid->ie_cnid_vci,
612 if (uvp && uvp->uv_type & VCC_SVC) {
613 unisig_clear_vcc(usp, uvp,
614 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
617 } else {
619 * Restart all VCCs
621 crit_enter();
622 for (uvp=Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
623 uvp=uvnext) {
624 uvnext = Q_NEXT(uvp, struct unisig_vccb,
625 uv_sigelem);
626 if (uvp->uv_type & VCC_SVC) {
627 unisig_clear_vcc(usp, uvp,
628 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
631 crit_exit();
635 * Get memory for a RESTART ACKNOWLEDGE message
637 rsta_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
638 if (rsta_msg == NULL) {
639 return;
643 * Fill out the message
645 rsta_msg->msg_call_ref = EXTRACT_CREF(msg->msg_call_ref);
646 rsta_msg->msg_type = UNI_MSG_RSTA;
647 rsta_msg->msg_type_flag = 0;
648 rsta_msg->msg_type_action = 0;
649 rsta_msg->msg_ie_rsti = msg->msg_ie_rsti;
650 if (msg->msg_ie_cnid) {
651 rsta_msg->msg_ie_cnid = msg->msg_ie_cnid;
655 * Send the message
657 unisig_send_msg(usp, rsta_msg);
658 rsta_msg->msg_ie_rsti = NULL;
659 rsta_msg->msg_ie_cnid = NULL;
660 unisig_free_msg(rsta_msg);
662 return;
667 * Process a SETUP message
669 * Arguments:
670 * usp pointer to UNISIG protocol instance block
671 * msg pointer to the SETUP message
673 * Returns:
674 * none
677 static void
678 unisig_rcv_setup(struct unisig *usp, struct unisig_msg *msg)
680 struct unisig_vccb *uvp = NULL;
681 struct ie_generic *iep;
683 ATM_DEBUG2("unisig_rcv_setup: usp=%p, msg=%p\n", usp, msg);
686 * If we already have a VCC with the call reference,
687 * ignore the SETUP message
689 uvp = unisig_find_conn(usp, EXTRACT_CREF(msg->msg_call_ref));
690 if (uvp)
691 return;
694 * If the call reference flag is incorrectly set,
695 * ignore the SETUP message
697 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
698 return;
701 * If there are missing mandatory IEs, send a
702 * RELEASE COMPLETE message and ignore the SETUP
704 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
705 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
706 unisig_send_release_complete(usp,
707 uvp, msg, UNI_IE_CAUS_MISSING);
708 return;
713 * If there are mandatory IEs with invalid content, send a
714 * RELEASE COMPLETE message and ignore the SETUP
716 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
717 if (iep->ie_err_cause == UNI_IE_CAUS_IECONTENT) {
718 unisig_send_release_complete(usp,
719 uvp, msg,
720 UNI_IE_CAUS_IECONTENT);
721 return;
726 * Get a new VCCB for the connection
728 uvp = (struct unisig_vccb *)atm_allocate(&unisig_vcpool);
729 if (uvp == NULL) {
730 return;
734 * Put the VCCB on the UNISIG queue
736 ENQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
739 * Set the state and call reference value
741 uvp->uv_sstate = UNI_NULL;
742 uvp->uv_call_ref = EXTRACT_CREF(msg->msg_call_ref);
745 * Pass the VCCB and message to the VC state machine
747 unisig_vc_state(usp, uvp, UNI_VC_SETUP_MSG, msg);
750 * If the VCCB state is NULL, the open failed and the
751 * VCCB should be released
753 if (uvp->uv_sstate == UNI_NULL) {
754 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem,
755 usp->us_vccq);
756 atm_free(uvp);
759 return;
764 * Process a UNISIG signalling message
766 * Called when a UNISIG message is received. The message is decoded
767 * and passed to the UNISIG state machine. Unrecognized and
768 * unexpected messages are logged.
770 * Arguments:
771 * usp pointer to UNISIG protocol instance block
772 * m pointer to a buffer chain containing the UNISIG message
774 * Returns:
775 * none
779 unisig_rcv_msg(struct unisig *usp, KBuffer *m)
781 int err;
782 u_int cref;
783 struct usfmt usf;
784 struct unisig_msg *msg = 0;
785 struct unisig_vccb *uvp = 0;
786 struct ie_generic *iep;
788 ATM_DEBUG2("unisig_rcv_msg: bfr=%p, len=%d\n", m, KB_LEN(m));
790 #ifdef NOTDEF
791 unisig_print_mbuf(m);
792 #endif
795 * Get storage for the message
797 msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
798 if (msg == NULL) {
799 err = ENOMEM;
800 goto done;
804 * Convert the message from network order to internal format
806 err = usf_init(&usf, usp, m, USF_DECODE, 0);
807 if (err) {
808 if (err == EINVAL)
809 panic("unisig_rcv_msg: invalid parameter\n");
810 ATM_DEBUG1("unisig_rcv_msg: decode init failed with %d\n",
811 err);
812 goto done;
815 err = usf_dec_msg(&usf, msg);
816 if (err) {
817 ATM_DEBUG1("unisig_rcv_msg: decode failed with %d\n",
818 err);
819 goto done;
822 #ifdef DIAGNOSTIC
824 * Debug--print some information about the message
826 if (unisig_print_msg)
827 usp_print_msg(msg, UNISIG_MSG_IN);
828 #endif
831 * Get the call reference value
833 cref = EXTRACT_CREF(msg->msg_call_ref);
836 * Any message with the global call reference value except
837 * RESTART, RESTART ACK, or STATUS is in error
839 if (GLOBAL_CREF(cref) &&
840 msg->msg_type != UNI_MSG_RSTR &&
841 msg->msg_type != UNI_MSG_RSTA &&
842 msg->msg_type != UNI_MSG_STAT) {
844 * Send STATUS message indicating the error
846 err = unisig_send_status(usp, (struct unisig_vccb *) 0,
847 msg, UNI_IE_CAUS_CREF);
848 goto done;
852 * Check for missing mandatory IEs. Checks for SETUP,
853 * RELEASE, and RELEASE COMPLETE are handled elsewhere.
855 if (msg->msg_type != UNI_MSG_SETU &&
856 msg->msg_type != UNI_MSG_RLSE &&
857 msg->msg_type != UNI_MSG_RLSC) {
858 for (iep = msg->msg_ie_err; iep; iep = iep->ie_next) {
859 if (iep->ie_err_cause == UNI_IE_CAUS_MISSING) {
860 err = unisig_send_status(usp,
861 uvp, msg,
862 UNI_IE_CAUS_MISSING);
863 goto done;
869 * Find the VCCB associated with the message
871 uvp = unisig_find_conn(usp, cref);
874 * Process the message based on its type
876 switch(msg->msg_type) {
877 case UNI_MSG_CALP:
878 unisig_vc_state(usp, uvp,
879 UNI_VC_CALLP_MSG, msg);
880 break;
881 case UNI_MSG_CONN:
882 unisig_vc_state(usp, uvp,
883 UNI_VC_CONNECT_MSG, msg);
884 break;
885 case UNI_MSG_CACK:
886 unisig_vc_state(usp, uvp,
887 UNI_VC_CNCTACK_MSG, msg);
888 break;
889 case UNI_MSG_SETU:
890 unisig_rcv_setup(usp, msg);
891 break;
892 case UNI_MSG_RLSE:
893 unisig_vc_state(usp, uvp,
894 UNI_VC_RELEASE_MSG, msg);
895 break;
896 case UNI_MSG_RLSC:
898 * Ignore a RELEASE COMPLETE with an unrecognized
899 * call reference value
901 if (uvp) {
902 unisig_vc_state(usp, uvp,
903 UNI_VC_RLSCMP_MSG, msg);
905 break;
906 case UNI_MSG_RSTR:
907 unisig_rcv_restart(usp, msg);
908 break;
909 case UNI_MSG_RSTA:
910 break;
911 case UNI_MSG_STAT:
912 unisig_vc_state(usp, uvp,
913 UNI_VC_STATUS_MSG, msg);
914 break;
915 case UNI_MSG_SENQ:
916 unisig_vc_state(usp, uvp,
917 UNI_VC_STATUSENQ_MSG, msg);
918 break;
919 case UNI_MSG_ADDP:
920 unisig_vc_state(usp, uvp,
921 UNI_VC_ADDP_MSG, msg);
922 break;
923 case UNI_MSG_ADPA:
924 unisig_vc_state(usp, uvp,
925 UNI_VC_ADDPACK_MSG, msg);
926 break;
927 case UNI_MSG_ADPR:
928 unisig_vc_state(usp, uvp,
929 UNI_VC_ADDPREJ_MSG, msg);
930 break;
931 case UNI_MSG_DRPP:
932 unisig_vc_state(usp, uvp,
933 UNI_VC_DROP_MSG, msg);
934 break;
935 case UNI_MSG_DRPA:
936 unisig_vc_state(usp, uvp,
937 UNI_VC_DROPACK_MSG, msg);
938 break;
939 default:
941 * Message size didn't match size received
943 err = unisig_send_status(usp, uvp, msg,
944 UNI_IE_CAUS_MTEXIST);
947 done:
949 * Handle message errors that require a response
951 switch(err) {
952 case EMSGSIZE:
954 * Message size didn't match size received
956 err = unisig_send_status(usp, uvp, msg,
957 UNI_IE_CAUS_LEN);
958 break;
962 * Free the incoming message (both buffer and internal format)
963 * if necessary.
965 if (msg)
966 unisig_free_msg(msg);
967 if (m)
968 KB_FREEALL(m);
970 return (err);