1 /*
2 * Copyright (c) 2003-2004
3 * Hartmut Brandt
4 * All rights reserved.
5 *
6 * Copyright (c) 2001-2002
7 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
8 * All rights reserved.
9 *
10 * Author: Harti Brandt <harti@freebsd.org>
11 *
12 * Redistribution of this software and documentation and use in source and
13 * binary forms, with or without modification, are permitted provided that
14 * the following conditions are met:
15 *
16 * 1. Redistributions of source code or documentation must retain the above
17 * copyright notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
23 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
25 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
26 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
29 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $Begemot: libunimsg/netnatm/api/cc_user.c,v 1.3 2004/07/16 18:46:55 brandt Exp $
35 *
36 * ATM API as defined per af-saa-0108
37 *
38 * User side (upper half)
39 */
40
41 #include <netnatm/unimsg.h>
42 #include <netnatm/msg/unistruct.h>
43 #include <netnatm/msg/unimsglib.h>
44 #include <netnatm/api/unisap.h>
45 #include <netnatm/sig/unidef.h>
46 #include <netnatm/api/atmapi.h>
47 #include <netnatm/api/ccatm.h>
48 #include <netnatm/api/ccpriv.h>
49
50 /*
51 * This file handles messages to a USER.
52 */
53 static const char *stab[] = {
54 #define DEF(N) [N] = #N,
55 USER_STATES
56 #undef DEF
57 };
58
59 const char *
60 cc_user_state2str(u_int s)
61 {
62 if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL)
63 return ("?");
64 return (stab[s]);
65 }
66
67 static __inline void
68 set_state(struct ccuser *user, enum user_state ns)
69 {
70 if (user->state != ns) {
71 if (user->cc->log & CCLOG_USER_STATE)
72 cc_user_log(user, "%s -> %s",
73 stab[user->state], stab[ns]);
74 user->state = ns;
75 }
76 }
77
78 static __inline void
79 cc_user_send(struct ccuser *user, u_int op, void *arg, size_t len)
80 {
81 user->cc->funcs->send_user(user, user->uarg, op, arg, len);
82 }
83
84 static __inline void
85 cc_user_ok(struct ccuser *user, u_int data, void *arg, size_t len)
86 {
87 user->cc->funcs->respond_user(user, user->uarg,
88 ATMERR_OK, data, arg, len);
89 }
90
91 static __inline void
92 cc_user_err(struct ccuser *user, int err)
93 {
94 user->cc->funcs->respond_user(user, user->uarg,
95 err, ATMRESP_NONE, NULL, 0);
96 }
97
98
99 /**********************************************************************
100 *
101 * INSTANCE MANAGEMENT
102 */
103 /*
104 * New endpoint created
105 */
106 struct ccuser *
107 cc_user_create(struct ccdata *cc, void *uarg, const char *name)
108 {
109 struct ccuser *user;
110
111 user = CCZALLOC(sizeof(*user));
112 if (user == NULL)
113 return (NULL);
114
115 user->cc = cc;
116 user->state = USER_NULL;
117 user->uarg = uarg;
118 strncpy(user->name, name, sizeof(user->name));
119 user->name[sizeof(user->name) - 1] = '\0';
120 TAILQ_INIT(&user->connq);
121 LIST_INSERT_HEAD(&cc->user_list, user, node_link);
122
123 if (user->cc->log & CCLOG_USER_INST)
124 cc_user_log(user, "created with name '%s'", name);
125
126 return (user);
127 }
128
129 /*
130 * Reset a user instance
131 */
132 static void
133 cc_user_reset(struct ccuser *user)
134 {
135
136 CCASSERT(TAILQ_EMPTY(&user->connq), ("connq not empty"));
137
138 if (user->sap != NULL) {
139 CCFREE(user->sap);
140 user->sap = NULL;
141 }
142
143 if (user->accepted != NULL) {
144 user->accepted->acceptor = NULL;
145 user->accepted = NULL;
146 }
147 user->config = USER_P2P;
148 user->queue_act = 0;
149 user->queue_max = 0;
150 user->aborted = 0;
151
152 set_state(user, USER_NULL);
153
154 cc_user_sig_flush(user);
155 }
156
157 static void
158 cc_user_abort(struct ccuser *user, const struct uni_ie_cause *cause)
159 {
160 struct ccconn *conn;
161
162 /*
163 * Although the standard state that 'all connections
164 * associated with this endpoint are aborted' we only
165 * have to abort the head one, because in state A6
166 * (call present) the endpoint is only associated to the
167 * head connection - the others are 'somewhere else' and
168 * need to be redispatched.
169 *
170 * First bring user into a state that the connections
171 * are not dispatched back to it.
172 */
173 set_state(user, USER_NULL);
174 if (!user->aborted) {
175 if ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
176 memset(conn->cause, 0, sizeof(conn->cause));
177 if (cause != NULL)
178 conn->cause[0] = *cause;
179 cc_conn_reset_acceptor(conn);
180 cc_disconnect_from_user(conn);
181 cc_conn_sig(conn, CONN_SIG_USER_ABORT, NULL);
182 }
183 }
184
185 while ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
186 /* these should be in C21 */
187 cc_disconnect_from_user(conn);
188 cc_conn_dispatch(conn);
189 }
190
191 cc_user_reset(user);
192 }
193
194 /*
195 * Application has closed this endpoint. Clean up all user resources and
196 * abort all connections. This can be called in any state.
197 */
198 void
199 cc_user_destroy(struct ccuser *user)
200 {
201
202 if (user->cc->log & CCLOG_USER_INST)
203 cc_user_log(user, "destroy '%s'", user->name);
204
205 cc_user_abort(user, NULL);
206
207 if (user->sap != NULL)
208 CCFREE(user->sap);
209
210 cc_user_sig_flush(user);
211
212 LIST_REMOVE(user, node_link);
213 CCFREE(user);
214 }
215
216 /**********************************************************************
217 *
218 * OUTGOING CALLS
219 */
220 /*
221 * Return true when the calling address of the connection matches the address.
222 */
223 static int
224 addr_matches(const struct ccaddr *addr, const struct ccconn *conn)
225 {
226
227 if (!IE_ISPRESENT(conn->calling))
228 return (0);
229
230 return (addr->addr.type == conn->calling.addr.type &&
231 addr->addr.plan == conn->calling.addr.plan &&
232 addr->addr.len == conn->calling.addr.len &&
233 memcmp(addr->addr.addr, conn->calling.addr.addr,
234 addr->addr.len) == 0);
235 }
236
237 /*
238 * Check if the user's SAP (given he is in the right state) and
239 * the given SAP overlap
240 */
241 static int
242 check_overlap(struct ccuser *user, struct uni_sap *sap)
243 {
244 return ((user->state == USER_IN_PREPARING ||
245 user->state == USER_IN_WAITING) &&
246 unisve_overlap_sap(user->sap, sap));
247 }
248
249 /*
250 * Send arrival notification to user
251 */
252 static void
253 do_arrival(struct ccuser *user)
254 {
255 struct ccconn *conn;
256
257 user->aborted = 0;
258 if ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
259 set_state(user, USER_IN_ARRIVED);
260 cc_user_send(user, ATMOP_ARRIVAL_OF_INCOMING_CALL, NULL, 0);
261 cc_conn_sig(conn, CONN_SIG_ARRIVAL, NULL);
262 }
263 }
264
265 /**********************************************************************
266 *
267 * ATTRIBUTES
268 */
269 /*
270 * Query an attribute. This is possible only in some states: preparation
271 * of an outgoing call, after an incoming call was offered to the application
272 * and in the three active states (P2P, P2PLeaf, P2PRoot).
273 */
274 static struct ccconn *
275 cc_query_check(struct ccuser *user)
276 {
277
278 switch (user->state) {
279
280 case USER_OUT_PREPARING:
281 case USER_IN_ARRIVED:
282 case USER_ACTIVE:
283 return (TAILQ_FIRST(&user->connq));
284
285 case USER_NULL:
286 /* if we are waiting for the SETUP_confirm, we are in
287 * the NULL state still (we are the new endpoint), but
288 * have a connection in 'accepted' that is in the
289 * CONN_IN_WAIT_ACCEPT_OK state.
290 */
291 if (user->accepted != NULL &&
292 user->accepted->state == CONN_IN_WAIT_ACCEPT_OK)
293 return (user->accepted);
294 /* FALLTHRU */
295
296 default:
297 return (NULL);
298 }
299 }
300
301 /*
302 * Query attributes
303 */
304 static void
305 cc_attr_query(struct ccuser *user, struct ccconn *conn,
306 uint32_t *attr, u_int count)
307 {
308 void *val, *ptr;
309 size_t total, len;
310 u_int i;
311 uint32_t *atab;
312
313 /* determine the length of the total attribute buffer */
314 total = sizeof(uint32_t) + count * sizeof(uint32_t);
315 for (i = 0; i < count; i++) {
316 len = 0;
317 switch ((enum atm_attribute)attr[i]) {
318
319 case ATM_ATTR_NONE:
320 break;
321
322 case ATM_ATTR_BLLI_SELECTOR:
323 len = sizeof(uint32_t);
324 break;
325
326 case ATM_ATTR_BLLI:
327 len = sizeof(struct uni_ie_blli);
328 break;
329
330 case ATM_ATTR_BEARER:
331 len = sizeof(struct uni_ie_bearer);
332 break;
333
334 case ATM_ATTR_TRAFFIC:
335 len = sizeof(struct uni_ie_traffic);
336 break;
337
338 case ATM_ATTR_QOS:
339 len = sizeof(struct uni_ie_qos);
340 break;
341
342 case ATM_ATTR_EXQOS:
343 len = sizeof(struct uni_ie_exqos);
344 break;
345
346 case ATM_ATTR_CALLED:
347 len = sizeof(struct uni_ie_called);
348 break;
349
350 case ATM_ATTR_CALLEDSUB:
351 len = sizeof(struct uni_ie_calledsub);
352 break;
353
354 case ATM_ATTR_CALLING:
355 len = sizeof(struct uni_ie_calling);
356 break;
357
358 case ATM_ATTR_CALLINGSUB:
359 len = sizeof(struct uni_ie_callingsub);
360 break;
361
362 case ATM_ATTR_AAL:
363 len = sizeof(struct uni_ie_aal);
364 break;
365
366 case ATM_ATTR_EPREF:
367 len = sizeof(struct uni_ie_epref);
368 break;
369
370 case ATM_ATTR_CONNED:
371 len = sizeof(struct uni_ie_conned);
372 break;
373
374 case ATM_ATTR_CONNEDSUB:
375 len = sizeof(struct uni_ie_connedsub);
376 break;
377
378 case ATM_ATTR_EETD:
379 len = sizeof(struct uni_ie_eetd);
380 break;
381
382 case ATM_ATTR_ABRSETUP:
383 len = sizeof(struct uni_ie_abrsetup);
384 break;
385
386 case ATM_ATTR_ABRADD:
387 len = sizeof(struct uni_ie_abradd);
388 break;
389
390 case ATM_ATTR_CONNID:
391 len = sizeof(struct uni_ie_connid);
392 break;
393
394 case ATM_ATTR_MDCR:
395 len = sizeof(struct uni_ie_mdcr);
396 break;
397 }
398 if (len == 0) {
399 cc_user_err(user, ATMERR_BAD_ATTR);
400 return;
401 }
402 total += len;
403 }
404
405 /* allocate buffer */
406 val = CCMALLOC(total);
407 if (val == NULL)
408 return;
409
410 atab = val;
411 atab[0] = count;
412
413 /* fill */
414 ptr = (u_char *)val + (sizeof(uint32_t) + count * sizeof(uint32_t));
415 for (i = 0; i < count; i++) {
416 len = 0;
417 atab[i + 1] = attr[i];
418 switch (attr[i]) {
419
420 case ATM_ATTR_NONE:
421 break;
422
423 case ATM_ATTR_BLLI_SELECTOR:
424 len = sizeof(uint32_t);
425 memcpy(ptr, &conn->blli_selector, len);
426 break;
427
428 case ATM_ATTR_BLLI:
429 /* in A6 the blli_selector may be 0 when
430 * there was no blli in the SETUP.
431 */
432 len = sizeof(struct uni_ie_blli);
433 if (conn->blli_selector == 0)
434 memset(ptr, 0, len);
435 else
436 memcpy(ptr, &conn->blli[conn->blli_selector -
437 1], len);
438 break;
439
440 case ATM_ATTR_BEARER:
441 len = sizeof(struct uni_ie_bearer);
442 memcpy(ptr, &conn->bearer, len);
443 break;
444
445 case ATM_ATTR_TRAFFIC:
446 len = sizeof(struct uni_ie_traffic);
447 memcpy(ptr, &conn->traffic, len);
448 break;
449
450 case ATM_ATTR_QOS:
451 len = sizeof(struct uni_ie_qos);
452 memcpy(ptr, &conn->qos, len);
453 break;
454
455 case ATM_ATTR_EXQOS:
456 len = sizeof(struct uni_ie_exqos);
457 memcpy(ptr, &conn->exqos, len);
458 break;
459
460 case ATM_ATTR_CALLED:
461 len = sizeof(struct uni_ie_called);
462 memcpy(ptr, &conn->called, len);
463 break;
464
465 case ATM_ATTR_CALLEDSUB:
466 len = sizeof(struct uni_ie_calledsub);
467 memcpy(ptr, &conn->calledsub, len);
468 break;
469
470 case ATM_ATTR_CALLING:
471 len = sizeof(struct uni_ie_calling);
472 memcpy(ptr, &conn->calling, len);
473 break;
474
475 case ATM_ATTR_CALLINGSUB:
476 len = sizeof(struct uni_ie_callingsub);
477 memcpy(ptr, &conn->callingsub, len);
478 break;
479
480 case ATM_ATTR_AAL:
481 len = sizeof(struct uni_ie_aal);
482 memcpy(ptr, &conn->aal, len);
483 break;
484
485 case ATM_ATTR_EPREF:
486 len = sizeof(struct uni_ie_epref);
487 memcpy(ptr, &conn->epref, len);
488 break;
489
490 case ATM_ATTR_CONNED:
491 len = sizeof(struct uni_ie_conned);
492 memcpy(ptr, &conn->conned, len);
493 break;
494
495 case ATM_ATTR_CONNEDSUB:
496 len = sizeof(struct uni_ie_connedsub);
497 memcpy(ptr, &conn->connedsub, len);
498 break;
499
500 case ATM_ATTR_EETD:
501 len = sizeof(struct uni_ie_eetd);
502 memcpy(ptr, &conn->eetd, len);
503 break;
504
505 case ATM_ATTR_ABRSETUP:
506 len = sizeof(struct uni_ie_abrsetup);
507 memcpy(ptr, &conn->abrsetup, len);
508 break;
509
510 case ATM_ATTR_ABRADD:
511 len = sizeof(struct uni_ie_abradd);
512 memcpy(ptr, &conn->abradd, len);
513 break;
514
515 case ATM_ATTR_CONNID:
516 len = sizeof(struct uni_ie_connid);
517 memcpy(ptr, &conn->connid, len);
518 break;
519
520 case ATM_ATTR_MDCR:
521 len = sizeof(struct uni_ie_mdcr);
522 memcpy(ptr, &conn->mdcr, len);
523 break;
524 }
525 ptr = (u_char *)ptr + len;
526 }
527
528 cc_user_ok(user, ATMRESP_ATTRS, val, total);
529
530 CCFREE(val);
531 }
532
533 /*
534 * Check whether the state is ok and return the connection
535 */
536 static struct ccconn *
537 cc_set_check(struct ccuser *user)
538 {
539 switch(user->state) {
540
541 case USER_OUT_PREPARING:
542 case USER_IN_ARRIVED:
543 return (TAILQ_FIRST(&user->connq));
544
545 default:
546 return (NULL);
547 }
548 }
549
550 /*
551 * Set connection attribute(s)
552 */
553 static void
554 cc_attr_set(struct ccuser *user, struct ccconn *conn, uint32_t *attr,
555 u_int count, u_char *val, size_t vallen)
556 {
557 size_t total, len;
558 u_int i;
559 u_char *ptr;
560
561 /* determine the length of the total attribute buffer */
562 total = 0;
563 ptr = val;
564 for (i = 0; i < count; i++) {
565 len = 0;
566 switch ((enum atm_attribute)attr[i]) {
567
568 case ATM_ATTR_NONE:
569 break;
570
571 case ATM_ATTR_BLLI_SELECTOR:
572 {
573 uint32_t sel;
574
575 if (conn->state != CONN_OUT_PREPARING)
576 goto rdonly;
577 memcpy(&sel, ptr, sizeof(sel));
578 if (sel == 0 || sel > UNI_NUM_IE_BLLI)
579 goto bad_val;
580 len = sizeof(uint32_t);
581 break;
582 }
583
584 case ATM_ATTR_BLLI:
585 len = sizeof(struct uni_ie_blli);
586 break;
587
588 case ATM_ATTR_BEARER:
589 if (conn->state != CONN_OUT_PREPARING)
590 goto rdonly;
591 len = sizeof(struct uni_ie_bearer);
592 break;
593
594 case ATM_ATTR_TRAFFIC:
595 len = sizeof(struct uni_ie_traffic);
596 break;
597
598 case ATM_ATTR_QOS:
599 if (conn->state != CONN_OUT_PREPARING)
600 goto rdonly;
601 len = sizeof(struct uni_ie_qos);
602 break;
603
604 case ATM_ATTR_EXQOS:
605 len = sizeof(struct uni_ie_exqos);
606 break;
607
608 case ATM_ATTR_CALLED:
609 goto rdonly;
610
611 case ATM_ATTR_CALLEDSUB:
612 if (conn->state != CONN_OUT_PREPARING)
613 goto rdonly;
614 len = sizeof(struct uni_ie_calledsub);
615 break;
616
617 case ATM_ATTR_CALLING:
618 if (conn->state != CONN_OUT_PREPARING)
619 goto rdonly;
620 len = sizeof(struct uni_ie_calling);
621 break;
622
623 case ATM_ATTR_CALLINGSUB:
624 if (conn->state != CONN_OUT_PREPARING)
625 goto rdonly;
626 len = sizeof(struct uni_ie_callingsub);
627 break;
628
629 case ATM_ATTR_AAL:
630 len = sizeof(struct uni_ie_aal);
631 break;
632
633 case ATM_ATTR_EPREF:
634 goto rdonly;
635
636 case ATM_ATTR_CONNED:
637 goto rdonly;
638
639 case ATM_ATTR_CONNEDSUB:
640 goto rdonly;
641
642 case ATM_ATTR_EETD:
643 len = sizeof(struct uni_ie_eetd);
644 break;
645
646 case ATM_ATTR_ABRSETUP:
647 len = sizeof(struct uni_ie_abrsetup);
648 break;
649
650 case ATM_ATTR_ABRADD:
651 len = sizeof(struct uni_ie_abradd);
652 break;
653
654 case ATM_ATTR_CONNID:
655 len = sizeof(struct uni_ie_connid);
656 break;
657
658 case ATM_ATTR_MDCR:
659 if (conn->state != CONN_OUT_PREPARING)
660 goto rdonly;
661 len = sizeof(struct uni_ie_mdcr);
662 break;
663 }
664 if (len == 0) {
665 cc_user_err(user, ATMERR_BAD_ATTR);
666 return;
667 }
668 total += len;
669 ptr += len;
670 }
671
672 /* check the length */
673 if (vallen != total) {
674 cc_user_err(user, ATMERR_BAD_ARGS);
675 return;
676 }
677
678 ptr = val;
679 for (i = 0; i < count; i++) {
680 len = 0;
681 switch ((enum atm_attribute)attr[i]) {
682
683 case ATM_ATTR_NONE:
684 break;
685
686 case ATM_ATTR_BLLI_SELECTOR:
687 {
688 uint32_t sel;
689
690 memcpy(&sel, ptr, sizeof(sel));
691 conn->blli_selector = sel;
692 len = sizeof(uint32_t);
693 break;
694 }
695
696 case ATM_ATTR_BLLI:
697 len = sizeof(struct uni_ie_blli);
698 memcpy(&conn->blli[conn->blli_selector - 1], ptr, len);
699 conn->dirty_attr |= CCDIRTY_BLLI;
700 break;
701
702 case ATM_ATTR_BEARER:
703 len = sizeof(struct uni_ie_bearer);
704 memcpy(&conn->bearer, ptr, len);
705 break;
706
707 case ATM_ATTR_TRAFFIC:
708 len = sizeof(struct uni_ie_traffic);
709 memcpy(&conn->traffic, ptr, len);
710 conn->dirty_attr |= CCDIRTY_TRAFFIC;
711 break;
712
713 case ATM_ATTR_QOS:
714 len = sizeof(struct uni_ie_qos);
715 memcpy(&conn->qos, ptr, len);
716 break;
717
718 case ATM_ATTR_EXQOS:
719 len = sizeof(struct uni_ie_exqos);
720 memcpy(&conn->exqos, ptr, len);
721 conn->dirty_attr |= CCDIRTY_EXQOS;
722 break;
723
724 case ATM_ATTR_CALLED:
725 len = sizeof(struct uni_ie_called);
726 break;
727
728 case ATM_ATTR_CALLEDSUB:
729 len = sizeof(struct uni_ie_calledsub);
730 memcpy(&conn->calledsub, ptr, len);
731 break;
732
733 case ATM_ATTR_CALLING:
734 len = sizeof(struct uni_ie_calling);
735 memcpy(&conn->calling, ptr, len);
736 break;
737
738 case ATM_ATTR_CALLINGSUB:
739 len = sizeof(struct uni_ie_callingsub);
740 memcpy(&conn->callingsub, ptr, len);
741 break;
742
743 case ATM_ATTR_AAL:
744 len = sizeof(struct uni_ie_aal);
745 memcpy(&conn->aal, ptr, len);
746 conn->dirty_attr |= CCDIRTY_AAL;
747 break;
748
749 case ATM_ATTR_EPREF:
750 len = sizeof(struct uni_ie_epref);
751 break;
752
753 case ATM_ATTR_CONNED:
754 len = sizeof(struct uni_ie_conned);
755 break;
756
757 case ATM_ATTR_CONNEDSUB:
758 len = sizeof(struct uni_ie_connedsub);
759 break;
760
761 case ATM_ATTR_EETD:
762 len = sizeof(struct uni_ie_eetd);
763 memcpy(&conn->eetd, ptr, len);
764 conn->dirty_attr |= CCDIRTY_EETD;
765 break;
766
767 case ATM_ATTR_ABRSETUP:
768 len = sizeof(struct uni_ie_abrsetup);
769 memcpy(&conn->abrsetup, ptr, len);
770 conn->dirty_attr |= CCDIRTY_ABRSETUP;
771 break;
772
773 case ATM_ATTR_ABRADD:
774 len = sizeof(struct uni_ie_abradd);
775 memcpy(&conn->abradd, ptr, len);
776 conn->dirty_attr |= CCDIRTY_ABRADD;
777 break;
778
779 case ATM_ATTR_CONNID:
780 len = sizeof(struct uni_ie_connid);
781 memcpy(&conn->connid, ptr, len);
782 conn->dirty_attr |= CCDIRTY_CONNID;
783 break;
784
785 case ATM_ATTR_MDCR:
786 len = sizeof(struct uni_ie_mdcr);
787 memcpy(&conn->mdcr, ptr, len);
788 break;
789 }
790 ptr += len;
791 }
792
793 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
794 return;
795
796 bad_val:
797 cc_user_err(user, ATMERR_BAD_VALUE);
798 return;
799
800 rdonly:
801 cc_user_err(user, ATMERR_RDONLY);
802 return;
803 }
804
805 #ifdef CCATM_DEBUG
806 static const char *op_names[] = {
807 #define S(OP) [ATMOP_##OP] = #OP
808 S(RESP),
809 S(ABORT_CONNECTION),
810 S(ACCEPT_INCOMING_CALL),
811 S(ADD_PARTY),
812 S(ADD_PARTY_REJECT),
813 S(ADD_PARTY_SUCCESS),
814 S(ARRIVAL_OF_INCOMING_CALL),
815 S(CALL_RELEASE),
816 S(CONNECT_OUTGOING_CALL),
817 S(DROP_PARTY),
818 S(GET_LOCAL_PORT_INFO),
819 S(P2MP_CALL_ACTIVE),
820 S(P2P_CALL_ACTIVE),
821 S(PREPARE_INCOMING_CALL),
822 S(PREPARE_OUTGOING_CALL),
823 S(QUERY_CONNECTION_ATTRIBUTES),
824 S(REJECT_INCOMING_CALL),
825 S(SET_CONNECTION_ATTRIBUTES),
826 S(WAIT_ON_INCOMING_CALL),
827 S(SET_CONNECTION_ATTRIBUTES_X),
828 S(QUERY_CONNECTION_ATTRIBUTES_X),
829 S(QUERY_STATE),
830 #undef S
831 };
832 #endif
833
834 /*
835 * Signal from user - map this to our internal signals and queue
836 * the mapped signal.
837 */
838 int
839 cc_user_signal(struct ccuser *user, enum atmop sig, struct uni_msg *msg)
840 {
841 size_t len = uni_msg_len(msg);
842 int err = EINVAL;
843
844 if (user->cc->log & CCLOG_USER_SIG)
845 cc_user_log(user, "signal %s to user", op_names[sig]);
846
847 if ((u_int)sig > ATMOP_QUERY_STATE)
848 goto bad_signal;
849
850 switch (sig) {
851
852 case ATMOP_ABORT_CONNECTION:
853 if (len != sizeof(struct atm_abort_connection))
854 goto bad_len;
855 err = cc_user_sig_msg(user, USER_SIG_ABORT_CONNECTION, msg);
856 break;
857
858 case ATMOP_ACCEPT_INCOMING_CALL:
859 if (len != sizeof(struct atm_accept_incoming_call))
860 goto bad_len;
861 err = cc_user_sig_msg(user, USER_SIG_ACCEPT_INCOMING, msg);
862 break;
863
864 case ATMOP_ADD_PARTY:
865 if (len != sizeof(struct atm_add_party))
866 goto bad_len;
867 err = cc_user_sig_msg(user, USER_SIG_ADD_PARTY, msg);
868 break;
869
870 case ATMOP_CALL_RELEASE:
871 if (len != sizeof(struct atm_call_release))
872 goto bad_len;
873 err = cc_user_sig_msg(user, USER_SIG_CALL_RELEASE, msg);
874 break;
875
876 case ATMOP_CONNECT_OUTGOING_CALL:
877 if (len != sizeof(struct atm_connect_outgoing_call))
878 goto bad_len;
879 err = cc_user_sig_msg(user, USER_SIG_CONNECT_OUTGOING, msg);
880 break;
881
882 case ATMOP_DROP_PARTY:
883 if (len != sizeof(struct atm_drop_party))
884 goto bad_len;
885 err = cc_user_sig_msg(user, USER_SIG_DROP_PARTY, msg);
886 break;
887
888 case ATMOP_GET_LOCAL_PORT_INFO:
889 if (len != sizeof(struct atm_get_local_port_info))
890 goto bad_len;
891 err = cc_user_sig_msg(user, USER_SIG_GET_LOCAL_PORT_INFO, msg);
892 break;
893
894 case ATMOP_PREPARE_INCOMING_CALL:
895 if (len != sizeof(struct atm_prepare_incoming_call))
896 goto bad_len;
897 err = cc_user_sig_msg(user, USER_SIG_PREPARE_INCOMING, msg);
898 break;
899
900 case ATMOP_PREPARE_OUTGOING_CALL:
901 if (len != 0)
902 goto bad_len;
903 uni_msg_destroy(msg);
904 err = cc_user_sig(user, USER_SIG_PREPARE_OUTGOING, NULL, 0);
905 break;
906
907 case ATMOP_QUERY_CONNECTION_ATTRIBUTES:
908 if (len != sizeof(struct atm_query_connection_attributes))
909 goto bad_len;
910 err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR, msg);
911 break;
912
913 case ATMOP_REJECT_INCOMING_CALL:
914 if (len != sizeof(struct atm_reject_incoming_call))
915 goto bad_len;
916 err = cc_user_sig_msg(user, USER_SIG_REJECT_INCOMING, msg);
917 break;
918
919 case ATMOP_SET_CONNECTION_ATTRIBUTES:
920 if (len < sizeof(struct atm_set_connection_attributes))
921 goto bad_len;
922 err = cc_user_sig_msg(user, USER_SIG_SET_ATTR, msg);
923 break;
924
925 case ATMOP_WAIT_ON_INCOMING_CALL:
926 if (len != 0)
927 goto bad_len;
928 uni_msg_destroy(msg);
929 err = cc_user_sig(user, USER_SIG_WAIT_ON_INCOMING, NULL, 0);
930 break;
931
932 case ATMOP_QUERY_CONNECTION_ATTRIBUTES_X:
933 if (len < sizeof(struct atm_set_connection_attributes_x) ||
934 len != offsetof(struct atm_set_connection_attributes_x,
935 attr) + uni_msg_rptr(msg,
936 struct atm_set_connection_attributes_x *)->count *
937 sizeof(uint32_t))
938 goto bad_len;
939 err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR_X, msg);
940 break;
941
942 case ATMOP_SET_CONNECTION_ATTRIBUTES_X:
943 if (len < sizeof(struct atm_set_connection_attributes_x))
944 goto bad_len;
945 err = cc_user_sig_msg(user, USER_SIG_SET_ATTR_X, msg);
946 break;
947
948 case ATMOP_QUERY_STATE:
949 if (len != 0)
950 goto bad_len;
951 uni_msg_destroy(msg);
952 err = cc_user_sig(user, USER_SIG_QUERY_STATE, NULL, 0);
953 break;
954
955 case ATMOP_RESP:
956 case ATMOP_ADD_PARTY_REJECT:
957 case ATMOP_ADD_PARTY_SUCCESS:
958 case ATMOP_ARRIVAL_OF_INCOMING_CALL:
959 case ATMOP_P2MP_CALL_ACTIVE:
960 case ATMOP_P2P_CALL_ACTIVE:
961 bad_signal:
962 /* bad signal */
963 if (user->cc->log & CCLOG_USER_SIG)
964 cc_user_log(user, "bad signal %u", sig);
965 cc_user_err(user, ATMERR_BAD_OP);
966 uni_msg_destroy(msg);
967 break;
968 }
969 return (err);
970
971 bad_len:
972 /* bad argument length */
973 if (user->cc->log & CCLOG_USER_SIG)
974 cc_user_log(user, "signal %s had bad len=%zu",
975 op_names[sig], len);
976 cc_user_err(user, ATMERR_BAD_ARGS);
977 uni_msg_destroy(msg);
978 return (EINVAL);
979 }
980
981 /*
982 * Send active signal to user
983 */
984 static void
985 cc_user_active(struct ccuser *user)
986 {
987 struct ccconn *conn = TAILQ_FIRST(&user->connq);
988
989 set_state(user, USER_ACTIVE);
990 if (conn->bearer.cfg == UNI_BEARER_P2P) {
991 struct atm_p2p_call_active *act;
992
993 user->config = USER_P2P;
994 act = CCZALLOC(sizeof(*act));
995 if (act == NULL)
996 return;
997 act->connid = conn->connid;
998 cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, act, sizeof(*act));
999 CCFREE(act);
1000 } else {
1001 struct atm_p2mp_call_active *act;
1002
1003 user->config = USER_ROOT;
1004 act = CCZALLOC(sizeof(*act));
1005 if (act == NULL)
1006 return;
1007 act->connid = conn->connid;
1008 cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, act, sizeof(*act));
1009 CCFREE(act);
1010 }
1011 }
1012
1013 /*
1014 * Handle a signal to this user
1015 */
1016 void
1017 cc_user_sig_handle(struct ccuser *user, enum user_sig sig,
1018 void *arg, u_int arg2)
1019 {
1020
1021 if (user->cc->log & CCLOG_USER_SIG)
1022 cc_user_log(user, "signal %s to user state %s",
1023 cc_user_sigtab[sig], stab[user->state]);
1024
1025 switch (sig) {
1026
1027
1028 case USER_SIG_PREPARE_OUTGOING:
1029 {
1030 /*
1031 * Here we create a connection for the call we soon will make.
1032 * We put this call on the list of orphaned connections,
1033 * because we don't know yet, which port will get the
1034 * connection. It is assigned, when the user issues the call
1035 * to connect.
1036 */
1037 struct ccconn *conn;
1038
1039 if (user->state != USER_NULL) {
1040 cc_user_err(user, ATMERR_BAD_STATE);
1041 goto bad_state;
1042 }
1043 conn = cc_conn_create(user->cc);
1044 if (conn == NULL) {
1045 cc_user_err(user, ATMERR_NOMEM);
1046 return;
1047 }
1048 set_state(user, USER_OUT_PREPARING);
1049 cc_conn_set_state(conn, CONN_OUT_PREPARING);
1050 conn->blli_selector = 1;
1051 cc_connect_to_user(conn, user);
1052
1053 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1054 return;
1055 }
1056
1057
1058 case USER_SIG_CONNECT_OUTGOING:
1059 {
1060 /*
1061 * Request to connect that call
1062 *
1063 * Here we assign the connection to a port.
1064 */
1065 struct uni_msg *msg = arg;
1066 struct atm_connect_outgoing_call *req = uni_msg_rptr(msg,
1067 struct atm_connect_outgoing_call *);
1068 struct ccdata *priv = user->cc;
1069 struct ccport *port;
1070 struct ccaddr *addr;
1071 struct ccconn *conn = TAILQ_FIRST(&user->connq);
1072
1073 if (user->state != USER_OUT_PREPARING) {
1074 uni_msg_destroy(msg);
1075 cc_user_err(user, ATMERR_BAD_STATE);
1076 goto bad_state;
1077 }
1078 if (!IE_ISPRESENT(req->called)) {
1079 uni_msg_destroy(msg);
1080 cc_user_err(user, ATMERR_BAD_ARGS);
1081 return;
1082 }
1083 CCASSERT(conn->port == NULL, ("connection still on port"));
1084
1085 if (TAILQ_EMPTY(&priv->port_list)) {
1086 /*
1087 * We have no ports - reject
1088 */
1089 uni_msg_destroy(msg);
1090 cc_user_err(user, ATMERR_BAD_PORT);
1091 return;
1092 }
1093
1094 /*
1095 * Find the correct port
1096 * Routing of outgoing calls goes to the lowest numbered port
1097 * with a matching address or, if no address match is found to
1098 * the lowest numbered port.
1099 */
1100 TAILQ_FOREACH(port, &priv->port_list, node_link)
1101 TAILQ_FOREACH(addr, &port->addr_list, port_link)
1102 if (addr_matches(addr, conn))
1103 break;
1104
1105 if (port == NULL)
1106 port = TAILQ_FIRST(&priv->port_list);
1107
1108 cc_conn_ins_port(conn, port);
1109 conn->called = req->called;
1110 uni_msg_destroy(msg);
1111
1112 /*
1113 * Now move the state
1114 */
1115 set_state(user, USER_OUT_WAIT_OK);
1116 cc_conn_sig(conn, CONN_SIG_CONNECT_OUTGOING, NULL);
1117
1118 return;
1119 }
1120
1121
1122 case USER_SIG_CONNECT_OUTGOING_ERR:
1123 switch (user->state) {
1124
1125 case USER_OUT_WAIT_OK:
1126 set_state(user, USER_OUT_PREPARING);
1127 cc_user_err(user, arg2);
1128 break;
1129
1130 case USER_REL_WAIT_CONN:
1131 {
1132 struct ccconn *conn;
1133
1134 conn = TAILQ_FIRST(&user->connq);
1135 if (conn != NULL) {
1136 cc_disconnect_from_user(conn);
1137 cc_conn_destroy(conn);
1138 }
1139
1140 cc_user_reset(user);
1141 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1142 break;
1143 }
1144
1145 default:
1146 goto bad_state;
1147 }
1148 return;
1149
1150
1151 case USER_SIG_CONNECT_OUTGOING_OK:
1152 switch (user->state) {
1153
1154 case USER_OUT_WAIT_OK:
1155 set_state(user, USER_OUT_WAIT_CONF);
1156 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1157 break;
1158
1159 case USER_REL_WAIT_CONN:
1160 set_state(user, USER_REL_WAIT_SCONF);
1161 break;
1162
1163 default:
1164 goto bad_state;
1165 }
1166 return;
1167
1168
1169 case USER_SIG_SETUP_CONFIRM:
1170 /*
1171 * SETUP.confirm from UNI stack.
1172 */
1173 switch (user->state) {
1174
1175 case USER_OUT_WAIT_CONF:
1176 cc_user_active(user);
1177 break;
1178
1179 case USER_REL_WAIT_SCONF:
1180 /* now try to release */
1181 set_state(user, USER_REL_WAIT_CONF);
1182 cc_conn_sig(TAILQ_FIRST(&user->connq),
1183 CONN_SIG_RELEASE, NULL);
1184 break;
1185
1186 default:
1187 goto bad_state;
1188 }
1189 return;
1190
1191
1192 case USER_SIG_PREPARE_INCOMING:
1193 {
1194 struct uni_msg *msg = arg;
1195 struct ccuser *ptr;
1196 struct atm_prepare_incoming_call *prep = uni_msg_rptr(msg,
1197 struct atm_prepare_incoming_call *);
1198
1199 if (user->state != USER_NULL) {
1200 uni_msg_destroy(msg);
1201 cc_user_err(user, ATMERR_BAD_STATE);
1202 goto bad_state;
1203 }
1204
1205 /*
1206 * Check the SAP
1207 */
1208 if (unisve_check_sap(&prep->sap) != UNISVE_OK) {
1209 uni_msg_destroy(msg);
1210 cc_user_err(user, ATMERR_BAD_SAP);
1211 return;
1212 }
1213
1214 /*
1215 * Loop through all incoming calls and check whether there
1216 * is an overlap in SAP space.
1217 */
1218 LIST_FOREACH(ptr, &user->cc->user_list, node_link) {
1219 if (check_overlap(ptr, &prep->sap)) {
1220 uni_msg_destroy(msg);
1221 cc_user_err(user, ATMERR_OVERLAP);
1222 return;
1223 }
1224 }
1225
1226 /*
1227 * Save info and set state
1228 */
1229 user->sap = CCZALLOC(sizeof(struct uni_sap));
1230 if (user->sap == NULL) {
1231 uni_msg_destroy(msg);
1232 cc_user_err(user, ATMERR_NOMEM);
1233 return;
1234 }
1235 *user->sap = prep->sap;
1236 user->queue_max = prep->queue_size;
1237 user->queue_act = 0;
1238 uni_msg_destroy(msg);
1239
1240 set_state(user, USER_IN_PREPARING);
1241 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1242
1243 return;
1244 }
1245
1246
1247 case USER_SIG_WAIT_ON_INCOMING:
1248 if (user->state != USER_IN_PREPARING) {
1249 cc_user_err(user, ATMERR_BAD_STATE);
1250 goto bad_state;
1251 }
1252
1253 set_state(user, USER_IN_WAITING);
1254 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1255 return;
1256
1257
1258 case USER_SIG_SETUP_IND:
1259 /*
1260 * New connection queued up in the queue. If this is the
1261 * first one, inform the application of the arrival.
1262 */
1263 switch (user->state) {
1264
1265 case USER_IN_WAITING:
1266 do_arrival(user);
1267 break;
1268
1269 case USER_IN_ARRIVED:
1270 case USER_IN_WAIT_REJ:
1271 case USER_IN_WAIT_ACC:
1272 break;
1273
1274 default:
1275 goto bad_state;
1276 }
1277 return;
1278
1279
1280 case USER_SIG_REJECT_INCOMING:
1281 {
1282 /*
1283 * User rejects call. This is done on the OLD user
1284 * (i.e. the one sending the arrival).
1285 */
1286 struct uni_msg *msg = arg;
1287 struct atm_reject_incoming_call *rej = uni_msg_rptr(msg,
1288 struct atm_reject_incoming_call *);
1289 struct ccconn *conn = TAILQ_FIRST(&user->connq);
1290
1291 if (user->state != USER_IN_ARRIVED) {
1292 uni_msg_destroy(msg);
1293 cc_user_err(user, ATMERR_BAD_STATE);
1294 goto bad_state;
1295 }
1296 if (user->aborted) {
1297 /* connection has disappeared. Send an ok
1298 * to the user and lock whether there is another
1299 * connection at this endpoint */
1300 uni_msg_destroy(msg);
1301 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1302
1303 set_state(user, USER_IN_WAITING);
1304 do_arrival(user);
1305 return;
1306 }
1307 conn->cause[0] = rej->cause;
1308 memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
1309 uni_msg_destroy(msg);
1310
1311 set_state(user, USER_IN_WAIT_REJ);
1312 cc_conn_sig(conn, CONN_SIG_REJECT, NULL);
1313
1314 return;
1315 }
1316
1317
1318 case USER_SIG_REJECT_OK:
1319 if (user->state != USER_IN_WAIT_REJ)
1320 goto bad_state;
1321 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1322
1323 set_state(user, USER_IN_WAITING);
1324 do_arrival(user);
1325 return;
1326
1327
1328 case USER_SIG_REJECT_ERR:
1329 if (user->state != USER_IN_WAIT_REJ)
1330 goto bad_state;
1331 cc_user_err(user, arg2);
1332
1333 if (arg == NULL)
1334 set_state(user, USER_IN_ARRIVED);
1335 else {
1336 set_state(user, USER_IN_WAITING);
1337 do_arrival(user);
1338 }
1339 return;
1340
1341
1342 case USER_SIG_ACCEPT_INCOMING:
1343 {
1344 /*
1345 * User accepts call. This is done on the OLD user (i.e. the one
1346 * sending the arrival), the message contains a pointer to the
1347 * new endpoint.
1348 */
1349 struct uni_msg *msg = arg;
1350 struct atm_accept_incoming_call *acc =
1351 uni_msg_rptr(msg, struct atm_accept_incoming_call *);
1352 struct ccuser *newep;
1353
1354 if (user->state != USER_IN_ARRIVED) {
1355 uni_msg_destroy(msg);
1356 cc_user_err(user, ATMERR_BAD_STATE);
1357 return;
1358 }
1359 if (user->aborted) {
1360 /* connection has disappeared. Send an error
1361 * to the user and lock whether there is another
1362 * connection at this endpoint */
1363 uni_msg_destroy(msg);
1364 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1365
1366 set_state(user, USER_IN_WAITING);
1367 do_arrival(user);
1368 return;
1369 }
1370 acc->newep[sizeof(acc->newep) - 1] = '\0';
1371
1372 LIST_FOREACH(newep, &user->cc->user_list, node_link)
1373 if (strcmp(acc->newep, newep->name) == 0)
1374 break;
1375 uni_msg_destroy(msg);
1376
1377 if (newep == NULL) {
1378 cc_user_err(user, ATMERR_BAD_ENDPOINT);
1379 return;
1380 }
1381
1382 if (newep->state != USER_NULL || newep->accepted != NULL) {
1383 cc_user_err(user, ATMERR_BAD_STATE);
1384 return;
1385 }
1386
1387 set_state(user, USER_IN_WAIT_ACC);
1388 cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep);
1389
1390 return;
1391 }
1392
1393
1394 case USER_SIG_ACCEPT_OK:
1395 if (user->state != USER_IN_WAIT_ACC)
1396 goto bad_state;
1397 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1398
1399 set_state(user, USER_IN_WAITING);
1400 do_arrival(user);
1401 return;
1402
1403
1404 case USER_SIG_ACCEPT_ERR:
1405 if (user->state != USER_IN_WAIT_ACC)
1406 goto bad_state;
1407 cc_user_err(user, arg2);
1408
1409 if (arg == NULL) {
1410 /* arg used as flag! */
1411 set_state(user, USER_IN_ARRIVED);
1412 } else {
1413 set_state(user, USER_IN_WAITING);
1414 do_arrival(user);
1415 }
1416 return;
1417
1418
1419 case USER_SIG_ACCEPTING:
1420 if (user->state != USER_NULL)
1421 goto bad_state;
1422 set_state(user, USER_IN_ACCEPTING);
1423 return;
1424
1425
1426 case USER_SIG_SETUP_COMPL:
1427 {
1428 struct ccconn *conn = TAILQ_FIRST(&user->connq);
1429
1430 if (user->state != USER_IN_ACCEPTING)
1431 goto bad_state;
1432
1433 user->state = USER_ACTIVE;
1434 if (conn->bearer.cfg == UNI_BEARER_P2P) {
1435 struct atm_p2p_call_active *act;
1436
1437 user->config = USER_P2P;
1438 act = CCZALLOC(sizeof(*act));
1439 if (act == NULL)
1440 return;
1441 act->connid = conn->connid;
1442 cc_user_send(user, ATMOP_P2P_CALL_ACTIVE,
1443 act, sizeof(*act));
1444 CCFREE(act);
1445 } else {
1446 struct atm_p2mp_call_active *act;
1447
1448 user->config = USER_LEAF;
1449 act = CCZALLOC(sizeof(*act));
1450 if (act == NULL)
1451 return;
1452 act->connid = conn->connid;
1453 cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE,
1454 act, sizeof(*act));
1455 CCFREE(act);
1456 }
1457 return;
1458 }
1459
1460
1461 case USER_SIG_CALL_RELEASE:
1462 {
1463 struct uni_msg *msg = arg;
1464 struct atm_call_release *api = uni_msg_rptr(msg,
1465 struct atm_call_release *);
1466 struct ccconn *conn;
1467
1468 conn = TAILQ_FIRST(&user->connq);
1469 switch (user->state) {
1470
1471 case USER_OUT_WAIT_OK: /* U2/A3 */
1472 /* wait for CONN_OK first */
1473 conn->cause[0] = api->cause[0];
1474 conn->cause[1] = api->cause[1];
1475 set_state(user, USER_REL_WAIT_CONN);
1476 break;
1477
1478 case USER_OUT_WAIT_CONF: /* U3/A3 */
1479 /* wait for SETUP.confirm first */
1480 conn->cause[0] = api->cause[0];
1481 conn->cause[1] = api->cause[1];
1482 set_state(user, USER_REL_WAIT_SCONF);
1483 break;
1484
1485 case USER_IN_ACCEPTING: /* U11/A7 */
1486 conn->cause[0] = api->cause[0];
1487 conn->cause[1] = api->cause[1];
1488 set_state(user, USER_REL_WAIT_SCOMP);
1489 cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
1490 break;
1491
1492 case USER_ACTIVE: /* U4/A8,A9,A10 */
1493 conn->cause[0] = api->cause[0];
1494 conn->cause[1] = api->cause[1];
1495 set_state(user, USER_REL_WAIT);
1496 cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
1497 break;
1498
1499 default:
1500 uni_msg_destroy(msg);
1501 cc_user_err(user, ATMERR_BAD_STATE);
1502 goto bad_state;
1503 }
1504 uni_msg_destroy(msg);
1505 return;
1506 }
1507
1508
1509 case USER_SIG_RELEASE_CONFIRM:
1510 {
1511 struct atm_call_release *ind;
1512
1513 switch (user->state) {
1514
1515 case USER_OUT_WAIT_CONF: /* U3/A3 */
1516 case USER_ACTIVE: /* U4/A8,A9,A10 */
1517 cc_user_reset(user);
1518 break;
1519
1520 case USER_REL_WAIT: /* U5 /A8,A9,A10 */
1521 case USER_REL_WAIT_SCOMP: /* U12/A7 */
1522 case USER_REL_WAIT_SCONF: /* U13/A3 */
1523 case USER_REL_WAIT_CONF: /* U14/A3 */
1524 cc_user_reset(user);
1525 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1526 return;
1527
1528 case USER_IN_ACCEPTING: /* U11/A7 */
1529 cc_user_reset(user);
1530 break;
1531
1532 default:
1533 goto bad_state;
1534 }
1535
1536 ind = CCZALLOC(sizeof(*ind));
1537 if (ind == NULL)
1538 return;
1539 memcpy(ind->cause, user->cause, sizeof(ind->cause));
1540 cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind));
1541 CCFREE(ind);
1542 return;
1543 }
1544
1545
1546 case USER_SIG_RELEASE_ERR:
1547 switch (user->state) {
1548
1549 case USER_REL_WAIT: /* U5/A8,A9,A10 */
1550 set_state(user, USER_ACTIVE);
1551 cc_user_err(user, ATM_MKUNIERR(arg2));
1552 break;
1553
1554 case USER_REL_WAIT_CONF: /* U14/A3 */
1555 cc_user_err(user, ATM_MKUNIERR(arg2));
1556 cc_user_active(user);
1557 break;
1558
1559 case USER_REL_WAIT_SCOMP: /* U12/A7 */
1560 set_state(user, USER_IN_ACCEPTING);
1561 cc_user_err(user, ATM_MKUNIERR(arg2));
1562 break;
1563
1564 default:
1565 goto bad_state;
1566 }
1567 return;
1568
1569
1570 case USER_SIG_ADD_PARTY:
1571 {
1572 struct uni_msg *msg = arg;
1573 struct atm_add_party *add = uni_msg_rptr(msg,
1574 struct atm_add_party *);
1575 struct ccconn *conn;
1576
1577 if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
1578 uni_msg_destroy(msg);
1579 cc_user_err(user, ATMERR_BAD_STATE);
1580 return;
1581 }
1582
1583 if (add->leaf_ident == 0 || add->leaf_ident >= 32786) {
1584 uni_msg_destroy(msg);
1585 cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
1586 return;
1587 }
1588
1589 conn = TAILQ_FIRST(&user->connq);
1590 conn->called = add->called;
1591
1592 cc_conn_sig(conn, CONN_SIG_ADD_PARTY,
1593 (void *)(uintptr_t)add->leaf_ident);
1594
1595 uni_msg_destroy(msg);
1596 return;
1597 }
1598
1599
1600 case USER_SIG_ADD_PARTY_ERR:
1601 if (user->state != USER_ACTIVE)
1602 goto bad_state;
1603 cc_user_err(user, arg2);
1604 return;
1605
1606
1607 case USER_SIG_ADD_PARTY_OK:
1608 if (user->state != USER_ACTIVE)
1609 goto bad_state;
1610 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1611 return;
1612
1613
1614 case USER_SIG_ADD_PARTY_ACK:
1615 {
1616 u_int leaf_ident = arg2;
1617 struct atm_add_party_success *succ;
1618
1619 if (user->state != USER_ACTIVE)
1620 goto bad_state;
1621
1622 succ = CCZALLOC(sizeof(*succ));
1623 if (succ == NULL)
1624 return;
1625
1626 succ->leaf_ident = leaf_ident;
1627 cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS,
1628 succ, sizeof(*succ));
1629
1630 CCFREE(succ);
1631 return;
1632 }
1633
1634
1635 case USER_SIG_ADD_PARTY_REJ:
1636 {
1637 u_int leaf_ident = arg2;
1638 struct atm_add_party_reject *reject;
1639
1640 if (user->state != USER_ACTIVE)
1641 goto bad_state;
1642
1643 reject = CCZALLOC(sizeof(*reject));
1644 if (reject == NULL)
1645 return;
1646
1647 reject->leaf_ident = leaf_ident;
1648 reject->cause = user->cause[0];
1649 cc_user_send(user, ATMOP_ADD_PARTY_REJECT,
1650 reject, sizeof(*reject));
1651
1652 CCFREE(reject);
1653 return;
1654 }
1655
1656
1657 case USER_SIG_DROP_PARTY:
1658 {
1659 struct uni_msg *msg = arg;
1660 struct atm_drop_party *drop = uni_msg_rptr(msg,
1661 struct atm_drop_party *);
1662 struct ccconn *conn;
1663
1664 if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
1665 uni_msg_destroy(msg);
1666 cc_user_err(user, ATMERR_BAD_STATE);
1667 return;
1668 }
1669
1670 if (drop->leaf_ident >= 32786) {
1671 uni_msg_destroy(msg);
1672 cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
1673 return;
1674 }
1675
1676 conn = TAILQ_FIRST(&user->connq);
1677 conn->cause[0] = drop->cause;
1678 memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
1679
1680 cc_conn_sig(conn, CONN_SIG_DROP_PARTY,
1681 (void *)(uintptr_t)drop->leaf_ident);
1682
1683 uni_msg_destroy(msg);
1684 return;
1685 }
1686
1687
1688 case USER_SIG_DROP_PARTY_ERR:
1689 if (user->state != USER_ACTIVE)
1690 goto bad_state;
1691 cc_user_err(user, arg2);
1692 return;
1693
1694
1695 case USER_SIG_DROP_PARTY_OK:
1696 if (user->state != USER_ACTIVE)
1697 goto bad_state;
1698 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1699 return;
1700
1701
1702 case USER_SIG_DROP_PARTY_IND:
1703 {
1704 u_int leaf_ident = arg2;
1705 struct atm_drop_party *drop;
1706
1707 if (user->state != USER_ACTIVE)
1708 goto bad_state;
1709
1710 drop = CCZALLOC(sizeof(*drop));
1711 if (drop == NULL)
1712 return;
1713
1714 drop->leaf_ident = leaf_ident;
1715 drop->cause = user->cause[0];
1716 cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop));
1717
1718 CCFREE(drop);
1719 return;
1720 }
1721
1722
1723 case USER_SIG_QUERY_ATTR:
1724 {
1725 struct uni_msg *msg = arg;
1726 struct atm_query_connection_attributes *req;
1727 struct ccconn *conn;
1728
1729 if (user->aborted) {
1730 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1731 uni_msg_destroy(msg);
1732 return;
1733 }
1734 conn = cc_query_check(user);
1735 if (conn == NULL) {
1736 cc_user_err(user, ATMERR_BAD_STATE);
1737 uni_msg_destroy(msg);
1738 return;
1739 }
1740 req = uni_msg_rptr(msg,
1741 struct atm_query_connection_attributes *);
1742 cc_attr_query(user, conn, &req->attr, 1);
1743 uni_msg_destroy(msg);
1744 return;
1745 }
1746
1747 case USER_SIG_QUERY_ATTR_X:
1748 {
1749 struct uni_msg *msg = arg;
1750 struct atm_query_connection_attributes_x *req;
1751 struct ccconn *conn;
1752
1753 conn = cc_query_check(user);
1754 if (conn == NULL) {
1755 cc_user_err(user, ATMERR_BAD_STATE);
1756 uni_msg_destroy(msg);
1757 return;
1758 }
1759 req = uni_msg_rptr(msg,
1760 struct atm_query_connection_attributes_x *);
1761 cc_attr_query(user, conn, req->attr, req->count);
1762 uni_msg_destroy(msg);
1763 return;
1764 }
1765
1766 case USER_SIG_SET_ATTR:
1767 {
1768 struct uni_msg *msg = arg;
1769 struct atm_set_connection_attributes *req;
1770 struct ccconn *conn;
1771
1772 if (user->aborted) {
1773 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1774 uni_msg_destroy(msg);
1775 return;
1776 }
1777 conn = cc_set_check(user);
1778 if (conn == NULL) {
1779 cc_user_err(user, ATMERR_BAD_STATE);
1780 uni_msg_destroy(msg);
1781 return;
1782 }
1783 req = uni_msg_rptr(msg, struct atm_set_connection_attributes *);
1784 cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1),
1785 uni_msg_len(msg) - sizeof(*req));
1786 uni_msg_destroy(msg);
1787 return;
1788 }
1789
1790 case USER_SIG_SET_ATTR_X:
1791 {
1792 struct uni_msg *msg = arg;
1793 struct atm_set_connection_attributes_x *req;
1794 struct ccconn *conn;
1795
1796 conn = cc_set_check(user);
1797 if (conn == NULL) {
1798 cc_user_err(user, ATMERR_BAD_STATE);
1799 uni_msg_destroy(msg);
1800 return;
1801 }
1802 req = uni_msg_rptr(msg,
1803 struct atm_set_connection_attributes_x *);
1804 cc_attr_set(user, conn, req->attr, req->count,
1805 (u_char *)req->attr + req->count * sizeof(req->attr[0]),
1806 uni_msg_len(msg) -
1807 offsetof(struct atm_set_connection_attributes_x, attr) -
1808 req->count * sizeof(req->attr[0]));
1809 uni_msg_destroy(msg);
1810 return;
1811 }
1812
1813 case USER_SIG_QUERY_STATE:
1814 {
1815 struct atm_epstate state;
1816
1817 strcpy(state.name, user->name);
1818 switch (user->state) {
1819
1820 case USER_NULL:
1821 if (user->accepted != NULL)
1822 state.state = ATM_A7;
1823 else
1824 state.state = ATM_A1;
1825 break;
1826
1827 case USER_OUT_PREPARING:
1828 state.state = ATM_A2;
1829 break;
1830
1831 case USER_OUT_WAIT_OK:
1832 case USER_OUT_WAIT_CONF:
1833 case USER_REL_WAIT_SCONF:
1834 case USER_REL_WAIT_CONF:
1835 case USER_REL_WAIT_CONN:
1836 state.state = ATM_A3;
1837 break;
1838
1839 case USER_ACTIVE:
1840 case USER_REL_WAIT:
1841 switch (user->config) {
1842
1843 case USER_P2P:
1844 state.state = ATM_A8;
1845 break;
1846
1847 case USER_ROOT:
1848 state.state = ATM_A9;
1849 break;
1850
1851 case USER_LEAF:
1852 state.state = ATM_A10;
1853 break;
1854 }
1855 break;
1856
1857 case USER_IN_PREPARING:
1858 state.state = ATM_A4;
1859 break;
1860
1861 case USER_IN_WAITING:
1862 state.state = ATM_A5;
1863 break;
1864
1865 case USER_IN_ARRIVED:
1866 case USER_IN_WAIT_REJ:
1867 case USER_IN_WAIT_ACC:
1868 state.state = ATM_A6;
1869 break;
1870
1871 case USER_IN_ACCEPTING:
1872 case USER_REL_WAIT_SCOMP:
1873 state.state = ATM_A7;
1874 break;
1875 }
1876 cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state));
1877 return;
1878 }
1879
1880 case USER_SIG_GET_LOCAL_PORT_INFO:
1881 {
1882 struct uni_msg *msg = arg;
1883 struct atm_port_list *list;
1884 size_t list_len;
1885
1886 list = cc_get_local_port_info(user->cc,
1887 uni_msg_rptr(msg, struct atm_get_local_port_info *)->port,
1888 &list_len);
1889 uni_msg_destroy(msg);
1890 if (list == NULL) {
1891 cc_user_err(user, ATMERR_NOMEM);
1892 return;
1893 }
1894 cc_user_ok(user, ATMRESP_PORTS, list, list_len);
1895 CCFREE(list);
1896 return;
1897 }
1898
1899 case USER_SIG_ABORT_CONNECTION:
1900 {
1901 struct uni_msg *msg = arg;
1902 struct atm_abort_connection *abo = uni_msg_rptr(msg,
1903 struct atm_abort_connection *);
1904
1905 cc_user_abort(user, &abo->cause);
1906 uni_msg_destroy(msg);
1907 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1908 return;
1909 }
1910
1911 }
1912 if (user->cc->log & CCLOG_USER_SIG)
1913 cc_user_log(user, "bad signal=%u in state=%u",
1914 sig, user->state);
1915 return;
1916
1917 bad_state:
1918 if (user->cc->log & CCLOG_USER_SIG)
1919 cc_user_log(user, "bad state=%u for signal=%u",
1920 user->state, sig);
1921 return;
1922 }
Cache object: dc128a21da45be4f1ae1cbfb3469ff83
|