1/*
2* Copyright (c) 2004
3*	Hartmut Brandt
4*	All rights reserved.
5*
6* Author: Harti Brandt <harti@freebsd.org>
7*
8* Redistribution of this software and documentation and use in source and
9* binary forms, with or without modification, are permitted provided that
10* the following conditions are met:
11*
12* 1. Redistributions of source code or documentation must retain the above
13*    copyright notice, this list of conditions and the following disclaimer.
14* 2. Redistributions in binary form must reproduce the above copyright
15*    notice, this list of conditions and the following disclaimer in the
16*    documentation and/or other materials provided with the distribution.
17*
18* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
19* AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
22* THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
23* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*
30* $Begemot: libunimsg/netnatm/api/cc_data.c,v 1.1 2004/07/08 08:21:50 brandt Exp $
31*
32* ATM API as defined per af-saa-0108
33*/
34#include <netnatm/unimsg.h>
35#include <netnatm/msg/unistruct.h>
36#include <netnatm/msg/unimsglib.h>
37#include <netnatm/api/unisap.h>
38#include <netnatm/sig/unidef.h>
39#include <netnatm/api/atmapi.h>
40#include <netnatm/api/ccatm.h>
41#include <netnatm/api/ccpriv.h>
42
43/*
44 * Create a new call control instance
45 */
46struct ccdata *
47cc_create(const struct cc_funcs *vtab)
48{
49	struct ccdata *cc;
50
51	cc = CCMALLOC(sizeof(*cc));
52	if (cc == NULL)
53		return (NULL);
54
55	LIST_INIT(&cc->user_list);
56	TAILQ_INIT(&cc->port_list);
57	LIST_INIT(&cc->orphaned_conns);
58	TAILQ_INIT(&cc->sigs);
59	TAILQ_INIT(&cc->def_sigs);
60	TAILQ_INIT(&cc->free_sigs);
61	cc->funcs = vtab;
62	cc->cookie = 0;
63
64	return (cc);
65}
66
67/*
68 * Reset everything the hard way by just freeing the data
69 */
70void
71cc_reset(struct ccdata *cc)
72{
73
74	while (!LIST_EMPTY(&cc->user_list))
75		cc_user_destroy(LIST_FIRST(&cc->user_list));
76
77	while (!TAILQ_EMPTY(&cc->port_list))
78		cc_port_destroy(TAILQ_FIRST(&cc->port_list), 1);
79
80	while (!LIST_EMPTY(&cc->orphaned_conns))
81		cc_conn_destroy(LIST_FIRST(&cc->orphaned_conns));
82
83	CCASSERT(LIST_EMPTY(&cc->user_list),
84	    ("user list not empty"));
85	CCASSERT(LIST_EMPTY(&cc->orphaned_conns),
86	    ("still orphaned conns"));
87
88	cc_sig_flush_all(cc);
89
90	cc->cookie = 0;
91}
92
93/*
94 * Destroy a call control instance and free all data
95 */
96void
97cc_destroy(struct ccdata *cc)
98{
99
100	cc_reset(cc);
101	CCFREE(cc);
102}
103
104/*
105 * set/get logging flags
106 */
107void
108cc_set_log(struct ccdata *cc, u_int flags)
109{
110	cc->log = flags;
111}
112u_int
113cc_get_log(const struct ccdata *cc)
114{
115	return (cc->log);
116}
117
118/* get extended status */
119int
120cc_get_extended_status(const struct ccdata *cc, struct atm_exstatus *status,
121    struct atm_exstatus_ep **pep, struct atm_exstatus_port **pport,
122    struct atm_exstatus_conn **pconn, struct atm_exstatus_party **pparty)
123{
124	const struct ccuser *user;
125	const struct ccport *port;
126	const struct ccconn *conn;
127	const struct ccparty *party;
128	struct atm_exstatus_ep *eep;
129	struct atm_exstatus_port *eport;
130	struct atm_exstatus_conn *econn;
131	struct atm_exstatus_party *eparty;
132
133	/* count and allocate */
134	status->neps = 0;
135	LIST_FOREACH(user, &cc->user_list, node_link)
136		status->neps++;
137
138	status->nports = 0;
139	status->nconns = 0;
140	status->nparties = 0;
141	LIST_FOREACH(conn, &cc->orphaned_conns, port_link) {
142		status->nconns++;
143		LIST_FOREACH(party, &conn->parties, link)
144			status->nparties++;
145	}
146	TAILQ_FOREACH(port, &cc->port_list, node_link) {
147		status->nports++;
148		LIST_FOREACH(conn, &port->conn_list, port_link) {
149			status->nconns++;
150			LIST_FOREACH(party, &conn->parties, link)
151				status->nparties++;
152		}
153	}
154
155	*pep = CCMALLOC(sizeof(**pep) * status->neps);
156	*pport = CCMALLOC(sizeof(**pport) * status->nports);
157	*pconn = CCMALLOC(sizeof(**pconn) * status->nconns);
158	*pparty = CCMALLOC(sizeof(**pparty) * status->nparties);
159
160	if (*pep == NULL || *pport == NULL ||
161	    *pconn == NULL || *pparty == NULL) {
162		CCFREE(*pep);
163		CCFREE(*pport);
164		CCFREE(*pconn);
165		CCFREE(*pparty);
166		return (ENOMEM);
167	}
168
169	eep = *pep;
170	eport = *pport;
171	econn = *pconn;
172	eparty = *pparty;
173
174	/* collect information */
175	LIST_FOREACH(user, &cc->user_list, node_link) {
176		strcpy(eep->name, user->name);
177		eep->state = user->state;
178		eep++;
179	}
180
181	LIST_FOREACH(conn, &cc->orphaned_conns, port_link) {
182		econn->id = econn - *pconn;
183		econn->port = 0;
184		if (conn->user != NULL)
185			strcpy(econn->ep, conn->user->name);
186		else
187			econn->ep[0] = '\0';
188		econn->state = conn->state;
189		econn->cref = conn->cref.cref;
190		if (conn->cref.flag)
191			econn->cref |= (1 << 23);
192		LIST_FOREACH(party, &conn->parties, link) {
193			eparty->connid = econn - *pconn;
194			eparty->epref = party->epref.epref;
195			eparty->state = party->state;
196			eparty++;
197		}
198		econn++;
199	}
200
201	TAILQ_FOREACH(port, &cc->port_list, node_link) {
202		eport->portno = port->param.port;
203		eport->state = port->admin;
204		LIST_FOREACH(conn, &port->conn_list, port_link) {
205			econn->id = econn - *pconn;
206			econn->port = port->param.port;
207			if (conn->user != NULL)
208				strcpy(econn->ep, conn->user->name);
209			else
210				econn->ep[0] = '\0';
211			econn->state = conn->state;
212			econn->cref = conn->cref.cref;
213			if (conn->cref.flag)
214				econn->cref |= (1 << 23);
215			LIST_FOREACH(party, &conn->parties, link) {
216				eparty->connid = econn - *pconn;
217				eparty->epref = party->epref.epref;
218				eparty->state = party->state;
219				eparty++;
220			}
221			econn++;
222		}
223		eport++;
224	}
225	return (0);
226}
227