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*/
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			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}
1923