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