cc_user.c revision 131826
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.2 2004/07/08 09:17:18 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*/
53static const char *stab[] = {
54#define DEF(N) [N] = #N,
55	USER_STATES
56#undef DEF
57};
58
59const char *
60cc_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
67static __inline void
68set_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
78static __inline void
79cc_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
84static __inline void
85cc_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
91static __inline void
92cc_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*/
106struct ccuser *
107cc_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 */
132static void
133cc_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
157static void
158cc_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 */
198void
199cc_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 */
223static int
224addr_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 */
241static int
242check_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 */
252static void
253do_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 */
274static struct ccconn *
275cc_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 */
304static void
305cc_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 */
536static struct ccconn *
537cc_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 */
553static void
554cc_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
806static 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 */
838int
839cc_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 */
984static void
985cc_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*/
1016void
1017cc_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			cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1301
1302			set_state(user, USER_IN_WAITING);
1303			do_arrival(user);
1304			return;
1305		}
1306		conn->cause[0] = rej->cause;
1307		memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
1308		uni_msg_destroy(msg);
1309
1310		set_state(user, USER_IN_WAIT_REJ);
1311		cc_conn_sig(conn, CONN_SIG_REJECT, NULL);
1312
1313		return;
1314	    }
1315
1316
1317	  case USER_SIG_REJECT_OK:
1318		if (user->state != USER_IN_WAIT_REJ)
1319			goto bad_state;
1320		cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1321
1322		set_state(user, USER_IN_WAITING);
1323		do_arrival(user);
1324		return;
1325
1326
1327	  case USER_SIG_REJECT_ERR:
1328		if (user->state != USER_IN_WAIT_REJ)
1329			goto bad_state;
1330		cc_user_err(user, arg2);
1331
1332		if (arg == NULL)
1333			set_state(user, USER_IN_ARRIVED);
1334		else {
1335			set_state(user, USER_IN_WAITING);
1336			do_arrival(user);
1337		}
1338		return;
1339
1340
1341	  case USER_SIG_ACCEPT_INCOMING:
1342	    {
1343		/*
1344		 * User accepts call. This is done on the OLD user (i.e. the one
1345		 * sending the arrival), the message contains a pointer to the
1346		 * new endpoint.
1347		 */
1348		struct uni_msg *msg = arg;
1349		struct atm_accept_incoming_call *acc =
1350		    uni_msg_rptr(msg, struct atm_accept_incoming_call *);
1351		struct ccuser *newep;
1352
1353		if (user->state != USER_IN_ARRIVED) {
1354			uni_msg_destroy(msg);
1355			cc_user_err(user, ATMERR_BAD_STATE);
1356			return;
1357		}
1358		if (user->aborted) {
1359			/* connection has disappeared. Send an error
1360			 * to the user and lock whether there is another
1361			 * connection at this endpoint */
1362			cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1363
1364			set_state(user, USER_IN_WAITING);
1365			do_arrival(user);
1366			return;
1367		}
1368		acc->newep[sizeof(acc->newep) - 1] = '\0';
1369
1370		LIST_FOREACH(newep, &user->cc->user_list, node_link)
1371			if (strcmp(acc->newep, newep->name) == 0)
1372				break;
1373
1374		if (newep == NULL) {
1375			uni_msg_destroy(msg);
1376			cc_user_err(user, ATMERR_BAD_ENDPOINT);
1377			return;
1378		}
1379
1380		if (newep->state != USER_NULL || newep->accepted != NULL) {
1381			uni_msg_destroy(msg);
1382			cc_user_err(user, ATMERR_BAD_STATE);
1383			return;
1384		}
1385
1386		set_state(user, USER_IN_WAIT_ACC);
1387		cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep);
1388
1389		return;
1390	    }
1391
1392
1393	  case USER_SIG_ACCEPT_OK:
1394		if (user->state != USER_IN_WAIT_ACC)
1395			goto bad_state;
1396		cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1397
1398		set_state(user, USER_IN_WAITING);
1399		do_arrival(user);
1400		return;
1401
1402
1403	  case USER_SIG_ACCEPT_ERR:
1404		if (user->state != USER_IN_WAIT_ACC)
1405			goto bad_state;
1406		cc_user_err(user, arg2);
1407
1408		if (arg == NULL) {
1409			/* arg used as flag! */
1410			set_state(user, USER_IN_ARRIVED);
1411		} else {
1412			set_state(user, USER_IN_WAITING);
1413			do_arrival(user);
1414		}
1415		return;
1416
1417
1418	  case USER_SIG_ACCEPTING:
1419		if (user->state != USER_NULL)
1420			goto bad_state;
1421		set_state(user, USER_IN_ACCEPTING);
1422		return;
1423
1424
1425	  case USER_SIG_SETUP_COMPL:
1426	    {
1427		struct ccconn *conn = TAILQ_FIRST(&user->connq);
1428
1429		if (user->state != USER_IN_ACCEPTING)
1430			goto bad_state;
1431
1432		user->state = USER_ACTIVE;
1433		if (conn->bearer.cfg == UNI_BEARER_P2P) {
1434			struct atm_p2p_call_active *act;
1435
1436			user->config = USER_P2P;
1437			act = CCZALLOC(sizeof(*act));
1438			if (act == NULL)
1439				return;
1440			act->connid = conn->connid;
1441			cc_user_send(user, ATMOP_P2P_CALL_ACTIVE,
1442			    act, sizeof(*act));
1443			CCFREE(act);
1444		} else {
1445			struct atm_p2mp_call_active *act;
1446
1447			user->config = USER_LEAF;
1448			act = CCZALLOC(sizeof(*act));
1449			if (act == NULL)
1450				return;
1451			act->connid = conn->connid;
1452			cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE,
1453			    act, sizeof(*act));
1454			CCFREE(act);
1455		}
1456		return;
1457	    }
1458
1459
1460	  case USER_SIG_CALL_RELEASE:
1461	    {
1462		struct uni_msg *msg = arg;
1463		struct atm_call_release *api = uni_msg_rptr(msg,
1464		    struct atm_call_release *);
1465		struct ccconn *conn;
1466
1467		conn = TAILQ_FIRST(&user->connq);
1468		switch (user->state) {
1469
1470		  case USER_OUT_WAIT_OK:	/* U2/A3 */
1471			/* wait for CONN_OK first */
1472			conn->cause[0] = api->cause[0];
1473			conn->cause[1] = api->cause[1];
1474			set_state(user, USER_REL_WAIT_CONN);
1475			break;
1476
1477		  case USER_OUT_WAIT_CONF:	/* U3/A3 */
1478			/* wait for SETUP.confirm first */
1479			conn->cause[0] = api->cause[0];
1480			conn->cause[1] = api->cause[1];
1481			set_state(user, USER_REL_WAIT_SCONF);
1482			break;
1483
1484		  case USER_IN_ACCEPTING:	/* U11/A7 */
1485			conn->cause[0] = api->cause[0];
1486			conn->cause[1] = api->cause[1];
1487			set_state(user, USER_REL_WAIT_SCOMP);
1488			cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
1489			break;
1490
1491		  case USER_ACTIVE:		/* U4/A8,A9,A10 */
1492			conn->cause[0] = api->cause[0];
1493			conn->cause[1] = api->cause[1];
1494			set_state(user, USER_REL_WAIT);
1495			cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
1496			break;
1497
1498		  default:
1499			uni_msg_destroy(msg);
1500			cc_user_err(user, ATMERR_BAD_STATE);
1501			goto bad_state;
1502		}
1503		uni_msg_destroy(msg);
1504		return;
1505	    }
1506
1507
1508	  case USER_SIG_RELEASE_CONFIRM:
1509	    {
1510		struct atm_call_release *ind;
1511
1512		switch (user->state) {
1513
1514		  case USER_OUT_WAIT_CONF:	/* U3/A3 */
1515		  case USER_ACTIVE:		/* U4/A8,A9,A10 */
1516			cc_user_reset(user);
1517			break;
1518
1519		  case USER_REL_WAIT:		/* U5 /A8,A9,A10 */
1520		  case USER_REL_WAIT_SCOMP:	/* U12/A7 */
1521		  case USER_REL_WAIT_SCONF:	/* U13/A3 */
1522		  case USER_REL_WAIT_CONF:	/* U14/A3 */
1523			cc_user_reset(user);
1524			cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1525			return;
1526
1527		  case USER_IN_ACCEPTING:	/* U11/A7 */
1528			cc_user_reset(user);
1529			break;
1530
1531		  default:
1532			goto bad_state;
1533		}
1534
1535		ind = CCZALLOC(sizeof(*ind));
1536		if (ind == NULL)
1537			return;
1538		memcpy(ind->cause, user->cause, sizeof(ind->cause));
1539		cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind));
1540		CCFREE(ind);
1541		return;
1542	    }
1543
1544
1545	  case USER_SIG_RELEASE_ERR:
1546		switch (user->state) {
1547
1548		  case USER_REL_WAIT:		/* U5/A8,A9,A10 */
1549			set_state(user, USER_ACTIVE);
1550			cc_user_err(user, ATM_MKUNIERR(arg2));
1551			break;
1552
1553		  case USER_REL_WAIT_CONF:	/* U14/A3 */
1554			cc_user_err(user, ATM_MKUNIERR(arg2));
1555			cc_user_active(user);
1556			break;
1557
1558		  case USER_REL_WAIT_SCOMP:	/* U12/A7 */
1559			set_state(user, USER_IN_ACCEPTING);
1560			cc_user_err(user, ATM_MKUNIERR(arg2));
1561			break;
1562
1563		  default:
1564			goto bad_state;
1565		}
1566		return;
1567
1568
1569	  case USER_SIG_ADD_PARTY:
1570	    {
1571		struct uni_msg *msg = arg;
1572		struct atm_add_party *add = uni_msg_rptr(msg,
1573		    struct atm_add_party *);
1574		struct ccconn *conn;
1575
1576		if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
1577			uni_msg_destroy(msg);
1578			cc_user_err(user, ATMERR_BAD_STATE);
1579			return;
1580		}
1581
1582		if (add->leaf_ident == 0 || add->leaf_ident >= 32786) {
1583			uni_msg_destroy(msg);
1584			cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
1585			return;
1586		}
1587
1588		conn = TAILQ_FIRST(&user->connq);
1589		conn->called = add->called;
1590
1591		cc_conn_sig(conn, CONN_SIG_ADD_PARTY,
1592		    (void *)(uintptr_t)add->leaf_ident);
1593
1594		uni_msg_destroy(msg);
1595		return;
1596	    }
1597
1598
1599	  case USER_SIG_ADD_PARTY_ERR:
1600		if (user->state != USER_ACTIVE)
1601			goto bad_state;
1602		cc_user_err(user, arg2);
1603		return;
1604
1605
1606	  case USER_SIG_ADD_PARTY_OK:
1607		if (user->state != USER_ACTIVE)
1608			goto bad_state;
1609		cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1610		return;
1611
1612
1613	  case USER_SIG_ADD_PARTY_ACK:
1614	    {
1615		u_int leaf_ident = arg2;
1616		struct atm_add_party_success *succ;
1617
1618		if (user->state != USER_ACTIVE)
1619			goto bad_state;
1620
1621		succ = CCZALLOC(sizeof(*succ));
1622		if (succ == NULL)
1623			return;
1624
1625		succ->leaf_ident = leaf_ident;
1626		cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS,
1627		    succ, sizeof(*succ));
1628
1629		CCFREE(succ);
1630		return;
1631	    }
1632
1633
1634	  case USER_SIG_ADD_PARTY_REJ:
1635	    {
1636		u_int leaf_ident = arg2;
1637		struct atm_add_party_reject *reject;
1638
1639		if (user->state != USER_ACTIVE)
1640			goto bad_state;
1641
1642		reject = CCZALLOC(sizeof(*reject));
1643		if (reject == NULL)
1644			return;
1645
1646		reject->leaf_ident = leaf_ident;
1647		reject->cause = user->cause[0];
1648		cc_user_send(user, ATMOP_ADD_PARTY_REJECT,
1649		    reject, sizeof(*reject));
1650
1651		CCFREE(reject);
1652		return;
1653	    }
1654
1655
1656	  case USER_SIG_DROP_PARTY:
1657	    {
1658		struct uni_msg *msg = arg;
1659		struct atm_drop_party *drop = uni_msg_rptr(msg,
1660		    struct atm_drop_party *);
1661		struct ccconn *conn;
1662
1663		if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
1664			uni_msg_destroy(msg);
1665			cc_user_err(user, ATMERR_BAD_STATE);
1666			return;
1667		}
1668
1669		if (drop->leaf_ident >= 32786) {
1670			uni_msg_destroy(msg);
1671			cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
1672			return;
1673		}
1674
1675		conn = TAILQ_FIRST(&user->connq);
1676		conn->cause[0] = drop->cause;
1677		memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
1678
1679		cc_conn_sig(conn, CONN_SIG_DROP_PARTY,
1680		    (void *)(uintptr_t)drop->leaf_ident);
1681
1682		uni_msg_destroy(msg);
1683		return;
1684	    }
1685
1686
1687	  case USER_SIG_DROP_PARTY_ERR:
1688		if (user->state != USER_ACTIVE)
1689			goto bad_state;
1690		cc_user_err(user, arg2);
1691		return;
1692
1693
1694	  case USER_SIG_DROP_PARTY_OK:
1695		if (user->state != USER_ACTIVE)
1696			goto bad_state;
1697		cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1698		return;
1699
1700
1701	  case USER_SIG_DROP_PARTY_IND:
1702	    {
1703		u_int leaf_ident = arg2;
1704		struct atm_drop_party *drop;
1705
1706		if (user->state != USER_ACTIVE)
1707			goto bad_state;
1708
1709		drop = CCZALLOC(sizeof(*drop));
1710		if (drop == NULL)
1711			return;
1712
1713		drop->leaf_ident = leaf_ident;
1714		drop->cause = user->cause[0];
1715		cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop));
1716
1717		CCFREE(drop);
1718		return;
1719	    }
1720
1721
1722	  case USER_SIG_QUERY_ATTR:
1723	    {
1724		struct uni_msg *msg = arg;
1725		struct atm_query_connection_attributes *req;
1726		struct ccconn *conn;
1727
1728		if (user->aborted) {
1729			cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1730			uni_msg_destroy(msg);
1731			return;
1732		}
1733		conn = cc_query_check(user);
1734		if (conn == NULL) {
1735			cc_user_err(user, ATMERR_BAD_STATE);
1736			uni_msg_destroy(msg);
1737			return;
1738		}
1739		req = uni_msg_rptr(msg,
1740		    struct atm_query_connection_attributes *);
1741		cc_attr_query(user, conn, &req->attr, 1);
1742		uni_msg_destroy(msg);
1743		return;
1744	    }
1745
1746	  case USER_SIG_QUERY_ATTR_X:
1747	    {
1748		struct uni_msg *msg = arg;
1749		struct atm_query_connection_attributes_x *req;
1750		struct ccconn *conn;
1751
1752		conn = cc_query_check(user);
1753		if (conn == NULL) {
1754			cc_user_err(user, ATMERR_BAD_STATE);
1755			uni_msg_destroy(msg);
1756			return;
1757		}
1758		req = uni_msg_rptr(msg,
1759		    struct atm_query_connection_attributes_x *);
1760		cc_attr_query(user, conn, req->attr, req->count);
1761		uni_msg_destroy(msg);
1762		return;
1763	    }
1764
1765	  case USER_SIG_SET_ATTR:
1766	    {
1767		struct uni_msg *msg = arg;
1768		struct atm_set_connection_attributes *req;
1769		struct ccconn *conn;
1770
1771		if (user->aborted) {
1772			cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
1773			uni_msg_destroy(msg);
1774			return;
1775		}
1776		conn = cc_set_check(user);
1777		if (conn == NULL) {
1778			cc_user_err(user, ATMERR_BAD_STATE);
1779			uni_msg_destroy(msg);
1780			return;
1781		}
1782		req = uni_msg_rptr(msg, struct atm_set_connection_attributes *);
1783		cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1),
1784		    uni_msg_len(msg) - sizeof(*req));
1785		uni_msg_destroy(msg);
1786		return;
1787	    }
1788
1789	  case USER_SIG_SET_ATTR_X:
1790	    {
1791		struct uni_msg *msg = arg;
1792		struct atm_set_connection_attributes_x *req;
1793		struct ccconn *conn;
1794
1795		conn = cc_set_check(user);
1796		if (conn == NULL) {
1797			cc_user_err(user, ATMERR_BAD_STATE);
1798			uni_msg_destroy(msg);
1799			return;
1800		}
1801		req = uni_msg_rptr(msg,
1802		    struct atm_set_connection_attributes_x *);
1803		cc_attr_set(user, conn, req->attr, req->count,
1804		    (u_char *)req->attr + req->count * sizeof(req->attr[0]),
1805		    uni_msg_len(msg) -
1806		    offsetof(struct atm_set_connection_attributes_x, attr) -
1807		    req->count * sizeof(req->attr[0]));
1808		uni_msg_destroy(msg);
1809		return;
1810	    }
1811
1812	  case USER_SIG_QUERY_STATE:
1813	    {
1814		struct atm_epstate state;
1815
1816		strcpy(state.name, user->name);
1817		switch (user->state) {
1818
1819		  case USER_NULL:
1820			if (user->accepted != NULL)
1821				state.state = ATM_A7;
1822			else
1823				state.state = ATM_A1;
1824			break;
1825
1826		  case USER_OUT_PREPARING:
1827			state.state = ATM_A2;
1828			break;
1829
1830		  case USER_OUT_WAIT_OK:
1831		  case USER_OUT_WAIT_CONF:
1832		  case USER_REL_WAIT_SCONF:
1833		  case USER_REL_WAIT_CONF:
1834		  case USER_REL_WAIT_CONN:
1835			state.state = ATM_A3;
1836			break;
1837
1838		  case USER_ACTIVE:
1839		  case USER_REL_WAIT:
1840			switch (user->config) {
1841
1842			  case USER_P2P:
1843				state.state = ATM_A8;
1844				break;
1845
1846			  case USER_ROOT:
1847				state.state = ATM_A9;
1848				break;
1849
1850			  case USER_LEAF:
1851				state.state = ATM_A10;
1852				break;
1853			}
1854			break;
1855
1856		  case USER_IN_PREPARING:
1857			state.state = ATM_A4;
1858			break;
1859
1860		  case USER_IN_WAITING:
1861			state.state = ATM_A5;
1862			break;
1863
1864		  case USER_IN_ARRIVED:
1865		  case USER_IN_WAIT_REJ:
1866		  case USER_IN_WAIT_ACC:
1867			state.state = ATM_A6;
1868			break;
1869
1870		  case USER_IN_ACCEPTING:
1871		  case USER_REL_WAIT_SCOMP:
1872			state.state = ATM_A7;
1873			break;
1874		}
1875		cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state));
1876		return;
1877	    }
1878
1879	  case USER_SIG_GET_LOCAL_PORT_INFO:
1880	    {
1881		struct uni_msg *msg = arg;
1882		struct atm_port_list *list;
1883		size_t list_len;
1884
1885		list = cc_get_local_port_info(user->cc,
1886		    uni_msg_rptr(msg, struct atm_get_local_port_info *)->port,
1887		    &list_len);
1888		uni_msg_destroy(msg);
1889		if (list == NULL) {
1890			cc_user_err(user, ATMERR_NOMEM);
1891			return;
1892		}
1893		cc_user_ok(user, ATMRESP_PORTS, list, list_len);
1894		CCFREE(list);
1895		return;
1896	    }
1897
1898	  case USER_SIG_ABORT_CONNECTION:
1899	    {
1900		struct uni_msg *msg = arg;
1901		struct atm_abort_connection *abo = uni_msg_rptr(msg,
1902		    struct atm_abort_connection *);
1903
1904		cc_user_abort(user, &abo->cause);
1905		uni_msg_destroy(msg);
1906		cc_user_ok(user, ATMRESP_NONE, NULL, 0);
1907		return;
1908	    }
1909
1910	}
1911	if (user->cc->log & CCLOG_USER_SIG)
1912		cc_user_log(user, "bad signal=%u in state=%u",
1913		    sig, user->state);
1914	return;
1915
1916  bad_state:
1917	if (user->cc->log & CCLOG_USER_SIG)
1918		cc_user_log(user, "bad state=%u for signal=%u",
1919		    user->state, sig);
1920	return;
1921}
1922