]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ngatm/netnatm/sig/sig_uni.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ngatm / netnatm / sig / sig_uni.c
1 /*
2  * Copyright (c) 1996-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  *
29  * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
30  *
31  * Instance handling
32  */
33
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>
41
42 #include <netnatm/sig/unipriv.h>
43
44 #ifdef UNICORE
45 UNICORE
46 #endif
47
48 #define STR(S) [S] = #S
49 static const char *custat_names[] = {
50         STR(CU_STAT0),
51         STR(CU_STAT1),
52         STR(CU_STAT2),
53         STR(CU_STAT3),
54 };
55 static const char *globstat_names[] = {
56         STR(UNI_CALLSTATE_REST0),
57         STR(UNI_CALLSTATE_REST1),
58         STR(UNI_CALLSTATE_REST2),
59 };
60
61 static const char *sig_names[] = {
62         STR(UNIAPI_ERROR),
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),
109 };
110
111 static const char *verb_names[] = {
112 # define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D,
113         UNI_DEBUG_FACILITIES
114 # undef UNI_DEBUG_DEFINE
115 };
116
117 const char *
118 uni_facname(enum uni_verb fac)
119 {
120         static char buf[40];
121
122         if (fac >= UNI_MAXFACILITY) {
123                 sprintf(buf, "FAC%u", fac);
124                 return (buf);
125         }
126         return (verb_names[fac]);
127 }
128
129 const char *
130 uni_signame(enum uni_sig sig)
131 {
132         static char buf[40];
133
134         if (sig >= UNIAPI_MAXSIG) {
135                 sprintf(buf, "UNIAPI_SIG%u", sig);
136                 return (buf);
137         }
138         return (sig_names[sig]);
139 }
140
141 struct unicx *
142 uni_context(struct uni *uni)
143 {
144         return (&uni->cx);
145 }
146
147 static void
148 uni_init(struct uni *uni)
149 {
150         uni->working = 0;
151         uni->cref_alloc = 12;
152         uni->custat = CU_STAT0;
153         uni->glob_start = UNI_CALLSTATE_REST0;
154         uni->glob_respond = UNI_CALLSTATE_REST0;
155 }
156
157 static void
158 uni_stop(struct uni *uni)
159 {
160         struct call *c;
161
162         while ((c = TAILQ_FIRST(&uni->calls)) != NULL) {
163                 TAILQ_REMOVE(&uni->calls, c, link);
164                 uni_destroy_call(c, 1);
165         }
166
167         SIGQ_CLEAR(&uni->workq);
168         SIGQ_CLEAR(&uni->delq);
169 }
170
171 /*
172  * INSTANCE HANDLING
173  */
174 struct uni *
175 uni_create(void *arg, const struct uni_funcs *funcs)
176 {
177         struct uni *uni;
178
179         if ((uni = INS_ALLOC()) == NULL)
180                 return (NULL);
181
182         uni_init(uni);
183
184         uni->funcs = funcs;
185         uni->arg = arg;
186         uni->proto = UNIPROTO_UNI40U;
187         uni->sb_tb = 0;
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);
196
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;
212
213         return (uni);
214 }
215
216 void 
217 uni_destroy(struct uni *uni)
218 {
219         uni_stop(uni);
220
221         TIMER_DESTROY_UNI(uni, t309);
222         TIMER_DESTROY_UNI(uni, t316);
223         TIMER_DESTROY_UNI(uni, t317);
224
225         INS_FREE(uni);
226 }
227
228 void
229 uni_reset(struct uni *uni)
230 {
231         uni_stop(uni);
232         uni_init(uni);
233 }
234
235
236 /*
237  * DISPATCH SSCOP SIGNAL
238  */
239 void
240 uni_saal_input(struct uni *uni, enum saal_sig sig, struct uni_msg *m)
241 {
242         switch (sig) {
243
244           case SAAL_ESTABLISH_indication:
245                 if (m != NULL)
246                         uni_msg_destroy(m);
247                 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_indication, 0, NULL);
248                 break;
249
250           case SAAL_ESTABLISH_confirm:
251                 if (m != NULL)
252                         uni_msg_destroy(m);
253                 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_confirm, 0, NULL);
254                 break;
255
256           case SAAL_RELEASE_confirm:
257                 if (m != NULL)
258                         uni_msg_destroy(m);
259                 uni_enq_coord(uni, SIGO_SAAL_RELEASE_confirm, 0, NULL);
260                 break;
261
262           case SAAL_RELEASE_indication:
263                 if (m != NULL)
264                         uni_msg_destroy(m);
265                 uni_enq_coord(uni, SIGO_SAAL_RELEASE_indication, 0, NULL);
266                 break;
267
268           case SAAL_DATA_indication:
269                 uni_enq_coord(uni, SIGO_SAAL_DATA_indication, 0, m);
270                 break;
271
272           case SAAL_UDATA_indication:
273                 uni_enq_coord(uni, SIGO_SAAL_UDATA_indication, 0, m);
274                 break;
275
276           default:
277                 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus saal signal %u", sig);
278                 if (m != NULL)
279                         uni_msg_destroy(m);
280                 break;
281         }
282 }
283
284 static struct {
285         const char      *name;
286         enum uni_sig    sig;
287         size_t          arglen;
288         u_int           coord_sig;
289         u_int           proto;
290 #define UNIU    0x01
291 #define UNIN    0x02
292 #define PNNI    0x04
293 } maptab[] = {
294         { "LINK-ESTABLISH.request", UNIAPI_LINK_ESTABLISH_request,
295             0,
296             SIGO_LINK_ESTABLISH_request, UNIU | UNIN },
297         { "LINK-RELEASE.request", UNIAPI_LINK_RELEASE_request,
298             0,
299             SIGO_LINK_RELEASE_request, UNIU | UNIN },
300
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 },
310
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 },
338
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 },
357
358         { "ABORT-CALL.request", UNIAPI_ABORT_CALL_request,
359             sizeof(struct uniapi_abort_call_request),
360             SIGO_ABORT_CALL_request, UNIU | UNIN },
361
362         { NULL, 0, 0, 0, 0 }
363 };
364
365 void
366 uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie,
367     struct uni_msg *m)
368 {
369         u_int i;
370
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);
385                         } else {
386                                 uniapi_uni_error(uni,
387                                     UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
388                         }
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));
393                                 uni_msg_destroy(m);
394                                 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_ARG,
395                                     cookie, 0);
396                                 return;
397                         }
398                         if (maptab[i].arglen == 0) {
399                                 uni_msg_destroy(m);
400                                 m = NULL;
401                         }
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);
405                         return;
406                 }
407         }
408         VERBOSE(uni, UNI_FAC_ERR, 1, "bogus uni signal %u", sig);
409         uni_msg_destroy(m);
410         uniapi_uni_error(uni, UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
411 }
412 #undef UNIU
413 #undef UNIN
414 #undef PNNI
415
416 /**************************************************************/
417
418 void
419 uni_work(struct uni *uni)
420 {
421         struct sig *s;
422
423         if (uni->working)
424                 return;
425         uni->working = 1;
426
427         while ((s = TAILQ_FIRST(&uni->workq)) != NULL) {
428                 TAILQ_REMOVE(&uni->workq, s, link);
429                 switch (s->type) {
430
431                   case SIG_COORD:
432                         uni_sig_coord(uni, s->sig, s->cookie, s->msg);
433                         break;
434
435                   case SIG_RESET_START:
436                         uni_sig_start(uni, s->sig, s->cookie, s->msg, s->u);
437                         break;
438
439                   case SIG_RESET_RESP:
440                         uni_sig_respond(uni, s->sig, s->cookie, s->msg, s->u);
441                         break;
442
443                   case SIG_CALL:
444                         uni_sig_call(s->call, s->sig, s->cookie, s->msg, s->u);
445                         break;
446
447                   case SIG_PARTY:
448                         uni_sig_party(s->party, s->sig, s->cookie, s->msg, s->u);
449                         break;
450
451                   default:
452                         ASSERT(0, ("bad signal type"));
453                 }
454                 SIG_FREE(s);
455         }
456
457         uni->working = 0;
458 }
459
460 /*
461  * Enqueue a signal in the working queue
462  */
463 void
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)
467 {
468         struct sig *s;
469
470         if ((s = SIG_ALLOC()) != NULL) {
471                 s->type = type;
472                 s->sig = sig;
473                 s->cookie = cookie;
474                 s->msg = msg;
475                 s->call = call;
476                 s->party = party;
477                 s->u = u;
478                 TAILQ_INSERT_TAIL(&uni->workq, s, link);
479         }
480 }
481
482 /*
483  * Enqueue a signal in the delayed queue
484  */
485 void
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)
489 {
490         struct sig *s;
491
492         if ((s = SIG_ALLOC()) != NULL) {
493                 s->type = type;
494                 s->sig = sig;
495                 s->cookie = cookie;
496                 s->msg = msg;
497                 s->call = call;
498                 s->party = party;
499                 s->u = u;
500                 TAILQ_INSERT_TAIL(&uni->delq, s, link);
501         }
502 }
503
504 /**************************************************************/
505
506 void
507 uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie,
508     uint32_t state)
509 {
510         struct uni_msg *resp;
511         struct uniapi_error *err;
512
513         if (cookie == 0)
514                 return;
515
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);
519
520         err->reason = reason;
521         err->state = state;
522
523         uni->funcs->uni_output(uni, uni->arg, UNIAPI_ERROR, cookie, resp);
524 }
525
526 void
527 uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie)
528 {
529         uniapi_uni_error(c->uni, reason, cookie, callstates[c->cstate].ext);
530 }
531 void
532 uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie)
533 {
534         uniapi_uni_error(p->call->uni, reason, cookie,
535             callstates[p->call->cstate].ext);
536 }
537
538 /**************************************************************/
539 void
540 uni_status(struct uni *uni, void *arg)
541 {
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]);
555 }
556
557 void
558 uni_undel(struct uni *uni, int (*filter)(struct sig *, void *), void *arg)
559 {
560         struct sigqueue         newq;
561         struct sig *s, *s1;
562
563         if (TAILQ_EMPTY(&uni->delq))
564                 return;
565
566         TAILQ_INIT(&newq);
567
568         s = TAILQ_FIRST(&uni->delq);
569         while (s != NULL) {
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);
574                 }
575                 s = s1;
576         }
577 }
578
579 void
580 uni_delsig(struct uni *uni, u_int type, struct call *c, struct party *p)
581 {
582         struct sig *s, *s1;
583
584         s = TAILQ_FIRST(&uni->workq);
585         while (s != NULL) {
586                 s1 = TAILQ_NEXT(s, link);
587                 if ((type == SIG_CALL && s->type == SIG_CALL &&
588                     s->call == c) ||
589                     (type == SIG_PARTY && s->type == SIG_PARTY &&
590                     s->call == c && s->party == p)) {
591                         TAILQ_REMOVE(&uni->workq, s, link);
592                         if (s->msg)
593                                 uni_msg_destroy(s->msg);
594                         if (s->u)
595                                 UNI_FREE(s->u);
596                         SIG_FREE(s);
597                 }
598                 s = s1;
599         }
600
601         s = TAILQ_FIRST(&uni->delq);
602         while (s != NULL) {
603                 s1 = TAILQ_NEXT(s, link);
604                 if ((type == SIG_CALL && s->type == SIG_CALL &&
605                     s->call == c) ||
606                     (type == SIG_PARTY && s->type == SIG_PARTY &&
607                     s->call == c && s->party == p)) {
608                         TAILQ_REMOVE(&uni->delq, s, link);
609                         if (s->msg)
610                                 uni_msg_destroy(s->msg);
611                         if (s->u)
612                                 UNI_FREE(s->u);
613                         SIG_FREE(s);                                            \
614                 }
615                 s = s1;
616         }
617 }
618
619 /**************************************************************/
620
621 void
622 uni_get_config(const struct uni *uni, struct uni_config *config)
623 {
624         config->proto = uni->proto;
625
626         config->popt = 0;
627         if (uni->cx.q2932)
628                 config->popt |= UNIPROTO_GFP;
629
630         config->option = 0;
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;
637         if (uni->sb_tb)
638                 config->popt |= UNIPROTO_SB_TB;
639
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;
656 }
657
658 void
659 uni_set_config(struct uni *uni, const struct uni_config *config,
660     uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask)
661 {
662         int idle;
663
664         idle = TAILQ_EMPTY(&uni->calls) &&
665             TAILQ_EMPTY(&uni->workq) &&
666             TAILQ_EMPTY(&uni->delq);
667
668         if ((*mask & UNICFG_PROTO) && idle) {
669                 switch (config->proto) {
670
671                   case UNIPROTO_UNI40U:
672                   case UNIPROTO_UNI40N:
673                   /* case UNIPROTO_PNNI10: XXX */
674                         uni->proto = config->proto;
675                         *mask &= ~UNICFG_PROTO;
676                         break;
677                 }
678         }
679         if (*popt_mask & UNIPROTO_GFP) {
680                 if (config->popt & UNIPROTO_GFP) {
681                         uni->cx.q2932 = 1;
682                         *popt_mask &= ~UNIPROTO_GFP;
683                 } else {
684                         if (!uni->cx.q2932 || idle) {
685                                 uni->cx.q2932 = 0;
686                                 *popt_mask &= ~UNIPROTO_GFP;
687                         }
688                 }
689         }
690         if (*popt_mask & UNIPROTO_SB_TB) {
691                 uni->sb_tb = ((config->popt & UNIPROTO_SB_TB) != 0);
692                 *popt_mask &= ~UNIPROTO_SB_TB;
693         }
694         if (*opt_mask & UNIOPT_GIT_HARD) {
695                 uni->cx.git_hard = ((config->option & UNIOPT_GIT_HARD) != 0);
696                 *opt_mask &= ~UNIOPT_GIT_HARD;
697         }
698         if (*opt_mask & UNIOPT_BEARER_HARD) {
699                 uni->cx.bearer_hard = ((config->option & UNIOPT_BEARER_HARD) != 0);
700                 *opt_mask &= ~UNIOPT_BEARER_HARD;
701         }
702         if (*opt_mask & UNIOPT_CAUSE_HARD) {
703                 uni->cx.cause_hard = ((config->option & UNIOPT_CAUSE_HARD) != 0);
704                 *opt_mask &= ~UNIOPT_CAUSE_HARD;
705         }
706
707 #define SET_TIMER(NAME,name)                                            \
708         if (*mask & UNICFG_##NAME) {                                    \
709                 uni->name = config->name;                               \
710                 *mask &= ~UNICFG_##NAME;                                \
711         }
712
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);
729
730 #undef SET_TIMER
731 }
732
733 void
734 uni_set_debug(struct uni *uni, enum uni_verb fac, u_int level)
735 {
736         uni->debug[fac] = level;
737 }
738
739 u_int
740 uni_get_debug(const struct uni *uni, enum uni_verb fac)
741 {
742         return (uni->debug[fac]);
743 }
744
745 u_int
746 uni_getcustate(const struct uni *uni)
747 {
748         return (uni->custat);
749 }