cnp.h   [plain text]


/*
 * Copyright (c) 2010 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Portions of this software have been released under the following terms:
 *
 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
 *
 * To anyone who acknowledges that this file is provided "AS IS"
 * without any express or implied warranty:
 * permission to use, copy, modify, and distribute this file for any
 * purpose is hereby granted without fee, provided that the above
 * copyright notices and this notice appears in all source code copies,
 * and that none of the names of Open Software Foundation, Inc., Hewlett-
 * Packard Company or Digital Equipment Corporation be used
 * in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  Neither Open Software
 * Foundation, Inc., Hewlett-Packard Company nor Digital
 * Equipment Corporation makes any representations about the suitability
 * of this software for any purpose.
 *
 * Copyright (c) 2007, Novell, Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Novell Inc. nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @APPLE_LICENSE_HEADER_END@
 */

/*
**
**  NAME
**
**      cnp.h
**
**  FACILITY:
**
**      Remote Procedure Call (RPC)
**
**  ABSTRACT:
**
**  Definitions of types/constants internal to NCA Connection RPC
**  Protocol Service and common to all its components.
**
**
*/

#ifndef _CNP_H
#define _CNP_H	1

#include <cn.h>

/*
 * CN internal status codes. These will not be passed out of CN.
 *	RPC_C_CN_STATEBASE:  determines base value for the state
 *			     and this value is used to quickly determine
 *			     by the state evaluation routine, whether a
 *			     value is a state or action.
 */
#define RPC_S_HEADER_FULL               0x0001beef
#define RPC_C_CN_STATEBASE 		100
/*
 * Macros for serializing access to the connection protocol code.
 */
#define RPC_CN_LOCK()                   RPC_LOCK(0)
#define RPC_CN_UNLOCK()                 RPC_UNLOCK(0)
#define RPC_CN_LOCK_ASSERT()            RPC_LOCK_ASSERT(0)

/*
 * rpc_e_dbg_general debug switch levels
 */
#define RPC_C_CN_DBG_ROUTINE_TRACE      20
#define RPC_C_CN_DBG_THREADS            2       /* exact */
#define RPC_C_CN_DBG_ERRORS             1
#define RPC_C_CN_DBG_BUFFS              1
#define RPC_C_CN_DBG_GENERAL            1
#define RPC_C_CN_DBG_SECURITY_ERRORS    1

/*
 * rpc_e_dbg_cn_state debug switch levels
 */
#define RPC_C_CN_DBG_ASSOC_SM_TRACE     3
#define RPC_C_CN_DBG_ASSOC_GRP_SM_TRACE 2
#define RPC_C_CN_DBG_CALL_SM_TRACE      1

/*
 * rpc_e_dbg_orphan debug switch levels
 */
#define RPC_C_CN_DBG_ORPHAN             1

/*
 * rpc_e_dbg_cancel debug switch levels
 */
#define RPC_C_CN_DBG_CANCEL             1

/*
 * rpc_e_dbg_cn_pkt debug switch levels
 */
#define RPC_C_CN_DBG_PKT_DUMP           20
#define RPC_C_CN_DBG_PKT                1

/*
 * rpc_e_dbg_cn_errors debug switch levels
 *
 * Switches to set on server to generate bind NAKs and a status code used only
 * when one of the error debug levels are set.
 */
#define RPC_S_CN_DBG_FAILURE            0xdeadbeefU
#define RPC_C_CN_DBG_PROT_VERS_MISMATCH 1 /* server: force a mismatch */
#define RPC_C_CN_DBG_GRP_LKUP_BY_ID     2 /* server: make lkup fail  */
                                          /* (>1 assoc on group) */
                                          /* Must be more than 1 */
                                          /* client thread making */
                                          /* call on group. */
#define RPC_C_CN_DBG_GRP_ALLOC          3 /* server: make alloc fail */
#define RPC_C_CN_DBG_HEADER_FULL        4 /* server: make bind ACK too big */
                                          /* for large fragbuf */
#define RPC_C_CN_DBG_GRP_MAX_EXCEEDED   5 /* server: set grp_cur_assoc = */
                                          /* grp_max_assoc */
                                          /* (>1 assoc on group) */
                                          /* Must be more than 1 */
                                          /* client thread making */
                                          /* call on group. */
/*
 * Switches to set on server to generate bind ACKs with various
 * pprov reason codes.
 */
#define RPC_C_CN_DBG_IF_LOOKUP          6 /* server: cause the abstract */
                                          /* syntax to not be found */
#define RPC_C_CN_DBG_NO_XFER_SYNTAX     7 /* server: cause no matching xfer */
                                          /* syntax to be found */

/*
 * Various other switches to force errors.
 */
#define RPC_C_CN_DBG_SEC_ALLOC_FAIL     8 /* cause the sec_alloc to */
                                          /* fail */
#define RPC_C_CN_DBG_ASSOC_REQ_FAIL     9 /* cause the association */
                                          /* request eval event to */
                                          /* fail */

/*
 * Error switches to force packet fragmentation.
 */
#define RPC_C_CN_DBG_FRAG_BIND		10 /* bind (and alter_ctx) fragment */
#define RPC_C_CN_DBG_FRAG_BIND_ACK	11 /* bind_ack (and alter_ctx_resp)
                                              fragment */

#define RPC_CN_DBG_RTN_PRINTF(s) RPC_DBG_PRINTF(rpc_e_dbg_general, \
                                                RPC_C_CN_DBG_ROUTINE_TRACE,\
                                                ("(" #s ")\n"))


/***********************************************************************/
/*
 * R P C _ C N _ M G M T _ T
 */
#include <cnpkt.h>
typedef struct
{
    unsigned32          calls_sent;
    unsigned32          calls_rcvd;
    unsigned32          pkts_sent;
    unsigned32          pkts_rcvd;
    unsigned32          connections;
    unsigned32          closed_connections;
    unsigned32          alloced_assocs;
    unsigned32          dealloced_assocs;
    unsigned32          aborted_assocs;
    unsigned32          assoc_grps;
    struct cn_pkt_stats_t              /* Breakdown of pkts sent/rcvd by pkt type */
    {
        unsigned32 sent;
        unsigned32 rcvd;
    } pstats[RPC_C_CN_PKT_MAX_TYPE + 1];
} rpc_cn_mgmt_t, *rpc_cn_mgmt_p_t;
#define RPC_CN_STATS_INCR(s) (rpc_g_cn_mgmt.s++)

/***********************************************************************/
/*
 * R P C _ C N _ S M _ P R E D _ R E S U L T _ T
 */

#define RPC_C_SM_NO_PREDICATE           255
#define RPC_C_SM_NO_ACTION              255
#define RPC_C_SM_NO_NSTATE              255

/*
 * Returning the current error status can be accomplished by
 * taking no action.  The generic state machine evaluator will
 * automatically return the status of the last action routine
 * invoked.
 */
#define RPC_C_SM_RETURN_ERROR_STATUS RPC_C_SM_NO_ACTION

typedef struct
{
    unsigned8                           nstate;
    unsigned8                           action;
} rpc_cn_sm_pred_result_t, *rpc_cn_sm_pred_result_p_t;

/***********************************************************************/
/*
 * R P C _ C N _ S M _ S T A T E _ E N T R Y _ T
 */

#define RPC_C_NUM_PREDICATES 	3

/*
 * The rpc_cn_sm_state_entry_t can contain either the action
 * or the next state.  If both are required, then we include the
 * action, which updates the next state internally.  Distinguish
 * between actions and states by numeric value.  States will
 * be some value (usually 0 -> 14) + rpc_c_cn_statebase.
 */
typedef struct
{
    unsigned8                           action;
} rpc_cn_sm_state_entry_t, *rpc_cn_sm_state_entry_p_t;

#define ILLEGAL_TRANSITION \
    { PROTOCOL_ERROR }

#define ILLEGAL_PREDICATE_RESULT \
    { RPC_C_SM_NO_NSTATE, \
      PROTOCOL_ERROR }

/*
 * R P C _ C N _ S M _ S T A T E _ T B L _ E N T R Y _ T
 */

typedef rpc_cn_sm_state_entry_t         rpc_cn_sm_state_tbl_entry_t[];

/*
 * R P C _ C N _ S M _ A C T I O N _ F N _ T
 */

typedef unsigned32     (*rpc_cn_sm_action_fn_t) (
    dce_pointer_t   /*spc_struct*/,
    dce_pointer_t   /*event_parameter*/,
    dce_pointer_t   /*sm*/);

typedef rpc_cn_sm_action_fn_t      *rpc_cn_sm_action_fn_p_t;

/*
 * R P C _ C N _ S M _ P R E D I C A T E _ F N _ T
 */

typedef unsigned8 (*rpc_cn_sm_predicate_fn_t) (
    dce_pointer_t   /*spc_struct*/,
    dce_pointer_t   /*event_parameter*/);

typedef rpc_cn_sm_predicate_fn_t   *rpc_cn_sm_predicate_fn_p_t;

/*
 * R P C _ C N _ S M _ E V E N T _ E N T R Y _ T
 */

typedef struct
{
    unsigned8                           event_id;
    dce_pointer_t                           event_param;
} rpc_cn_sm_event_entry_t, *rpc_cn_sm_event_entry_p_t;

/*
 * R P C _ C N _ S M _ E V E N T _ L I S T _ T
 */

#define RPC_C_CN_SM_EVENT_LIST_MAX_ENTRIES 2
typedef rpc_cn_sm_event_entry_t
        rpc_cn_sm_event_list_t [ RPC_C_CN_SM_EVENT_LIST_MAX_ENTRIES ];

/*
 * R P C _ C N _ S M _ C T L B L K _ T
 */
/*
 * State values are incremented by 100 to distinguish them from
 * action routine indexes which are all < 100.  This was done as
 * an efficiency measure to the engine, rpc__cn_sm_eval_event().
 */

/*
 * Performance Table ID defines
 */
#define       rpc_c_cn_svr_assoc   1  /* server association tbl */
#define       rpc_c_cn_cl_assoc    2  /* client association tbl */
#define       rpc_c_cn_svr_call    3  /* server call rep tbl */
#define       rpc_c_cn_cl_call     4  /* client call rep tbl */
#define       rpc_c_cn_svr_a_g     5  /* server assoc group tbl */
#define       rpc_c_cn_cl_a_g	   6  /* client assoc group tbl */

typedef struct
{
    rpc_cn_sm_state_entry_p_t           *state_tbl;
    rpc_cn_sm_action_fn_t               *action_tbl;
#define RPC_C_SM_CLOSED_STATE           100
    unsigned8                           cur_state;
    unsigned8                           cur_event;
    unsigned32                          action_status;
    unsigned8                           event_list_hindex;
    unsigned8                           event_list_tindex;
#define RPC_C_CN_SM_EVENT_LIST_EMPTY       0
    unsigned8                           event_list_state;
    rpc_cn_sm_event_list_t              event_list;
    unsigned32				tbl_id;
} rpc_cn_sm_ctlblk_t, *rpc_cn_sm_ctlblk_p_t;

/***********************************************************************/

/*
 * R P C _ C N _ F R A G B U F _ T
 */

#define RPC_C_CN_OVERHEAD_SIZE          4

typedef struct rpc_cn_fragbuf_s_t rpc_cn_fragbuf_t, *rpc_cn_fragbuf_p_t;
typedef void (*rpc_cn_fragbuf_dealloc_fn_t) (rpc_cn_fragbuf_t *);

struct rpc_cn_fragbuf_s_t
{
    rpc_list_t                  link;   /* MUST BE 1ST */
    unsigned32                  max_data_size;
    rpc_cn_fragbuf_dealloc_fn_t fragbuf_dealloc;
    dce_pointer_t                   data_p;
    unsigned32                  data_size;
    unsigned8                   overhead_area[RPC_C_CN_OVERHEAD_SIZE];
    unsigned8                   data_area[1];
};

/***********************************************************************/

/*
 * R P C _ CN _ L O C A L _ I D _ T
 */

typedef struct
{
    unsigned16                          id_seqnum;
    unsigned16                          id_index;
} rpc_cn_local_id_parts_t, *rpc_cn_local_id_parts_p_t;

typedef union
{
    unsigned32                          all;
    rpc_cn_local_id_parts_t             parts;
} rpc_cn_local_id_t, *rpc_cn_local_id_p_t;

/*
 * R P C _ C N _ B I N D I N G _ R E P _ T
 */

typedef struct
{
    rpc_binding_rep_t                   common;
    rpc_cn_local_id_t                   grp_id;
    boolean                             being_resolved;
    dcethread*                          resolving_thread_id;
} rpc_cn_binding_rep_t, *rpc_cn_binding_rep_p_t;

/*
 * R P C _ C N _ C A L L _ R E P _ T
 */

typedef struct
{
    rpc_iovector_t                      iov;
    rpc_iovector_elt_t                  iov_elmts[ RPC_C_MAX_IOVEC_LEN - 1];
    unsigned32                          total_acc_byte_count;
    unsigned32                          cur_iov_index;
    unsigned32                          num_free_bytes;
    byte_p_t                            free_byte_ptr;
    unsigned32                          size_of_header;
    unsigned32                          trailer_pad;
} rpc_cn_buffered_output_t, *rpc_cn_buffered_output_p_t;

/*
 * Client cancel state information
 *
 * server_is_accepting : used to indicate when the first fragment
 *                       has been sent.
 * local_count         : # of cancels detected locally but not
 *                       forwarded yet. These may be forwarded
 *                       by setting the PFC_PENDING_ALERT bit in
 *                       the first fragment of a request.
 * server_count        : # of cancels detected and forwarded
 *                       locally *not* including the PFC_PENDING_ALERT
 *                       bit in the first fragment of a request.
 * server_had_pending  : indicates whether the server completed
 *                       with a pending alert. If so the alert
 *                       should be re-generated before returning
 *                       to the client stub
 */
typedef struct rpc_cn_cancel_info_s_t
{
    unsigned16                          local_count;
    unsigned16                          server_count;
    rpc_clock_t                         timeout_time;
    rpc_timer_t                         timer;
    unsigned                            timer_running: 1;
    unsigned                            server_is_accepting: 1;
    unsigned                            server_had_pending: 1;
    dcethread*                          thread_h;
} rpc_cn_cancel_info_t, *rpc_cn_cancel_info_p_t;

typedef struct rpc_cn_call_rep_s_t
{
    rpc_call_rep_t                      common;
    rpc_cn_sm_ctlblk_t                  call_state;
    unsigned32                          cn_call_status;
    rpc_binding_rep_t                   *binding_rep;
    struct rpc_cn_assoc_s_t             *assoc;
    rpc_cn_fragbuf_t                    *prot_header;
    rpc_cn_fragbuf_t                    *prot_tlr;
    unsigned32                          max_seg_size;
    unsigned32                          alloc_hint;
    rpc_cn_buffered_output_t            buffered_output;
    unsigned16                          context_id;
    unsigned16                          num_pkts;
    rpc_transfer_syntax_t               transfer_syntax;
    unsigned16                          opnum;
    unsigned                            last_frag_received: 1;
    unsigned                            call_executed: 1;
    rpc_cn_sec_context_t                *sec;
    union
    {
        struct
        {
            rpc_cn_fragbuf_t            *fault_data;
            rpc_cn_cancel_info_t        cancel;
        } client;
        struct
        {
            idl_uuid_t                      *if_id;
            unsigned32                  if_vers;
            unsigned16                  ihint;
            struct
            {
                unsigned16              local_count; /* common cancel count */
                                                     /* less pending */
                                                     /* alert bit cancel */
            } cancel;
        } server;
    } u;
} rpc_cn_call_rep_t, *rpc_cn_call_rep_p_t;

#define RPC_CN_CREP_SEND_HDR(cp) \
    (((rpc_cn_fragbuf_p_t)((cp)->prot_header))->data_p)
#define RPC_CN_CREP_ACC_BYTCNT(cp) \
    (((cp)->buffered_output).total_acc_byte_count)
#define RPC_CN_CREP_IOV(cp)                (((cp)->buffered_output).iov.elt)
#define RPC_CN_CREP_IOVLEN(cp)             (((cp)->buffered_output).iov.num_elt)
#define RPC_CN_CREP_CUR_IOV_INDX(cp)       (((cp)->buffered_output).cur_iov_index)
#define RPC_CN_CREP_FREE_BYTES(cp)         (((cp)->buffered_output).num_free_bytes)
#define RPC_CN_CREP_FREE_BYTE_PTR(cp)      (((cp)->buffered_output).free_byte_ptr)
#define RPC_CN_CREP_SIZEOF_HDR(cp)         (((cp)->buffered_output).size_of_header)
#define RPC_CN_CREP_SIZEOF_TLR_PAD(cp)     (((cp)->buffered_output).trailer_pad)

/*
 * R P C _ C N _ C R E P _ A D J _ F O R _ T L R
 *
 * This macro will adjust all the appriate field in the call rep
 * "buffered_output" structure so that an authentication trailer can
 * be added to the packet. Note that the size of the trailer will be
 * rounded up to the nearest 8-byte boundary. This is so that any user
 * data placed in the PDU will also be a multiple of 8-bytes. This
 * rounding will be removed before the packet is sent.
 */
#define RPC_CN_CREP_ADJ_IOV_FOR_TLR(cp, header_p, auth_value_len)\
{\
    (cp)->prot_tlr->data_size = \
    ((auth_value_len + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + 7) & ~0x07);\
    RPC_CN_CREP_SIZEOF_TLR_PAD (cp) =\
       (cp)->prot_tlr->data_size - \
       auth_value_len - \
       RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; \
    RPC_CN_CREP_SIZEOF_HDR (cp) += (cp)->prot_tlr->data_size;\
    RPC_CN_CREP_FREE_BYTES (cp) -= (cp)->prot_tlr->data_size;\
    RPC_CN_CREP_ACC_BYTCNT (cp) += (cp)->prot_tlr->data_size;\
    RPC_CN_CREP_IOVLEN (cp)++;\
    RPC_CN_PKT_AUTH_LEN (header_p) = auth_value_len;\
    /*\
     * Add the size of the auth trailer (plus padding to\
     * make it an 8-byte multiple to the data length of the\
     * protocol header iovector element. This is so that the\
     * trailer length will be taken into account when adding\
     * user data to the packet. It will be subtracted when the\
     * actual trailer is added to the packet in\
     * rpc__cn_transmit_buffers.\
     */\
    (RPC_CN_CREP_IOV (cp)[0]).data_len = RPC_CN_CREP_SIZEOF_HDR (cp);\
}


/***********************************************************************/
/*
 * R P C _ C N _ A S S O C _ G R P _ T B L _ T
 */

typedef struct
{
    unsigned16                          grp_count;
    unsigned16                          grp_active_count;
    rpc_timer_t                         grp_client_timer;
    rpc_timer_t                         grp_server_timer;
    struct rpc_cn_assoc_grp_s_t         *assoc_grp_vector;
} rpc_cn_assoc_grp_tbl_t, *rpc_cn_assoc_grp_tbl_p_t;

/*
 * R P C _ C N _ S Y N T A X _ T
 */

typedef void    (*rpc_cn_marshal_fn_t) (void);

typedef struct rpc_cn_syntax_s_t
{
    rpc_list_t                          link;   /* MUST BE 1ST */
    rpc_syntax_id_t                     syntax_abstract_id;
    rpc_syntax_id_t                     syntax_transfer_id;
    unsigned16                          syntax_pres_id;
    unsigned16                          syntax_vector_index;
    rpc_syntax_vector_t                 *syntax_vector;
    rpc_cn_marshal_fn_t                 *syntax_epv;
    unsigned16                          syntax_ihint;
    unsigned                            syntax_valid: 1;
    unsigned32                          syntax_status;
    unsigned32                          syntax_call_id;
} rpc_cn_syntax_t, *rpc_cn_syntax_p_t;


/***********************************************************************/
/*
 * R P C _ A S S O C _ S M _ W O R K _ T
 *
 * This structure is used to hold various pieces of information
 * which are needed by action routines in the association state
 * machine.
 */
typedef struct
{
    unsigned32                  grp_id;
    rpc_cn_syntax_t             *pres_context;
    boolean                     reuse_context;
    rpc_cn_sec_context_t        *sec_context;
} rpc_cn_assoc_sm_work_t, *rpc_cn_assoc_sm_work_p_t;

/*
 * R P C _ C N _ A S S O C _ G R P _ T
 */

#define RPC_C_CN_ASSOC_GRP_CLIENT       1
#define RPC_C_CN_ASSOC_GRP_SERVER       2

typedef struct rpc_cn_assoc_grp_s_t
{
    rpc_cn_sm_ctlblk_t                  grp_state;
    unsigned32                          grp_status;
    unsigned16                          grp_flags;
    unsigned16                          grp_refcnt;
    rpc_addr_p_t                        grp_address;
    rpc_addr_p_t                        grp_secaddr;
    rpc_transport_info_p_t              grp_transport_info;
    rpc_cn_local_id_t                   grp_id;
    unsigned16                          grp_max_assoc;
    unsigned16                          grp_cur_assoc;
    unsigned16                          grp_assoc_waiters;
    rpc_cond_t                          grp_assoc_wt;
    rpc_list_t                          grp_assoc_list;
    unsigned16                          grp_callcnt;
    rpc_network_rundown_fn_t            grp_liveness_mntr;
    rpc_cn_local_id_t                   grp_remid;
    unsigned32                          grp_next_key_id;
} rpc_cn_assoc_grp_t, *rpc_cn_assoc_grp_p_t;

/*
 * R P C _ C N _ C T L B L K _ T
 */

typedef struct
{
    unsigned16 volatile                 cn_state;
    unsigned16 volatile                 cn_rcvr_waiters;
    rpc_mutex_t                         cn_rcvr_mutex; /* unused so far */
    rpc_cond_t                          cn_rcvr_cond;
    dcethread*                          cn_rcvr_thread_id;
    unsigned_char_t                     *cn_listening_endpoint;
    rpc_socket_t volatile               cn_sock;
    rpc_addr_p_t                        rpc_addr;
    unsigned volatile                   exit_rcvr : 1;
    unsigned volatile                   in_sendmsg : 1;
    unsigned volatile                   waiting_for_sendmsg_complete : 1;
} rpc_cn_ctlblk_t, *rpc_cn_ctlblk_p_t;

#define RPC_CN_ASSOC_LOCK(__assoc)	RPC_MUTEX_LOCK((__assoc)->cn_ctlblk.cn_rcvr_mutex)
#define RPC_CN_ASSOC_UNLOCK(__assoc)	RPC_MUTEX_UNLOCK((__assoc)->cn_ctlblk.cn_rcvr_mutex)

/*
 * R P C _ C N _ A S S O C _ T
 */

#define RPC_C_CN_ASSOC_CLIENT                   0x00000001
#define RPC_C_CN_ASSOC_SERVER                   0x00000002
#define RPC_C_CN_ASSOC_SHUTDOWN_REQUESTED       0x00000004
#define RPC_C_CN_ASSOC_SCANNED                  0x00000008
#define RPC_C_CN_ASSOC_AUTH_EXPECTED            0x00000010

struct rpc_cn_assoc_s_t
{
    rpc_list_t                          link;   /* MUST BE 1ST */
    rpc_cn_sm_ctlblk_t                  assoc_state;
    unsigned32                          assoc_status;
    unsigned32                          assoc_local_status;
    unsigned16                          assoc_flags;
    unsigned16                          assoc_ref_count;
    unsigned16                          assoc_acb_ref_count;
#define RPC_C_CN_ASSOC_SERVER_MAX_SHUTDOWN_REQ_COUNT 2
    unsigned16                          assoc_shutdown_req_count;

    rpc_cn_local_id_t                   assoc_grp_id;
    unsigned16                          assoc_msg_waiters;
    rpc_cond_t                          assoc_msg_cond;
    unsigned16                          assoc_max_xmit_frag;
    unsigned16                          assoc_max_recv_frag;
    unsigned8                           assoc_vers_minor;
    unsigned32                          assoc_pres_context_id;
    ndr_format_t                        assoc_remote_ndr_format;
    rpc_cn_fragbuf_t                    assoc_dummy_fragbuf;
    rpc_cn_call_rep_t                   *call_rep;
    rpc_cn_ctlblk_t                     cn_ctlblk;
    rpc_list_t                          syntax_list;    /* rpc_cn_syntax_t */
    rpc_list_t                          msg_list;       /* rpc_cn_fragbuf_t */
    rpc_cn_assoc_sec_context_t          security;
    rpc_transport_info_p_t              transport_info;
    rpc_cn_fragbuf_p_t                  raw_packet_p;
    rpc_cn_assoc_sm_work_p_t            assoc_sm_work;
    unsigned32                          bind_packets_sent;
    signed long long                    alter_call_id;
};
// rpc_cn_assoc_t and rpc_cn_assoc_p_t are declared in comsoc.h

/*
 * If KRB_CN is on, or it isn't explicitly off, turn on CN_AUTH.
 */
#if	defined(AUTH_KRB_CN) || !defined(AUTH_KRB_DG)
#define CN_AUTH
#endif

/*
 * Authentication interface macros. These will dispatch through the
 * authentication protocol ID table using an auth prot ID and the CN
 * RPC prot ID.
 */
#ifdef CN_AUTH
#define RPC_CN_AUTH_PROT_EPV(prot)              (rpc_cn_auth_epv_t *)(rpc__auth_rpc_prot_epv(prot, RPC_C_PROTOCOL_ID_NCACN))
#else
#define RPC_CN_AUTH_PROT_EPV(prot)              (rpc_cn_auth_epv_t *)(0xbabababa)
#endif /* CN_AUTH */

#define RPC_CN_AUTH_SEC_THREE_WAY(sec, ind)\
{\
    ind = (*(sec)->sec_cn_info->cn_epv->three_way)();\
}

#define RPC_CN_AUTH_THREE_WAY(prot, ind)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV(prot);\
    ind = (*_cn_epv->three_way)();\
}

#define RPC_CN_AUTH_CONTEXT_VALID(sec, st)\
    (*(sec)->sec_cn_info->cn_epv->context_valid)(sec, st)

#define RPC_CN_AUTH_CREATE_INFO(prot, level, info, st)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV(prot);\
    (*_cn_epv->create_info)(level, info, st);\
}

#define RPC_CN_AUTH_CRED_CHANGED(sec, st)\
    (*(sec)->sec_cn_info->cn_epv->cred_changed)(sec, st)

#define RPC_CN_AUTH_CRED_REFRESH(auth_info, st)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV((auth_info)->authn_protocol);\
    (*_cn_epv->cred_refresh)(auth_info, st);\
}

#define RPC_CN_AUTH_FMT_CLIENT_REQ(assoc_sec, sec, auth_value, auth_value_len, last_auth_pos, auth_len_remain, retry, st)\
    (*(sec)->sec_cn_info->cn_epv->fmt_client_req)(assoc_sec, sec, auth_value, auth_value_len, last_auth_pos, auth_len_remain, retry, st)

#define RPC_CN_AUTH_FMT_SRVR_RESP(verify_st, assoc_sec, sec, req_auth_value, req_auth_value_len, auth_value, auth_value_len)\
    (*(sec)->sec_cn_info->cn_epv->fmt_srvr_resp)(verify_st,assoc_sec,sec,\
                                                 req_auth_value, req_auth_value_len, auth_value, auth_value_len)

#define RPC_CN_AUTH_FREE_PROT_INFO(info, cn_info)\
    (*(*(cn_info))->cn_epv->free_prot_info)(info, cn_info)

#define RPC_CN_AUTH_GET_PROT_INFO(info, cn_info, st)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV((info)->authn_protocol);\
    (*_cn_epv->get_prot_info)(info, cn_info, st);\
}

#define RPC_CN_AUTH_PRE_CALL(assoc_sec, sec, auth_value, auth_value_len, st)\
    (*(sec)->sec_cn_info->cn_epv->pre_call)(assoc_sec, sec, auth_value, auth_value_len, st);

#define RPC_CN_AUTH_PRE_SEND(assoc_sec, sec, iovp, iovlen, out_iov, st)\
    (*(sec)->sec_cn_info->cn_epv->pre_send)(assoc_sec, sec, iovp, iovlen, out_iov, st);

#define RPC_CN_AUTH_RECV_CHECK(authn_prot, assoc_sec, sec, pdu, pdu_len, cred_len, auth_tlr, unpack_ints, st)\
{\
    if (sec == NULL)\
    {\
        rpc_cn_auth_epv_t   *_cn_epv;\
        _cn_epv = RPC_CN_AUTH_PROT_EPV(authn_prot);\
        (*_cn_epv->recv_check)(assoc_sec, sec, pdu, pdu_len, cred_len,\
                               auth_tlr, unpack_ints, st);\
    }\
    else\
    {\
        (*(sec)->sec_cn_info->cn_epv->recv_check)(assoc_sec, sec, pdu,\
             pdu_len, cred_len, auth_tlr, unpack_ints, st);\
    }\
}

#define RPC_CN_AUTH_TLR_UUID_CRC(prot, auth_value, auth_value_len, assoc_uuid_crc)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV(prot);\
    (*_cn_epv->tlr_uuid_crc)(auth_value, auth_value_len, assoc_uuid_crc);\
}

#define RPC_CN_AUTH_TLR_UNPACK(prot, pkt_p, auth_value_len, packed_drep)\
{\
    rpc_cn_auth_epv_t   *_cn_epv;\
    _cn_epv = RPC_CN_AUTH_PROT_EPV(prot);\
    (*_cn_epv->tlr_unpack)(pkt_p, auth_value_len, packed_drep);\
}

#define RPC_CN_AUTH_VFY_CLIENT_REQ(assoc_sec, sec, auth_value, auth_value_len, old_client, st)\
    (*(sec)->sec_cn_info->cn_epv->vfy_client_req)(assoc_sec, sec, auth_value, auth_value_len, old_client, st)

#define RPC_CN_AUTH_VFY_SRVR_RESP(assoc_sec, sec, auth_value, auth_value_len, st)\
    (*(sec)->sec_cn_info->cn_epv->vfy_srvr_resp)(assoc_sec, sec, auth_value, auth_value_len, st)

/*
 * These macros are RPC protocol independent.
 */
#define RPC_CN_AUTH_ADD_REFERENCE(info)         rpc__auth_info_reference(info)
#define RPC_CN_AUTH_RELEASE_REFERENCE(info)     rpc__auth_info_release(info)
#ifdef CN_AUTH
#define RPC_CN_AUTH_CVT_ID_API_TO_WIRE(id,st)   rpc__auth_cvt_id_api_to_wire(\
id,st)
#define RPC_CN_AUTH_CVT_ID_WIRE_TO_API(id,st)   rpc__auth_cvt_id_wire_to_api(\
id,st)
#define RPC_CN_AUTH_INQ_SUPPORTED(id)           rpc__auth_inq_supported(id)
#else
#define RPC_CN_AUTH_CVT_ID_API_TO_WIRE(id,st)   0
#define RPC_CN_AUTH_CVT_ID_WIRE_TO_API(id,st)   0
#define RPC_CN_AUTH_INQ_SUPPORTED(id)           false
#endif

/*
 * R P C _ C N _ A L I G N _ P T R
 *
 * RPC Pointer Alignment macro
 *
 * Casting to (unsigned long) is needed because bitwise operations are not
 * allowed with pointers as an operand.
 *
 * NOTE: Assumption sizeof(unsigned long) = sizeof(unsigned8 *).  This
 *       assumption may not be correct for all machines.
 */

/* ??? */

#define RPC_CN_ALIGN_PTR(ptr, boundary) \
    ((uintptr_t) ((unsigned8 *)(ptr) + ((boundary)-1)) & ~((boundary)-1))

/*
 * R P C _ C N _ A U T H _ R E Q U I R E D
 */

#define RPC_CN_AUTH_REQUIRED(info) ((info != NULL) && \
                                    ((info)->authn_protocol != rpc_c_authn_none))

#define RPC_CN_PKT_AUTH_REQUIRED(info) ((info != NULL) && \
                                    ((info)->authn_level != rpc_c_protect_level_none) && \
                                    ((info)->authn_level != rpc_c_protect_level_connect))

/*
 * R P C _ G _ C N _ A S S O C _ G R P _ T B L
 */

EXTERNAL rpc_cn_assoc_grp_tbl_t rpc_g_cn_assoc_grp_tbl;

/*
 * R P C _ G _ C N _ S Y N T A X _ L O O K A S I D E _ L I S T
 */

#define RPC_C_CN_SYNTAX_LOOKASIDE_MAX           16
EXTERNAL rpc_list_desc_t        rpc_g_cn_syntax_lookaside_list;

/*
 * R P C _ G _ C N _ S E C _ L O O K A S I D E _ L I S T
 */

#define RPC_C_CN_SEC_LOOKASIDE_MAX              16
EXTERNAL rpc_list_desc_t        rpc_g_cn_sec_lookaside_list;

/*
 * R P C _ G _ C N _ A S S O C _ L O O K A S I D E _ L I S T
 */

#define RPC_C_CN_ASSOC_LOOKASIDE_MAX            16
EXTERNAL rpc_list_desc_t        rpc_g_cn_assoc_lookaside_list;

/*
 * R P C _ G _ C N _ C A L L _ R E P _ L O O K A S I D E _ L I S T
 */

#define RPC_C_CN_CALL_LOOKASIDE_MAX             0
EXTERNAL rpc_list_desc_t        rpc_g_cn_call_lookaside_list;

/*
 * R P C _ G _ C N _ B I N D I N G _ L O O K A S I D E _ L I S T
 */

#define RPC_C_CN_BINDING_LOOKASIDE_MAX          8
EXTERNAL rpc_list_desc_t          rpc_g_cn_binding_lookaside_list;

/*
 * R P C _ G _ C N _ [ L G , S M ] _ F R A G B U F _ L I S T
 */

#define RPC_C_CN_FRAGBUF_LOOKASIDE_MAX          0
EXTERNAL rpc_list_desc_t          rpc_g_cn_lg_fbuf_lookaside_list;
EXTERNAL rpc_list_desc_t          rpc_g_cn_sm_fbuf_lookaside_list;

/*
 * R P C _ G _ C N _ L O O K A S I D E _ C O N D
 */

EXTERNAL rpc_cond_t             rpc_g_cn_lookaside_cond;

/*
 * R P C _ G _ C N _ C A L L _ I D
 */

EXTERNAL unsigned32             rpc_g_cn_call_id;

/*
 * R P C _ G _ C N _ M G M T
 */
EXTERNAL rpc_cn_mgmt_t          rpc_g_cn_mgmt;

#endif /* _CNP_H */