1/*
2 * Copyright (c) 2003-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/ccpriv.h,v 1.2 2005/05/23 11:49:17 brandt_h Exp $
31 *
32 * ATM API as defined per af-saa-0108
33 *
34 * Private declarations.
35 */
36#ifdef _KERNEL
37#ifdef __FreeBSD__
38#include <netgraph/atm/ccatm/ng_ccatm_cust.h>
39#endif
40#else	/* !_KERNEL */
41#include "cccust.h"
42#endif
43
44struct ccuser;
45struct ccconn;
46struct ccaddr;
47struct ccport;
48struct ccdata;
49struct ccsig;
50struct ccparty;
51
52LIST_HEAD(ccuser_list, ccuser);
53LIST_HEAD(ccconn_list, ccconn);
54TAILQ_HEAD(ccaddr_list, ccaddr);
55TAILQ_HEAD(ccport_list, ccport);
56TAILQ_HEAD(ccsig_list, ccsig);
57LIST_HEAD(ccparty_list, ccparty);
58
59/*
60 * Private node data.
61 */
62struct ccdata {
63	struct ccuser_list	user_list;	/* instance list */
64	struct ccport_list	port_list;	/* list of ports */
65	struct ccconn_list	orphaned_conns;	/* list of connections */
66	struct ccsig_list	sigs;		/* current signals */
67	struct ccsig_list	def_sigs;	/* deferred signals */
68	struct ccsig_list	free_sigs;	/* free signals */
69
70	const struct cc_funcs	*funcs;
71	uint32_t		cookie;		/* cookie generator */
72	u_int			log;		/* logging flags */
73};
74
75/* retrieve info on local ports */
76struct atm_port_list *cc_get_local_port_info(struct ccdata *,
77    u_int, size_t *);
78
79/* log */
80#ifdef CCATM_DEBUG
81#if defined(__GNUC__) && __GNUC__ < 3
82#define	cc_log(CC, FMT, ARGS...) do {					\
83	(CC)->funcs->log("%s (data=%p): " FMT, __FUNCTION__,		\
84	    (CC) , ## ARGS);						\
85    } while (0)
86#else
87#define	cc_log(CC, FMT, ...) do {					\
88	(CC)->funcs->log("%s (data=%p): " FMT, __func__,		\
89	    (CC), __VA_ARGS__);						\
90    } while (0)
91#endif
92#else
93#if defined(__GNUC__) && __GNUC__ < 3
94#define	cc_log(CC, FMT, ARGS...) do { } while (0)
95#else
96#define	cc_log(CC, FMT, ...) do { } while (0)
97#endif
98#endif
99
100/*
101 * structure to remember cookies for outstanding requests
102 * we also remember the request itself but don't use it.
103 */
104struct ccreq {
105	TAILQ_ENTRY(ccreq)	link;
106	uint32_t		cookie;
107	uint32_t		req;
108	struct ccconn		*conn;
109};
110TAILQ_HEAD(ccreq_list, ccreq);
111
112/*
113 * Port data. Each port has one UNI stack below.
114 * The port number is in param.port. The number is assigned when the
115 * hook to the uni is connected. This hook has the name 'uni<port>'.
116 */
117struct ccport {
118	void		*uarg;		/* hook to UNI protocol */
119	struct ccdata 	*cc;		/* back pointer to node */
120	enum {
121		CCPORT_STOPPED,		/* halted */
122		CCPORT_RUNNING,		/* ok */
123	}		admin;		/* admin status */
124	struct ccconn_list conn_list;	/* list of connections */
125	struct ccaddr_list addr_list;	/* list of network addresses */
126	struct atm_port_info param;	/* parameters */
127
128	/* list of outstanding requests */
129	struct ccreq_list	cookies;
130
131	TAILQ_ENTRY(ccport) node_link;
132};
133
134#ifdef CCATM_DEBUG
135#if defined(__GNUC__) && __GNUC__ < 3
136#define	cc_port_log(P, FMT, ARGS...) do {				\
137	(P)->cc->funcs->log("%s (port=%p/%u): " FMT, __FUNCTION__,	\
138	    (P), (P)->param.port , ## ARGS);				\
139    } while (0)
140#else
141#define	cc_port_log(P, FMT, ...) do {					\
142	(P)->cc->funcs->log("%s (port=%p/%u): " FMT, __func__,		\
143	    (P), (P)->param.port, __VA_ARGS__);				\
144    } while (0)
145#endif
146#else
147#if defined(__GNUC__) && __GNUC__ < 3
148#define	cc_port_log(P, FMT, ARGS...) do { } while (0)
149#else
150#define	cc_port_log(P, FMT, ...) do { } while (0)
151#endif
152#endif
153
154#define CONN_STATES					\
155	DEF(CONN_NULL)			/*  C0 */	\
156	DEF(CONN_OUT_PREPARING)		/*  C1 */	\
157	DEF(CONN_OUT_WAIT_CREATE)	/*  C2 */	\
158	DEF(CONN_OUT_WAIT_OK)		/*  C3 */	\
159	DEF(CONN_OUT_WAIT_CONF)		/*  C4 */	\
160							\
161	DEF(CONN_ACTIVE)		/*  C5 */	\
162							\
163	DEF(CONN_IN_PREPARING)		/* C10 */	\
164	DEF(CONN_IN_WAITING)		/* C21 */	\
165	DEF(CONN_IN_ARRIVED)		/* C11 */	\
166	DEF(CONN_IN_WAIT_ACCEPT_OK)	/* C12 */	\
167	DEF(CONN_IN_WAIT_COMPL)		/* C13 */	\
168							\
169	DEF(CONN_REJ_WAIT_OK)		/* C14 */	\
170	DEF(CONN_REL_IN_WAIT_OK)	/* C15 */	\
171	DEF(CONN_REL_WAIT_OK)		/* C20 */	\
172							\
173	DEF(CONN_AB_WAIT_REQ_OK)	/* C33 */	\
174	DEF(CONN_AB_WAIT_RESP_OK)	/* C34 */	\
175	DEF(CONN_AB_FLUSH_IND)		/* C35 */	\
176	DEF(CONN_OUT_WAIT_DESTROY)	/* C37 */
177
178enum conn_state {
179#define DEF(N) N,
180	CONN_STATES
181#undef DEF
182};
183
184#define	CONN_SIGS							\
185	DEF(CONNECT_OUTGOING)	/* U */					\
186	DEF(ARRIVAL)		/* U */					\
187	DEF(RELEASE)		/* U */					\
188	DEF(REJECT)		/* U */					\
189	DEF(ACCEPT)		/* U newuser */				\
190	DEF(ADD_PARTY)		/* U ident */				\
191	DEF(DROP_PARTY)		/* U ident */				\
192	DEF(USER_ABORT)		/* U */					\
193									\
194	DEF(CREATED)		/* P msg */				\
195	DEF(DESTROYED)		/* P */					\
196	DEF(SETUP_CONFIRM)	/* P msg */				\
197	DEF(SETUP_IND)		/* P msg */				\
198	DEF(SETUP_COMPL)	/* P msg */				\
199	DEF(PROC_IND)		/* P msg */				\
200	DEF(ALERTING_IND)	/* P msg */				\
201	DEF(REL_CONF)		/* P msg */				\
202	DEF(REL_IND)		/* P msg */				\
203	DEF(PARTY_CREATED)	/* P msg */				\
204	DEF(PARTY_DESTROYED)	/* P msg */				\
205	DEF(PARTY_ALERTING_IND)	/* P msg */				\
206	DEF(PARTY_ADD_ACK_IND)	/* P msg */				\
207	DEF(PARTY_ADD_REJ_IND)	/* P msg */				\
208	DEF(DROP_PARTY_IND)	/* P msg */				\
209	DEF(DROP_PARTY_ACK_IND)	/* P msg */				\
210									\
211	DEF(OK)			/* P msg */				\
212	DEF(ERROR)		/* P msg */
213
214enum conn_sig {
215#define DEF(NAME) CONN_SIG_##NAME,
216CONN_SIGS
217#undef DEF
218};
219extern const char *const cc_conn_sigtab[];
220
221/*
222 * This describes a connection and must be in sync with the UNI
223 * stack.
224 */
225struct ccconn {
226	enum conn_state		state;	/* API state of the connection */
227	struct ccdata		*cc;	/* owner node */
228	struct ccport		*port;	/* the port we belong to */
229	struct ccuser		*user;	/* user instance we belong to */
230    	TAILQ_ENTRY(ccconn)	connq_link;	/* queue of the owner */
231	LIST_ENTRY(ccconn) 	port_link;	/* link in list of port */
232	struct uni_cref		cref;
233	uint8_t			reason;
234	struct ccuser		*acceptor;
235
236	/* attributes */
237	uint32_t		blli_selector;
238	struct uni_ie_blli	blli[UNI_NUM_IE_BLLI];
239
240	struct uni_ie_bearer	bearer;
241	struct uni_ie_traffic	traffic;
242	struct uni_ie_qos	qos;
243	struct uni_ie_exqos	exqos;
244	struct uni_ie_called	called;
245	struct uni_ie_calledsub	calledsub;
246	struct uni_ie_aal	aal;
247	struct uni_ie_epref	epref;
248	struct uni_ie_conned	conned;
249	struct uni_ie_connedsub	connedsub;
250	struct uni_ie_eetd	eetd;
251	struct uni_ie_abrsetup	abrsetup;
252	struct uni_ie_abradd	abradd;
253	struct uni_ie_mdcr	mdcr;
254
255	struct uni_ie_calling	calling;
256	struct uni_ie_callingsub callingsub;
257	struct uni_ie_connid	connid;
258	struct uni_ie_tns	tns[UNI_NUM_IE_TNS];
259	struct uni_ie_atraffic	atraffic;
260	struct uni_ie_mintraffic mintraffic;
261	struct uni_ie_cscope	cscope;
262	struct uni_ie_bhli	bhli;
263
264	/* bit mask of written attributes in A6 */
265	u_int			dirty_attr;
266
267	struct uni_ie_cause	cause[2];
268
269	struct ccparty_list	parties;
270};
271
272/* dirty attribute mask values */
273enum {
274	CCDIRTY_AAL		= 0x0001,
275	CCDIRTY_BLLI		= 0x0002,
276	CCDIRTY_CONNID		= 0x0004,
277	CCDIRTY_NOTIFY		= 0x0008,	/* XXX */
278	CCDIRTY_EETD		= 0x0010,
279	CCDIRTY_GIT		= 0x0020,	/* XXX */
280	CCDIRTY_UU		= 0x0040,	/* XXX */
281	CCDIRTY_TRAFFIC		= 0x0080,
282	CCDIRTY_EXQOS		= 0x0100,
283	CCDIRTY_ABRSETUP	= 0x0200,
284	CCDIRTY_ABRADD		= 0x0400,
285};
286
287/* set conn to new state */
288void cc_conn_set_state(struct ccconn *, enum conn_state);
289
290/* return string for state */
291const char *cc_conn_state2str(u_int);
292
293/* connect connection to user */
294void cc_connect_to_user(struct ccconn *, struct ccuser *);
295
296/* disconnect from the user */
297void cc_disconnect_from_user(struct ccconn *);
298
299/* abort the connection */
300void cc_conn_abort(struct ccconn *, int);
301
302/* destroy a connection */
303void cc_conn_destroy(struct ccconn *);
304
305/* create a connection */
306struct ccconn *cc_conn_create(struct ccdata *);
307
308/* assign to port */
309void cc_conn_ins_port(struct ccconn *, struct ccport *);
310
311/* remove from port */
312void cc_conn_rem_port(struct ccconn *);
313
314/* dispatch a connection to a user or reject it */
315void cc_conn_dispatch(struct ccconn *);
316
317/* disconnect from acceptor */
318void cc_conn_reset_acceptor(struct ccconn *);
319
320/* log on a connection */
321#ifdef CCATM_DEBUG
322#if defined(__GNUC__) && __GNUC__ < 3
323#define	cc_conn_log(C, FMT, ARGS...) do {				\
324	(C)->cc->funcs->log("%s (conn=%p): " FMT, __FUNCTION__,		\
325	    (C) , ## ARGS);						\
326    } while (0)
327#else
328#define	cc_conn_log(C, FMT, ...) do {					\
329	(C)->cc->funcs->log("%s (conn=%p): " FMT, __func__,		\
330	    (C), __VA_ARGS__);						\
331    } while (0)
332#endif
333#else
334#if defined(__GNUC__) && __GNUC__ < 3
335#define	cc_conn_log(C, FMT, ARGS...) do { } while (0)
336#else
337#define	cc_conn_log(C, FMT, ...) do { } while (0)
338#endif
339#endif
340
341/* handle signal to connection */
342void cc_conn_sig_handle(struct ccconn *, enum conn_sig, void *arg, u_int iarg);
343
344/*
345 * Mp connection parties
346 */
347#define	PARTY_STATES							\
348	DEF(NULL)		/* 0 created */				\
349	DEF(ACTIVE)		/* 1 active */				\
350	DEF(ADD_WAIT_CREATE)	/* 2 wait for PARTY_CREATE */		\
351	DEF(ADD_WAIT_OK)	/* 3 wait for OK for ADD.request */	\
352	DEF(ADD_WAIT_ACK)	/* 4 wait for ADD.ack/rej */		\
353	DEF(DROP_WAIT_OK)	/* 5 wait for OK for DROP.request */	\
354	DEF(DROP_WAIT_ACK)	/* 6 wait for DROP.ack */		\
355	DEF(WAIT_DESTROY)	/* 7 wait for destroy */		\
356	DEF(WAIT_SETUP_COMPL)	/* 8 wait for setup.complete */		\
357	DEF(WAIT_DROP_ACK_OK)	/* 9 wait for OK for DROP_ACK.request */\
358	DEF(WAIT_SETUP_CONF)	/* 10 wait for setup.confirm */		\
359	DEF(ADD_DROP_WAIT_OK)	/* 11 wait for ok to DROP.request */	\
360	DEF(ADD_DROPACK_WAIT_OK)/* 12 wait for ok to DROP_ACK.req */
361
362enum party_state {
363#define	DEF(N)	PARTY_##N,
364PARTY_STATES
365#undef DEF
366};
367
368struct ccparty {
369	struct ccconn		*conn;	/* owner */
370	LIST_ENTRY(ccparty)	link;
371	enum party_state	state;
372	struct uni_ie_called	called;
373	struct uni_ie_epref	epref;
374};
375
376/* set party to new state */
377void cc_party_set_state(struct ccparty *, enum party_state);
378
379/* return string for state */
380const char *cc_party_state2str(u_int);
381
382/* create new party */
383struct ccparty *cc_party_create(struct ccconn *, u_int ident, u_int flag);
384
385/* log on a party */
386#ifdef CCATM_DEBUG
387#if defined(__GNUC__) && __GNUC__ < 3
388#define	cc_party_log(P, FMT, ARGS...) do {				\
389	(P)->conn->cc->funcs->log("%s (conn=%p, party=%p): " FMT,	\
390	    __FUNCTION__, (P)->conn, (P) , ## ARGS);			\
391    } while (0)
392#else
393#define	cc_party_log(P, FMT, ...) do {					\
394	(P)->conn->cc->funcs->log("%s (conn=%p, party=%p): " FMT,	\
395	__func__, (P)->conn, (P), __VA_ARGS__);				\
396    } while (0)
397#endif
398#else
399#if defined(__GNUC__) && __GNUC__ < 3
400#define	cc_party_log(P, FMT, ARGS...) do { } while (0)
401#else
402#define	cc_party_log(P, FMT, ...) do { } while (0)
403#endif
404#endif
405
406/*
407 * This is kind of a user socket, i.e. the entity managed towards the
408 * upper layer.
409 */
410#define USER_STATES							\
411	DEF(USER_NULL)		/* U0 none */				\
412	DEF(USER_OUT_PREPARING)	/* U1 process set/query requests */	\
413	DEF(USER_OUT_WAIT_OK)	/* U2 wait for OK to setup */		\
414	DEF(USER_OUT_WAIT_CONF)	/* U3 wait for SETUP.confirm */		\
415	DEF(USER_ACTIVE)	/* U4 A8-9-10/U10 */			\
416	DEF(USER_REL_WAIT)	/* U5 wait for release to compl */	\
417	DEF(USER_IN_PREPARING)	/* U6 set SAP */			\
418	DEF(USER_IN_WAITING)	/* U7 wait and dispatch */		\
419	DEF(USER_IN_ARRIVED)	/* U8 waiting for rej/acc */		\
420	DEF(USER_IN_WAIT_REJ)	/* U9 wait for rejecting */		\
421	DEF(USER_IN_WAIT_ACC)	/* U10 wait for accepting */		\
422	DEF(USER_IN_ACCEPTING)	/* U11 wait for SETUP_complete */	\
423	DEF(USER_REL_WAIT_SCOMP)/* U12 wait for SETUP_complete */	\
424	DEF(USER_REL_WAIT_SCONF)/* U13 wait for SETUP.confirm */	\
425	DEF(USER_REL_WAIT_CONF)	/* U14 wait for confirm */		\
426	DEF(USER_REL_WAIT_CONN)	/* U15 wait for CONN_OK */
427
428enum user_state {
429#define	DEF(N) N,
430USER_STATES
431#undef DEF
432};
433
434#define	USER_SIGS						\
435	DEF(PREPARE_OUTGOING)		/* U */			\
436	DEF(CONNECT_OUTGOING)		/* U msg */		\
437	DEF(PREPARE_INCOMING)		/* U msg */		\
438	DEF(WAIT_ON_INCOMING)		/* U msg */		\
439	DEF(REJECT_INCOMING)		/* U msg */		\
440	DEF(ACCEPT_INCOMING)		/* U msg */		\
441	DEF(CALL_RELEASE)		/* U msg */		\
442	DEF(ADD_PARTY)			/* U msg */		\
443	DEF(DROP_PARTY)			/* U msg */		\
444	DEF(QUERY_ATTR)			/* U msg */		\
445	DEF(QUERY_ATTR_X)		/* U msg */		\
446	DEF(SET_ATTR)			/* U msg */		\
447	DEF(SET_ATTR_X)			/* U msg */		\
448	DEF(QUERY_STATE)		/* U */			\
449	DEF(GET_LOCAL_PORT_INFO)	/* U msg */		\
450	DEF(ABORT_CONNECTION)		/* U msg */		\
451								\
452	DEF(CONNECT_OUTGOING_OK)	/* */			\
453	DEF(CONNECT_OUTGOING_ERR)	/* reason */		\
454	DEF(SETUP_CONFIRM)		/* */			\
455	DEF(SETUP_IND)			/* */			\
456	DEF(REJECT_OK)			/* */			\
457	DEF(REJECT_ERR)			/* reason */		\
458	DEF(ACCEPT_OK)			/* */			\
459	DEF(ACCEPT_ERR)			/* reason */		\
460	DEF(ACCEPTING)			/* */			\
461	DEF(SETUP_COMPL)		/* */			\
462	DEF(RELEASE_CONFIRM)		/* */			\
463	DEF(RELEASE_ERR)		/* reason */		\
464	DEF(ADD_PARTY_ERR)		/* reason */		\
465	DEF(ADD_PARTY_OK)		/* */			\
466	DEF(ADD_PARTY_ACK)		/* leaf-ident */	\
467	DEF(ADD_PARTY_REJ)		/* leaf-ident */	\
468	DEF(DROP_PARTY_ERR)		/* reason */		\
469	DEF(DROP_PARTY_OK)		/* */			\
470	DEF(DROP_PARTY_IND)		/* leaf-ident */	\
471
472
473enum user_sig {
474#define	DEF(NAME)	USER_SIG_##NAME,
475USER_SIGS
476#undef DEF
477};
478extern const char *const cc_user_sigtab[];
479
480struct ccuser {
481	LIST_ENTRY(ccuser) 	node_link;	/* link in list of node */
482	enum user_state		state;		/* type of this instance */
483	struct ccdata		*cc;		/* the node */
484	void			*uarg;		/* the hook (if any) */
485	char			name[ATM_EPNAMSIZ];
486	enum {
487		USER_P2P,
488		USER_ROOT,
489		USER_LEAF
490	}			config;		/* configuration */
491
492	struct uni_sap		*sap;		/* listening SAP */
493	u_int			queue_max;	/* maximum queue size */
494	u_int			queue_act;	/* actual queue size */
495	TAILQ_HEAD(,ccconn)	connq;		/* pending connections */
496	struct ccconn		*accepted;
497	struct uni_ie_cause	cause[2];	/* cause from connection */
498	u_int			aborted;
499};
500
501/* set user to new state */
502void cc_user_set_state(struct ccuser *, enum user_state);
503
504/* return string for state */
505const char *cc_user_state2str(u_int);
506
507/* log on a user */
508#ifdef CCATM_DEBUG
509#if defined(__GNUC__) && __GNUC__ < 3
510#define	cc_user_log(U, FMT, ARGS...) do {				\
511	(U)->cc->funcs->log("%s (user=%p): " FMT, __FUNCTION__,		\
512	    (U) , ## ARGS);						\
513    } while (0)
514#else
515#define	cc_user_log(U, FMT, ...) do {					\
516	(U)->cc->funcs->log("%s (user=%p): " FMT, __func__,		\
517	    (U), __VA_ARGS__);						\
518    } while (0)
519#endif
520#else
521#if defined(__GNUC__) && __GNUC__ < 3
522#define	cc_user_log(U, FMT, ARGS...) do { } while (0)
523#else
524#define	cc_user_log(U, FMT, ...) do { } while (0)
525#endif
526#endif
527
528/* Handle a signal to this user */
529void cc_user_sig_handle(struct ccuser *, enum user_sig, void *, u_int);
530
531/*
532 * Addresses
533 */
534struct ccaddr {
535	TAILQ_ENTRY(ccaddr) port_link;
536	struct uni_addr	addr;
537};
538
539/* signal to connection */
540int cc_conn_sig(struct ccconn *, enum conn_sig, void *arg);
541
542/* signal with message to connection */
543int cc_conn_sig_msg(struct ccconn *, enum conn_sig, struct uni_msg *);
544int cc_conn_sig_msg_nodef(struct ccconn *, enum conn_sig, struct uni_msg *);
545
546/* response signal to connection */
547int cc_conn_resp(struct ccconn *, enum conn_sig, u_int, u_int, u_int);
548
549/* flush all signals to a given connection */
550void cc_conn_sig_flush(struct ccconn *);
551
552/* Queue a signal to this user */
553int cc_user_sig(struct ccuser *, enum user_sig, void *, u_int);
554
555/* Queue a signal with message to this user */
556int cc_user_sig_msg(struct ccuser *, enum user_sig, struct uni_msg *);
557
558/* Flush all signals to a given user */
559void cc_user_sig_flush(struct ccuser *);
560
561/* flush all signals */
562void cc_sig_flush_all(struct ccdata *);
563