1 /*
2  * Copyright (c) 2003-2004
3  *	Hartmut Brandt
4  *	All rights reserved.
5  *
6  * Author: Harti Brandt <[email protected]>
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 
44 struct ccuser;
45 struct ccconn;
46 struct ccaddr;
47 struct ccport;
48 struct ccdata;
49 struct ccsig;
50 struct ccparty;
51 
52 LIST_HEAD(ccuser_list, ccuser);
53 LIST_HEAD(ccconn_list, ccconn);
54 TAILQ_HEAD(ccaddr_list, ccaddr);
55 TAILQ_HEAD(ccport_list, ccport);
56 TAILQ_HEAD(ccsig_list, ccsig);
57 LIST_HEAD(ccparty_list, ccparty);
58 
59 /*
60  * Private node data.
61  */
62 struct 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 */
76 struct 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  */
104 struct ccreq {
105 	TAILQ_ENTRY(ccreq)	link;
106 	uint32_t		cookie;
107 	uint32_t		req;
108 	struct ccconn		*conn;
109 };
110 TAILQ_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  */
117 struct 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 
178 enum 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 
214 enum conn_sig {
215 #define DEF(NAME) CONN_SIG_##NAME,
216 CONN_SIGS
217 #undef DEF
218 };
219 extern const char *const cc_conn_sigtab[];
220 
221 /*
222  * This describes a connection and must be in sync with the UNI
223  * stack.
224  */
225 struct 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 */
273 enum {
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 */
288 void cc_conn_set_state(struct ccconn *, enum conn_state);
289 
290 /* return string for state */
291 const char *cc_conn_state2str(u_int);
292 
293 /* connect connection to user */
294 void cc_connect_to_user(struct ccconn *, struct ccuser *);
295 
296 /* disconnect from the user */
297 void cc_disconnect_from_user(struct ccconn *);
298 
299 /* abort the connection */
300 void cc_conn_abort(struct ccconn *, int);
301 
302 /* destroy a connection */
303 void cc_conn_destroy(struct ccconn *);
304 
305 /* create a connection */
306 struct ccconn *cc_conn_create(struct ccdata *);
307 
308 /* assign to port */
309 void cc_conn_ins_port(struct ccconn *, struct ccport *);
310 
311 /* remove from port */
312 void cc_conn_rem_port(struct ccconn *);
313 
314 /* dispatch a connection to a user or reject it */
315 void cc_conn_dispatch(struct ccconn *);
316 
317 /* disconnect from acceptor */
318 void 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 */
342 void 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 
362 enum party_state {
363 #define	DEF(N)	PARTY_##N,
364 PARTY_STATES
365 #undef DEF
366 };
367 
368 struct 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 */
377 void cc_party_set_state(struct ccparty *, enum party_state);
378 
379 /* return string for state */
380 const char *cc_party_state2str(u_int);
381 
382 /* create new party */
383 struct 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 
428 enum user_state {
429 #define	DEF(N) N,
430 USER_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 
473 enum user_sig {
474 #define	DEF(NAME)	USER_SIG_##NAME,
475 USER_SIGS
476 #undef DEF
477 };
478 extern const char *const cc_user_sigtab[];
479 
480 struct 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 */
502 void cc_user_set_state(struct ccuser *, enum user_state);
503 
504 /* return string for state */
505 const 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 */
529 void cc_user_sig_handle(struct ccuser *, enum user_sig, void *, u_int);
530 
531 /*
532  * Addresses
533  */
534 struct ccaddr {
535 	TAILQ_ENTRY(ccaddr) port_link;
536 	struct uni_addr	addr;
537 };
538 
539 /* signal to connection */
540 int cc_conn_sig(struct ccconn *, enum conn_sig, void *arg);
541 
542 /* signal with message to connection */
543 int cc_conn_sig_msg(struct ccconn *, enum conn_sig, struct uni_msg *);
544 int cc_conn_sig_msg_nodef(struct ccconn *, enum conn_sig, struct uni_msg *);
545 
546 /* response signal to connection */
547 int cc_conn_resp(struct ccconn *, enum conn_sig, u_int, u_int, u_int);
548 
549 /* flush all signals to a given connection */
550 void cc_conn_sig_flush(struct ccconn *);
551 
552 /* Queue a signal to this user */
553 int cc_user_sig(struct ccuser *, enum user_sig, void *, u_int);
554 
555 /* Queue a signal with message to this user */
556 int cc_user_sig_msg(struct ccuser *, enum user_sig, struct uni_msg *);
557 
558 /* Flush all signals to a given user */
559 void cc_user_sig_flush(struct ccuser *);
560 
561 /* flush all signals */
562 void cc_sig_flush_all(struct ccdata *);
563