2 * Copyright (c) 1996-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * Author: Hartmut Brandt <harti@freebsd.org>
29 * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
34 #include <netnatm/unimsg.h>
35 #include <netnatm/saal/sscopdef.h>
36 #include <netnatm/saal/sscfudef.h>
37 #include <netnatm/msg/unistruct.h>
38 #include <netnatm/msg/unimsglib.h>
39 #include <netnatm/sig/uni.h>
40 #include <netnatm/sig/unisig.h>
42 #include <netnatm/sig/unipriv.h>
48 #define STR(S) [S] = #S
49 static const char *custat_names[] = {
55 static const char *globstat_names[] = {
56 STR(UNI_CALLSTATE_REST0),
57 STR(UNI_CALLSTATE_REST1),
58 STR(UNI_CALLSTATE_REST2),
61 static const char *sig_names[] = {
63 STR(UNIAPI_CALL_CREATED),
64 STR(UNIAPI_CALL_DESTROYED),
65 STR(UNIAPI_PARTY_CREATED),
66 STR(UNIAPI_PARTY_DESTROYED),
67 STR(UNIAPI_LINK_ESTABLISH_request),
68 STR(UNIAPI_LINK_ESTABLISH_confirm),
69 STR(UNIAPI_LINK_RELEASE_request),
70 STR(UNIAPI_LINK_RELEASE_confirm),
71 STR(UNIAPI_RESET_request),
72 STR(UNIAPI_RESET_confirm),
73 STR(UNIAPI_RESET_indication),
74 STR(UNIAPI_RESET_ERROR_indication),
75 STR(UNIAPI_RESET_response),
76 STR(UNIAPI_RESET_ERROR_response),
77 STR(UNIAPI_RESET_STATUS_indication),
78 STR(UNIAPI_SETUP_request),
79 STR(UNIAPI_SETUP_indication),
80 STR(UNIAPI_SETUP_response),
81 STR(UNIAPI_SETUP_confirm),
82 STR(UNIAPI_SETUP_COMPLETE_indication),
83 STR(UNIAPI_SETUP_COMPLETE_request),
84 STR(UNIAPI_ALERTING_request),
85 STR(UNIAPI_ALERTING_indication),
86 STR(UNIAPI_PROCEEDING_request),
87 STR(UNIAPI_PROCEEDING_indication),
88 STR(UNIAPI_RELEASE_request),
89 STR(UNIAPI_RELEASE_indication),
90 STR(UNIAPI_RELEASE_response),
91 STR(UNIAPI_RELEASE_confirm),
92 STR(UNIAPI_NOTIFY_request),
93 STR(UNIAPI_NOTIFY_indication),
94 STR(UNIAPI_STATUS_indication),
95 STR(UNIAPI_STATUS_ENQUIRY_request),
96 STR(UNIAPI_ADD_PARTY_request),
97 STR(UNIAPI_ADD_PARTY_indication),
98 STR(UNIAPI_PARTY_ALERTING_request),
99 STR(UNIAPI_PARTY_ALERTING_indication),
100 STR(UNIAPI_ADD_PARTY_ACK_request),
101 STR(UNIAPI_ADD_PARTY_ACK_indication),
102 STR(UNIAPI_ADD_PARTY_REJ_request),
103 STR(UNIAPI_ADD_PARTY_REJ_indication),
104 STR(UNIAPI_DROP_PARTY_request),
105 STR(UNIAPI_DROP_PARTY_indication),
106 STR(UNIAPI_DROP_PARTY_ACK_request),
107 STR(UNIAPI_DROP_PARTY_ACK_indication),
108 STR(UNIAPI_ABORT_CALL_request),
111 static const char *verb_names[] = {
112 # define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D,
114 # undef UNI_DEBUG_DEFINE
118 uni_facname(enum uni_verb fac)
122 if (fac >= UNI_MAXFACILITY) {
123 sprintf(buf, "FAC%u", fac);
126 return (verb_names[fac]);
130 uni_signame(enum uni_sig sig)
134 if (sig >= UNIAPI_MAXSIG) {
135 sprintf(buf, "UNIAPI_SIG%u", sig);
138 return (sig_names[sig]);
142 uni_context(struct uni *uni)
148 uni_init(struct uni *uni)
151 uni->cref_alloc = 12;
152 uni->custat = CU_STAT0;
153 uni->glob_start = UNI_CALLSTATE_REST0;
154 uni->glob_respond = UNI_CALLSTATE_REST0;
158 uni_stop(struct uni *uni)
162 while ((c = TAILQ_FIRST(&uni->calls)) != NULL) {
163 TAILQ_REMOVE(&uni->calls, c, link);
164 uni_destroy_call(c, 1);
167 SIGQ_CLEAR(&uni->workq);
168 SIGQ_CLEAR(&uni->delq);
175 uni_create(void *arg, const struct uni_funcs *funcs)
179 if ((uni = INS_ALLOC()) == NULL)
186 uni->proto = UNIPROTO_UNI40U;
188 TAILQ_INIT(&uni->workq);
189 TAILQ_INIT(&uni->delq);
190 TIMER_INIT_UNI(uni, t309);
191 uni->timer309 = UNI_T309_DEFAULT;
192 TAILQ_INIT(&uni->calls);
193 uni_initcx(&uni->cx);
194 TIMER_INIT_UNI(uni, t317);
195 TIMER_INIT_UNI(uni, t316);
197 uni->timer301 = UNI_T301_DEFAULT;
198 uni->init303 = UNI_T303_CNT_DEFAULT;
199 uni->timer303 = UNI_T303_DEFAULT;
200 uni->init308 = UNI_T308_CNT_DEFAULT;
201 uni->timer308 = UNI_T308_DEFAULT;
202 uni->timer310 = UNI_T310U_DEFAULT;
203 uni->timer313 = UNI_T313_DEFAULT;
204 uni->init316 = UNI_T316_CNT_DEFAULT;
205 uni->timer316 = UNI_T316_DEFAULT;
206 uni->timer317 = UNI_T317_DEFAULT;
207 uni->timer322 = UNI_T322_DEFAULT;
208 uni->init322 = UNI_T322_CNT_DEFAULT;
209 uni->timer397 = UNI_T397_DEFAULT;
210 uni->timer398 = UNI_T398_DEFAULT;
211 uni->timer399 = UNI_T399U_DEFAULT;
217 uni_destroy(struct uni *uni)
221 TIMER_DESTROY_UNI(uni, t309);
222 TIMER_DESTROY_UNI(uni, t316);
223 TIMER_DESTROY_UNI(uni, t317);
229 uni_reset(struct uni *uni)
237 * DISPATCH SSCOP SIGNAL
240 uni_saal_input(struct uni *uni, enum saal_sig sig, struct uni_msg *m)
244 case SAAL_ESTABLISH_indication:
247 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_indication, 0, NULL);
250 case SAAL_ESTABLISH_confirm:
253 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_confirm, 0, NULL);
256 case SAAL_RELEASE_confirm:
259 uni_enq_coord(uni, SIGO_SAAL_RELEASE_confirm, 0, NULL);
262 case SAAL_RELEASE_indication:
265 uni_enq_coord(uni, SIGO_SAAL_RELEASE_indication, 0, NULL);
268 case SAAL_DATA_indication:
269 uni_enq_coord(uni, SIGO_SAAL_DATA_indication, 0, m);
272 case SAAL_UDATA_indication:
273 uni_enq_coord(uni, SIGO_SAAL_UDATA_indication, 0, m);
277 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus saal signal %u", sig);
294 { "LINK-ESTABLISH.request", UNIAPI_LINK_ESTABLISH_request,
296 SIGO_LINK_ESTABLISH_request, UNIU | UNIN },
297 { "LINK-RELEASE.request", UNIAPI_LINK_RELEASE_request,
299 SIGO_LINK_RELEASE_request, UNIU | UNIN },
301 { "RESET.request", UNIAPI_RESET_request,
302 sizeof(struct uniapi_reset_request),
303 SIGO_RESET_request, UNIU | UNIN },
304 { "RESET-ERROR.response", UNIAPI_RESET_ERROR_response,
305 sizeof(struct uniapi_reset_error_response),
306 SIGO_RESET_ERROR_response, UNIU | UNIN },
307 { "RESET.response", UNIAPI_RESET_response,
308 sizeof(struct uniapi_reset_response),
309 SIGO_RESET_response, UNIU | UNIN },
311 { "SETUP.request", UNIAPI_SETUP_request,
312 sizeof(struct uniapi_setup_request),
313 SIGO_SETUP_request, UNIU | UNIN },
314 { "SETUP.response", UNIAPI_SETUP_response,
315 sizeof(struct uniapi_setup_response),
316 SIGO_SETUP_response, UNIU | UNIN },
317 { "SETUP-COMPLETE.request", UNIAPI_SETUP_COMPLETE_request,
318 sizeof(struct uniapi_setup_complete_request),
319 SIGO_SETUP_COMPLETE_request, UNIN },
320 { "PROCEEDING.request", UNIAPI_PROCEEDING_request,
321 sizeof(struct uniapi_proceeding_request),
322 SIGO_PROCEEDING_request, UNIU | UNIN },
323 { "ALERTING.request", UNIAPI_ALERTING_request,
324 sizeof(struct uniapi_alerting_request),
325 SIGO_ALERTING_request, UNIU | UNIN },
326 { "RELEASE.request", UNIAPI_RELEASE_request,
327 sizeof(struct uniapi_release_request),
328 SIGO_RELEASE_request, UNIU | UNIN },
329 { "RELEASE.response", UNIAPI_RELEASE_response,
330 sizeof(struct uniapi_release_response),
331 SIGO_RELEASE_response, UNIU | UNIN },
332 { "NOTIFY.request", UNIAPI_NOTIFY_request,
333 sizeof(struct uniapi_notify_request),
334 SIGO_NOTIFY_request, UNIU | UNIN },
335 { "STATUS-ENQUIRY.request", UNIAPI_STATUS_ENQUIRY_request,
336 sizeof(struct uniapi_status_enquiry_request),
337 SIGO_STATUS_ENQUIRY_request, UNIU | UNIN },
339 { "ADD-PARTY.request", UNIAPI_ADD_PARTY_request,
340 sizeof(struct uniapi_add_party_request),
341 SIGO_ADD_PARTY_request, UNIU | UNIN },
342 { "ADD-PARTY-ACK.request", UNIAPI_ADD_PARTY_ACK_request,
343 sizeof(struct uniapi_add_party_ack_request),
344 SIGO_ADD_PARTY_ACK_request, UNIU | UNIN },
345 { "ADD-PARTY-REJ.request", UNIAPI_ADD_PARTY_REJ_request,
346 sizeof(struct uniapi_add_party_rej_request),
347 SIGO_ADD_PARTY_REJ_request, UNIU | UNIN },
348 { "PARTY-ALERTING.request", UNIAPI_PARTY_ALERTING_request,
349 sizeof(struct uniapi_party_alerting_request),
350 SIGO_PARTY_ALERTING_request, UNIU | UNIN },
351 { "DROP-PARTY.request", UNIAPI_DROP_PARTY_request,
352 sizeof(struct uniapi_drop_party_request),
353 SIGO_DROP_PARTY_request, UNIU | UNIN },
354 { "DROP-PARTY-ACK.request", UNIAPI_DROP_PARTY_ACK_request,
355 sizeof(struct uniapi_drop_party_ack_request),
356 SIGO_DROP_PARTY_ACK_request, UNIU | UNIN },
358 { "ABORT-CALL.request", UNIAPI_ABORT_CALL_request,
359 sizeof(struct uniapi_abort_call_request),
360 SIGO_ABORT_CALL_request, UNIU | UNIN },
366 uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie,
371 for (i = 0; maptab[i].name != NULL; i++) {
372 if (maptab[i].sig == sig) {
373 if (uni->proto == UNIPROTO_UNI40U) {
374 if (!(maptab[i].proto & UNIU))
375 uniapi_uni_error(uni,
376 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
377 } else if(uni->proto == UNIPROTO_UNI40N) {
378 if (!(maptab[i].proto & UNIN))
379 uniapi_uni_error(uni,
380 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
381 } else if(uni->proto == UNIPROTO_PNNI10) {
382 if (!(maptab[i].proto & PNNI))
383 uniapi_uni_error(uni,
384 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
386 uniapi_uni_error(uni,
387 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
389 if (uni_msg_len(m) != maptab[i].arglen) {
390 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus data in %s"
391 " (expecting %zu, got %zu)", maptab[i].name,
392 maptab[i].arglen, uni_msg_len(m));
394 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_ARG,
398 if (maptab[i].arglen == 0) {
402 VERBOSE(uni, UNI_FAC_API, 1, "got signal %s - "
403 "delivering to Coord", maptab[i].name);
404 uni_enq_coord(uni, maptab[i].coord_sig, cookie, m);
408 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus uni signal %u", sig);
410 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
416 /**************************************************************/
419 uni_work(struct uni *uni)
427 while ((s = TAILQ_FIRST(&uni->workq)) != NULL) {
428 TAILQ_REMOVE(&uni->workq, s, link);
432 uni_sig_coord(uni, s->sig, s->cookie, s->msg);
435 case SIG_RESET_START:
436 uni_sig_start(uni, s->sig, s->cookie, s->msg, s->u);
440 uni_sig_respond(uni, s->sig, s->cookie, s->msg, s->u);
444 uni_sig_call(s->call, s->sig, s->cookie, s->msg, s->u);
448 uni_sig_party(s->party, s->sig, s->cookie, s->msg, s->u);
452 ASSERT(0, ("bad signal type"));
461 * Enqueue a signal in the working queue
464 uni_enq_sig(struct uni *uni, u_int type, struct call *call,
465 struct party *party, uint32_t sig, uint32_t cookie,
466 struct uni_msg *msg, struct uni_all *u)
470 if ((s = SIG_ALLOC()) != NULL) {
478 TAILQ_INSERT_TAIL(&uni->workq, s, link);
483 * Enqueue a signal in the delayed queue
486 uni_delenq_sig(struct uni *uni, u_int type, struct call *call,
487 struct party *party, uint32_t sig, uint32_t cookie,
488 struct uni_msg *msg, struct uni_all *u)
492 if ((s = SIG_ALLOC()) != NULL) {
500 TAILQ_INSERT_TAIL(&uni->delq, s, link);
504 /**************************************************************/
507 uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie,
510 struct uni_msg *resp;
511 struct uniapi_error *err;
516 resp = uni_msg_alloc(sizeof(struct uniapi_error));
517 err = uni_msg_wptr(resp, struct uniapi_error *);
518 resp->b_wptr += sizeof(struct uniapi_error);
520 err->reason = reason;
523 uni->funcs->uni_output(uni, uni->arg, UNIAPI_ERROR, cookie, resp);
527 uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie)
529 uniapi_uni_error(c->uni, reason, cookie, callstates[c->cstate].ext);
532 uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie)
534 uniapi_uni_error(p->call->uni, reason, cookie,
535 callstates[p->call->cstate].ext);
538 /**************************************************************/
540 uni_status(struct uni *uni, void *arg)
542 uni->funcs->status(uni, uni->arg, arg,
543 "working: %s\n", uni->working ? "yes" : "no");
544 uni->funcs->status(uni, uni->arg, arg,
545 "work queue: %sempty\n", TAILQ_EMPTY(&uni->workq)? "" : "not ");
546 uni->funcs->status(uni, uni->arg, arg,
547 "delayed work queue: %sempty\n",
548 TAILQ_EMPTY(&uni->delq)? "" : "not ");
549 uni->funcs->status(uni, uni->arg, arg,
550 "coordinator: %s\n", custat_names[uni->custat]);
551 uni->funcs->status(uni, uni->arg, arg,
552 "reset-start: %s\n", globstat_names[uni->glob_start]);
553 uni->funcs->status(uni, uni->arg, arg,
554 "reset-respond: %s\n", globstat_names[uni->glob_respond]);
558 uni_undel(struct uni *uni, int (*filter)(struct sig *, void *), void *arg)
560 struct sigqueue newq;
563 if (TAILQ_EMPTY(&uni->delq))
568 s = TAILQ_FIRST(&uni->delq);
570 s1 = TAILQ_NEXT(s, link);
571 if ((*filter)(s, arg)) {
572 TAILQ_REMOVE(&uni->delq, s, link);
573 TAILQ_INSERT_TAIL(&uni->workq, s, link);
580 uni_delsig(struct uni *uni, u_int type, struct call *c, struct party *p)
584 s = TAILQ_FIRST(&uni->workq);
586 s1 = TAILQ_NEXT(s, link);
587 if ((type == SIG_CALL && s->type == SIG_CALL &&
589 (type == SIG_PARTY && s->type == SIG_PARTY &&
590 s->call == c && s->party == p)) {
591 TAILQ_REMOVE(&uni->workq, s, link);
593 uni_msg_destroy(s->msg);
601 s = TAILQ_FIRST(&uni->delq);
603 s1 = TAILQ_NEXT(s, link);
604 if ((type == SIG_CALL && s->type == SIG_CALL &&
606 (type == SIG_PARTY && s->type == SIG_PARTY &&
607 s->call == c && s->party == p)) {
608 TAILQ_REMOVE(&uni->delq, s, link);
610 uni_msg_destroy(s->msg);
619 /**************************************************************/
622 uni_get_config(const struct uni *uni, struct uni_config *config)
624 config->proto = uni->proto;
628 config->popt |= UNIPROTO_GFP;
631 if (uni->cx.git_hard)
632 config->option |= UNIOPT_GIT_HARD;
633 if (uni->cx.bearer_hard)
634 config->option |= UNIOPT_BEARER_HARD;
635 if (uni->cx.cause_hard)
636 config->option |= UNIOPT_CAUSE_HARD;
638 config->popt |= UNIPROTO_SB_TB;
640 config->timer301 = uni->timer301;
641 config->timer303 = uni->timer303;
642 config->init303 = uni->init303;
643 config->timer308 = uni->timer308;
644 config->init308 = uni->init308;
645 config->timer309 = uni->timer309;
646 config->timer310 = uni->timer310;
647 config->timer313 = uni->timer313;
648 config->timer316 = uni->timer316;
649 config->init316 = uni->init316;
650 config->timer317 = uni->timer317;
651 config->timer322 = uni->timer322;
652 config->init322 = uni->init322;
653 config->timer397 = uni->timer397;
654 config->timer398 = uni->timer398;
655 config->timer399 = uni->timer399;
659 uni_set_config(struct uni *uni, const struct uni_config *config,
660 uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask)
664 idle = TAILQ_EMPTY(&uni->calls) &&
665 TAILQ_EMPTY(&uni->workq) &&
666 TAILQ_EMPTY(&uni->delq);
668 if ((*mask & UNICFG_PROTO) && idle) {
669 switch (config->proto) {
671 case UNIPROTO_UNI40U:
672 case UNIPROTO_UNI40N:
673 /* case UNIPROTO_PNNI10: XXX */
674 uni->proto = config->proto;
675 *mask &= ~UNICFG_PROTO;
679 if (*popt_mask & UNIPROTO_GFP) {
680 if (config->popt & UNIPROTO_GFP) {
682 *popt_mask &= ~UNIPROTO_GFP;
684 if (!uni->cx.q2932 || idle) {
686 *popt_mask &= ~UNIPROTO_GFP;
690 if (*popt_mask & UNIPROTO_SB_TB) {
691 uni->sb_tb = ((config->popt & UNIPROTO_SB_TB) != 0);
692 *popt_mask &= ~UNIPROTO_SB_TB;
694 if (*opt_mask & UNIOPT_GIT_HARD) {
695 uni->cx.git_hard = ((config->option & UNIOPT_GIT_HARD) != 0);
696 *opt_mask &= ~UNIOPT_GIT_HARD;
698 if (*opt_mask & UNIOPT_BEARER_HARD) {
699 uni->cx.bearer_hard = ((config->option & UNIOPT_BEARER_HARD) != 0);
700 *opt_mask &= ~UNIOPT_BEARER_HARD;
702 if (*opt_mask & UNIOPT_CAUSE_HARD) {
703 uni->cx.cause_hard = ((config->option & UNIOPT_CAUSE_HARD) != 0);
704 *opt_mask &= ~UNIOPT_CAUSE_HARD;
707 #define SET_TIMER(NAME,name) \
708 if (*mask & UNICFG_##NAME) { \
709 uni->name = config->name; \
710 *mask &= ~UNICFG_##NAME; \
713 SET_TIMER(TIMER301, timer301);
714 SET_TIMER(TIMER303, timer303);
715 SET_TIMER(INIT303, init303);
716 SET_TIMER(TIMER308, timer308);
717 SET_TIMER(INIT308, init308);
718 SET_TIMER(TIMER309, timer309);
719 SET_TIMER(TIMER310, timer310);
720 SET_TIMER(TIMER313, timer313);
721 SET_TIMER(TIMER316, timer316);
722 SET_TIMER(INIT316, init316);
723 SET_TIMER(TIMER317, timer317);
724 SET_TIMER(TIMER322, timer322);
725 SET_TIMER(INIT322, init322);
726 SET_TIMER(TIMER397, timer397);
727 SET_TIMER(TIMER398, timer398);
728 SET_TIMER(TIMER399, timer399);
734 uni_set_debug(struct uni *uni, enum uni_verb fac, u_int level)
736 uni->debug[fac] = level;
740 uni_get_debug(const struct uni *uni, enum uni_verb fac)
742 return (uni->debug[fac]);
746 uni_getcustate(const struct uni *uni)
748 return (uni->custat);