/* * 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 ** ** cnpkt.c ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** Connection-based protocol packet packing/unpacking routines. ** ** */ #include /* Common declarations for all RPC runtime */ #include /* Common communications services */ #include /* Common protocol services */ #include /* System (machine architecture) dependent definitions */ #include /* NCA Connection private declarations */ #include /* NCA Connection packet encoding */ /* * R P C _ G _ C N _ C O M M O N _ H D R * * This is a template of the common part of all NCA connection * packet headers. It is statically initialized where possible. This * is used by the rpc__cn_pkt_format_common routine. */ GLOBAL rpc_cn_common_hdr_t rpc_g_cn_common_hdr = { RPC_C_CN_PROTO_VERS, /* rpc_vers */ RPC_C_CN_PROTO_VERS_MINOR, /* rpc_vers_minor */ RPC_C_CN_PKT_INVALID, /* ptype */ 0, /* flags */ { /* drep[4] */ (NDR_LOCAL_INT_REP << 4) | NDR_LOCAL_CHAR_REP, NDR_LOCAL_FLOAT_REP, 0, 0 }, 0, /* frag_len */ 0, /* auth_len */ 0 /* call_id */ }; INTERNAL rpc_cn_pres_result_list_p_t unpack_port_any ( rpc_cn_port_any_t *port_any_p, unsigned8 *drepp, unsigned8 *end_of_pkt, unsigned32 *st ); INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_context_list ( rpc_cn_pres_cont_list_p_t pcontp, boolean32 swap, unsigned8 *end_of_pkt, unsigned32 *st ); INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_result_list ( rpc_cn_pres_result_list_p_t presp, boolean32 swap, unsigned8 *end_of_pkt, unsigned32 *st ); INTERNAL rpc_cn_auth_tlr_p_t unpack_versions_supported ( rpc_cn_versions_supported_p_t /*versp*/ ); void SWAP_INPLACE_UUID ( idl_uuid_t *uuid_p, unsigned8 *end_of_pkt, unsigned32 *st ) { SWAP_INPLACE_32(&uuid_p->time_low, end_of_pkt, st); if (*st == rpc_s_ok) { SWAP_INPLACE_16(&uuid_p->time_mid, end_of_pkt, st); } if (*st == rpc_s_ok) { SWAP_INPLACE_16(&uuid_p->time_hi_and_version, end_of_pkt, st); } } void SWAP_INPLACE_SYNTAX ( rpc_cn_pres_syntax_id_p_t syntax_p, unsigned8 *end_of_pkt, unsigned32 *st ) { SWAP_INPLACE_UUID(&syntax_p->id, end_of_pkt, st); if (*st == rpc_s_ok) { SWAP_INPLACE_32(&syntax_p->version, end_of_pkt, st); } } /* **++ ** ** ROUTINE NAME: unpack_port_any ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine unpacks the 'port_any' secondary address field of an ** RPC connection packet and returns a pointer to the next octet following ** the port_any field. ** ** INPUTS: ** ** port_any_p pointer to the 'port_any' field within the packet ** drepp pointer to the data representation ** swap boolean indicating we need to perform byte swapping ** end_of_pkt ptr to 1 byte past end of packet ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: ** st The return status of this routine ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: ** ** return pointer to the next octet after the 'port_any' field ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL rpc_cn_pres_result_list_p_t unpack_port_any ( rpc_cn_port_any_t *port_any_p, unsigned8 *drepp, unsigned8 *end_of_pkt, unsigned32 *st ) { unsigned8 * string_end; union { /* a "proper" union to shut up lint */ unsigned8 *string; /* a string pointer */ rpc_cn_pres_result_list_p_t rtn; /* a return value */ } ptr; *st = rpc_s_ok; ptr.string = port_any_p->s; /* init our string pointer */ /* * byte-swap the length field if the endian's are different */ if (NDR_LOCAL_INT_REP != NDR_DREP_INT_REP (drepp)) { SWAP_INPLACE_16 (&port_any_p->length, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } } /* * only do the inplace string conversion if the two drep's are different */ if (NDR_LOCAL_CHAR_REP != NDR_DREP_CHAR_REP (drepp)) { string_end = ptr.string + port_any_p->length; if ( (string_end < ptr.string) || (end_of_pkt < string_end) ) { *st = rpc_s_bad_pkt; return (NULL); } rpc_util_strcvt ( NDR_LOCAL_CHAR_REP == ndr_c_char_ascii, port_any_p->length, ptr.string, ptr.string ); } /* * point to just beyond the end of the string and return that value * as our return value */ ptr.string += port_any_p->length; return (ptr.rtn); } /* **++ ** ** ROUTINE NAME: unpack_pres_context_list ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine unpacks a presentation context list in an RPC connection ** packet and returns a pointer to the next octet following the list. ** ** INPUTS: ** ** pcontp pointer to the presentation context list ** swap boolean indicating we need to perform byte swapping ** end_of_pkt ptr to 1 byte past end of packet ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: ** st The return status of this routine ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** return pointer to the next octet following the presentation ** context list ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_context_list ( rpc_cn_pres_cont_list_p_t pcontp, boolean32 swap, unsigned8 *end_of_pkt, unsigned32 *st ) { unsigned8 n; /* presentation context list element * loop count */ unsigned8 id; /* transfer syntax list loop count */ unsigned8 tsn; /* number of transfer syntaxes */ union { /* a "proper" union to shutup lint */ rpc_cn_pres_cont_elem_p_t ep; /* ptr to presentation context list * element */ rpc_cn_pres_syntax_id_p_t sp; /* ptr to a transfer syntax id */ rpc_cn_auth_tlr_p_t rtn; /* return value */ } ptrs; *st = rpc_s_ok; /* * Get a pointer to the first element. * * NB: The elements and lists that we are parsing are all variable length. */ ptrs.ep = &(pcontp->pres_cont_elem[0]); /* * Process each element of the presentation context list. */ for (n = 0; n < pcontp->n_context_elem; n++) { /* * Get the number of transfer syntaxes in this element. */ tsn = (ptrs.ep)->n_transfer_syn; /* * Unpack the abstract and transfer syntaxes. */ if (swap) { /* * Convert the presentation context id. */ SWAP_INPLACE_16 (&(ptrs.ep)->pres_context_id, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } /* * Convert the abstract syntax. */ SWAP_INPLACE_SYNTAX (&(ptrs.ep)->abstract_syntax, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } /* * Process each transfer syntax id of this element. */ for (id = 0; id < tsn; id++) { SWAP_INPLACE_SYNTAX (&(ptrs.ep)->transfer_syntaxes[id], end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } } } /* * Point to the next context element. */ (ptrs.sp) = &((ptrs.ep)->transfer_syntaxes[tsn]); } /* * We return a pointer to the next byte. */ return (ptrs.rtn); } /* **++ ** ** ROUTINE NAME: unpack_pres_result_list ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine unpacks a presentation result list in an RPC connection ** packet and returns a pointer to the next octet following the list. ** ** INPUTS: ** ** presp pointer to the presentation result list ** swap boolean indicating we need to perform byte swapping ** swap boolean indicating we need to perform byte swapping ** end_of_pkt ptr to 1 byte past end of packet ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: ** st The return status of this routine ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: ** ** return pointer to the next octet following the presentation ** result list ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL rpc_cn_auth_tlr_p_t unpack_pres_result_list ( rpc_cn_pres_result_list_p_t presp, boolean32 swap, unsigned8 *end_of_pkt, unsigned32 *st ) { unsigned8 n; /* presentation result list element loop * count */ unsigned8 prn; /* number of presentation results */ *st = rpc_s_ok; /* * Process each element of the presentation result list. */ prn = presp->n_results; for (n = 0; (n < prn) && swap; n++) { SWAP_INPLACE_16 (&presp->pres_results[n].result, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } SWAP_INPLACE_16 (&presp->pres_results[n].reason, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } SWAP_INPLACE_SYNTAX (&presp->pres_results[n].transfer_syntax, end_of_pkt, st); if (*st != rpc_s_ok) { return (NULL); } } /* * We return a pointer to the next byte. */ return ((rpc_cn_auth_tlr_p_t) &presp->pres_results[prn]); } /* **++ ** ** ROUTINE NAME: unpack_versions_supported ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine unpacks a 'rpc_cn_versions_supported_t' structure ** in an RPC connection packet and returns a pointer to the next ** octet following the versions structure. ** ** INPUTS: ** ** versions_p pointer to versions supported field ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: ** ** return pointer to the next octet after the ** 'versions_supported' ** ** SIDE EFFECTS: ** **-- **/ INTERNAL rpc_cn_auth_tlr_p_t unpack_versions_supported ( rpc_cn_versions_supported_p_t versions_p ) { union { rpc_cn_version_p_t versp; rpc_cn_auth_tlr_p_t rtn; } ptrs; int i; for (ptrs.versp = &versions_p->protocols[0], i = 0; in_protocols; i++, ptrs.versp++) ; return (ptrs.rtn); } /* **++ ** ** ROUTINE NAME: force_alignment ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine takes as in put a pointer which is to be aligned on a ** requested byte boundary. Note well that this routine is a potential ** source of portability problems since we are performing math operations ** on pointers. ** ** INPUTS: ** ** boundary number of octets of forced alignment ** ** INPUTS/OUTPUTS: ** ** ptr pointer to be aligned ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL void force_alignment ( unsigned32 boundary, unsigned8 **ptr ) { union { unsigned8 **as_ptr; unsigned32 *as_int; } anyptr; anyptr.as_ptr = ptr; if (*anyptr.as_int & (boundary-1)) { *anyptr.as_int += boundary; *anyptr.as_int &= ~(boundary-1); } } /* **++ ** ** ROUTINE NAME: end_of_stub_data ** ** SCOPE: INTERNAL - declared in cnpkt.c ** ** DESCRIPTION: ** ** This routine returns a pointer to the octet just following the stub data. ** ** INPUTS: ** ** pkt_p a pointer to the packet being unpacked ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ INTERNAL rpc_cn_auth_tlr_p_t end_of_stub_data ( rpc_cn_packet_p_t pkt_p ) { union { unsigned8 *any; rpc_cn_packet_p_t pkt; rpc_cn_auth_tlr_p_t rtn; } ptrs; unsigned32 stub_data_length; unsigned32 packet_header_overhead = 0; /* * Figure out our packet overhead. */ switch (RPC_CN_PKT_PTYPE (pkt_p)) { case RPC_C_CN_PKT_REQUEST: if (RPC_CN_PKT_OBJ_UUID_PRESENT (pkt_p)) { packet_header_overhead = RPC_CN_PKT_SIZEOF_RQST_HDR_W_OBJ; } else { packet_header_overhead = RPC_CN_PKT_SIZEOF_RQST_HDR_NO_OBJ; } break; case RPC_C_CN_PKT_RESPONSE: packet_header_overhead = RPC_CN_PKT_SIZEOF_RESP_HDR; break; case RPC_C_CN_PKT_FAULT: packet_header_overhead = RPC_CN_PKT_SIZEOF_FAULT_HDR; break; default: /* FIXME */ fprintf(stderr, "%s, unhandled case in switch: aborting\n", __PRETTY_FUNCTION__); raise(SIGILL); } #ifdef AUTH_QUESTIONS This is going to need some work based on what steve says about padding of stub data for auth trailers. #endif /* * calculate our stub data length */ stub_data_length = RPC_CN_PKT_FRAG_LEN(pkt_p) - RPC_CN_PKT_AUTH_LEN(pkt_p) - packet_header_overhead; /* * 1 - init our union of pointers to the start of the packet * 2 - bump to point to start of stub data in packet * 3 - bump to point to end of stub data */ ptrs.pkt = pkt_p; ptrs.any += packet_header_overhead; ptrs.any += stub_data_length; return (ptrs.rtn); } /* **++ ** ** ROUTINE NAME: rpc__cn_unpack_hdr ** ** SCOPE: PRIVATE - declared in cnpkt.h ** ** DESCRIPTION: ** ** This routine is called by the network receiver thread to unpack an ** RPC connection packet. Basically, this routine does all the byte ** swapping required between different endian machines as well as any ** ebcdic <-> ascii translation required. ** ** INPUTS: ** ** pkt_p a pointer to the packet to be unpacked ** data_size length of packet to ensure do not go past end of packet ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: unsigned32 error ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ PRIVATE unsigned32 rpc__cn_unpack_hdr ( rpc_cn_packet_p_t pkt_p, unsigned32 data_size ) { rpc_cn_auth_tlr_p_t authp; /* ptr to pkt authentication data */ rpc_cn_pres_cont_list_p_t pconp; /* ptr to pkt presentation context lists */ rpc_cn_pres_result_list_p_t presp; /* ptr to pkt presentation result lists */ rpc_cn_port_any_p_t secadrp; /* ptr to pkt secondary address data */ rpc_cn_versions_supported_p_t versp; /* ptr to pkt versions supported data */ unsigned8 *drepp; /* ptr to pkt drep[] data */ boolean swap; /* boolean says we swap bytes/words */ boolean authenticate; /* boolean says authentication data is valid */ boolean has_uuid; /* boolean says an OBJECT uuid is present */ unsigned32 st; /* status variable */ unsigned8 *end_of_pkt; /* ptr to 1 byte past end of packet */ end_of_pkt = (unsigned8 *) pkt_p; end_of_pkt += data_size; /* * Get the DREP and see if we need to do byte/word swapping. */ drepp = RPC_CN_PKT_DREP (pkt_p); swap = (NDR_DREP_INT_REP (drepp) != NDR_LOCAL_INT_REP); /* * RPC_CN_COMMON_HDR_T * * Unpack the common part of the packet header. */ if (swap) { SWAP_INPLACE_16 (&RPC_CN_PKT_FRAG_LEN (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_AUTH_LEN (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_32 (&RPC_CN_PKT_CALL_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } /* * See if the authentication data is valid. */ authenticate = RPC_CN_PKT_AUTH_LEN(pkt_p) != 0; authp = NULL; /* * Check for the presence of an OBJECT uuid. */ has_uuid = (RPC_CN_PKT_FLAGS (pkt_p) & RPC_C_CN_FLAGS_OBJECT_UUID) != 0; /* * Unpack the packet-type specific part of the packet. We also find the * start of the authentication data if there is any. */ switch (RPC_CN_PKT_PTYPE (pkt_p)) { /* * RPC_CN_BIND_HDR_T */ case RPC_C_CN_PKT_BIND: case RPC_C_CN_PKT_ALTER_CONTEXT: if (swap) { SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_RECV_FRAG (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_32 (&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } pconp = (rpc_cn_pres_cont_list_p_t)((unsigned8 *)(&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p)) + 4); authp = unpack_pres_context_list (pconp, swap, end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } break; /* * RPC_CN_BIND_ACK_HDR_T */ case RPC_C_CN_PKT_BIND_ACK: case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: if (swap) { SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_XMIT_FRAG (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_MAX_RECV_FRAG (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_32 (&RPC_CN_PKT_ASSOC_GROUP_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } secadrp = (rpc_cn_port_any_t *) ((unsigned8 *)(pkt_p) + RPC_CN_PKT_SIZEOF_BIND_ACK_HDR); presp = unpack_port_any (secadrp, drepp, end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } force_alignment (4, (unsigned8 **)&presp); authp = unpack_pres_result_list (presp, swap, end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } break; /* * RPC_CN_BIND_NACK_HDR_T */ case RPC_C_CN_PKT_BIND_NAK: if (swap) { SWAP_INPLACE_16 (&RPC_CN_PKT_PROV_REJ_REASON (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } versp = &RPC_CN_PKT_VERSIONS (pkt_p); authp = unpack_versions_supported (versp); break; /* * RPC_CN_REQUEST_HDR_T */ case RPC_C_CN_PKT_REQUEST: if (swap) { SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_OPNUM (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } if (has_uuid) { SWAP_INPLACE_UUID (&RPC_CN_PKT_OBJECT (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } } authp = end_of_stub_data (pkt_p); break; /* * RPC_CN_RESPONSE_HDR_T */ case RPC_C_CN_PKT_RESPONSE: if (swap) { SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } authp = end_of_stub_data (pkt_p); break; /* * RPC_CN_FAULT_HDR_T */ case RPC_C_CN_PKT_FAULT: if (swap) { SWAP_INPLACE_32 (&RPC_CN_PKT_ALLOC_HINT (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_16 (&RPC_CN_PKT_PRES_CONT_ID (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } SWAP_INPLACE_32 (&RPC_CN_PKT_STATUS (pkt_p), end_of_pkt, &st); if (st != rpc_s_ok) { return (st); } } authp = end_of_stub_data (pkt_p); break; /* * RPC_CN_AUTH3_HDR_T */ case RPC_C_CN_PKT_SHUTDOWN: case RPC_C_CN_PKT_AUTH3: case RPC_C_CN_PKT_REMOTE_ALERT: case RPC_C_CN_PKT_ORPHANED: break; default: /* "(%s) Illegal or unknown packet type: %x\n" */ rpc_dce_svc_printf ( __FILE__, __LINE__, "%s %x", rpc_svc_cn_pkt, svc_c_sev_warning, rpc_m_bad_pkt_type, "rpc__cn_unpack_hdr", RPC_CN_PKT_PTYPE(pkt_p) ); return (rpc_s_bad_pkt); } /* * Unpack the authentication part of the packet if it exists. */ if (authenticate && swap) { switch (RPC_CN_PKT_PTYPE (pkt_p)) { case RPC_C_CN_PKT_BIND: case RPC_C_CN_PKT_ALTER_CONTEXT: case RPC_C_CN_PKT_BIND_ACK: case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: case RPC_C_CN_PKT_BIND_NAK: case RPC_C_CN_PKT_AUTH3: { #ifdef DEBUG char *p; #endif rpc_authn_protocol_id_t authn_protocol; authp = RPC_CN_PKT_AUTH_TLR (pkt_p, RPC_CN_PKT_FRAG_LEN (pkt_p)); #ifdef DEBUG p = (char *)authp; force_alignment(4, (unsigned8 **)&authp); if (p != (char *)authp) { /* * rpc_m_unalign_authtrl * "(%s) Unaligned RPC_CN_PKT_AUTH_TRL" */ rpc_dce_svc_printf ( __FILE__, __LINE__, "%s", rpc_svc_cn_pkt, svc_c_sev_fatal | svc_c_action_abort, rpc_m_unalign_authtrl, "rpc__cn_unpack_hdr" ); return (rpc_s_bad_pkt); } #endif authn_protocol = RPC_CN_AUTH_CVT_ID_WIRE_TO_API (authp->auth_type, &st); if (st == rpc_s_ok) { RPC_CN_AUTH_TLR_UNPACK (authn_protocol, pkt_p, RPC_CN_PKT_AUTH_LEN (pkt_p), drepp); } break; } default: /* * We do not need the auth trailer of the other packet * types since they are thrown away after recv_check. * So don't bother to unpack them in these cases. */ break; } } return (rpc_s_ok); } /* **++ ** ** ROUTINE NAME: rpc__cn_pkt_format_common ** ** SCOPE: PRIVATE - declared in cnpkt.h ** ** DESCRIPTION: ** ** This routine will format the fields common to all packet ** types in the NCA connection protocol. ** ** INPUTS: ** ** pkt_p a pointer to the packet to be formatted ** ptype the packet type ** flags the packet flags ** frag_len the length of the packet (header and body) ** auth_len the length of the authentication trailer ** call_id call identifier ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ PRIVATE void rpc__cn_pkt_format_common ( rpc_cn_packet_p_t pkt_p, unsigned32 ptype, unsigned32 flags, unsigned32 frag_len, unsigned32 auth_len, unsigned32 call_id, unsigned8 minor_version ) { /* * First copy the template common packet header. */ memcpy (pkt_p, &rpc_g_cn_common_hdr, sizeof (rpc_g_cn_common_hdr)); /* * Now fill in the fields based on the input args to this * routine. */ RPC_CN_PKT_PTYPE (pkt_p) = (unsigned8)ptype; RPC_CN_PKT_FLAGS (pkt_p) = (unsigned8)flags; RPC_CN_PKT_FRAG_LEN (pkt_p) = (unsigned16)frag_len; RPC_CN_PKT_AUTH_LEN (pkt_p) = (unsigned16)auth_len; RPC_CN_PKT_CALL_ID (pkt_p) = call_id; RPC_CN_PKT_VERS_MINOR (pkt_p) = minor_version; } /* **++ ** ** ROUTINE NAME: rpc__cn_stats_print ** ** SCOPE: PRIVATE - declared in cnpkt.h ** ** DESCRIPTION: ** ** This routine will dump all statistics kept by the CN protocol. ** ** INPUTS: none ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ PRIVATE void rpc__cn_stats_print (void) { unsigned16 i; RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("RPC CN Protocol Statistics")); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("--------------------------------------------------------")); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Calls sent: %9u", rpc_g_cn_mgmt.calls_sent)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Calls rcvd: %9u", rpc_g_cn_mgmt.calls_rcvd)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Pkts sent: %9u", rpc_g_cn_mgmt.pkts_sent)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Pkts rcvd: %9u", rpc_g_cn_mgmt.pkts_rcvd)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Connects established: %9u", rpc_g_cn_mgmt.connections)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Connects broken: %9u", rpc_g_cn_mgmt.closed_connections)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Associations alloced: %9u", rpc_g_cn_mgmt.alloced_assocs)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Associations dealloced:%9u", rpc_g_cn_mgmt.dealloced_assocs)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Associations aborted: %9u", rpc_g_cn_mgmt.aborted_assocs)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Association groups: %9u", rpc_g_cn_mgmt.assoc_grps)); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("Breakdown by packet type sent rcvd")); RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("-------------------------------------------------------------------")); for (i = 0; i <= RPC_C_CN_PKT_MAX_TYPE; i++) { RPC_DBG_PRINTF(rpc_e_dbg_stats, 1, ("(%02u) %-10s %9u %9u", i, rpc__cn_pkt_name(i), rpc_g_cn_mgmt.pstats[i].sent, rpc_g_cn_mgmt.pstats[i].rcvd)); } } /* **++ ** ** ROUTINE NAME: rpc__cn_pkt_name ** ** SCOPE: PRIVATE - declared in cnpkt.h ** ** DESCRIPTION: ** ** Return the string name for a type of packet. This can't simply be ** a variable because of the vagaries of global libraries. ** ** INPUTS: ** ** ptype The packet type. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: none ** ** SIDE EFFECTS: none ** **-- **/ PRIVATE const char *rpc__cn_pkt_name ( unsigned32 ptype ATTRIBUTE_UNUSED ) { #ifndef DEBUG return(""); #else static const char *names[RPC_C_CN_PKT_MAX_TYPE + 1] = { "REQUEST ", "PING ", "RESPONSE ", "FAULT ", "WORKING ", "NOCALL ", "REJECT ", "ACK ", "QUIT ", "FACK ", "QUACK ", "BIND ", "BIND_ACK ", "BIND_NAK ", "ALT_CTXT ", "ALT_CTXT_RESP", "AUTH3 ", "SHUTDOWN ", "REMOTE_ALERT ", "ORPHANED " }; return((int) ptype > RPC_C_CN_PKT_MAX_TYPE ? "BOGUS PACKET TYPE" : names[(int) ptype]); #endif } /* **++ ** ** ROUTINE NAME: rpc__cn_pkt_crc_compute ** ** SCOPE: PRIVATE - declared in cnpkt.h ** ** DESCRIPTION: ** ** Compute a CRC-32/AUTODIN-II. ** ** First, the polynomial itself and its table of feedback terms. The ** polynomial is ** X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 ** Note that we take it "backwards" and put the highest-order term in ** the lowest-order bit. The X^32 term is "implied"; the LSB is the ** X^31 term, etc. The X^0 term (usually shown as "+1") results in ** the MSB being 1. ** Note that the usual hardware shift register implementation, which ** is what we're using (we're merely optimizing it by doing eight-bit ** chunks at a time) shifts bits into the lowest-order term. In our ** implementation, that means shifting towards the right. Why do we ** do it this way? Because the calculated CRC must be transmitted in ** order from highest-order term to lowest-order term. UARTs transmit ** characters in order from LSB to MSB. By storing the CRC this way, ** we hand it to the UART in the order low-byte to high-byte; the UART ** sends each low-bit to hight-bit; and the result is transmission bit ** by bit from highest- to lowest-order term without requiring any bit ** shuffling on our part. Reception works similarly. ** The feedback terms table consists of 256, 32-bit entries. Notes: ** ** 1. The table can be generated at runtime if desired; code to do so ** is shown later. It might not be obvious, but the feedback ** terms simply represent the results of eight shift/xor opera- ** tions for all combinations of data and CRC register values. ** ** 2. The CRC accumulation logic is the same for all CRC polynomials, ** be they sixteen or thirty-two bits wide. You simply choose the ** appropriate table. Alternatively, because the table can be ** generated at runtime, you can start by generating the table for ** the polynomial in question and use exactly the same "updcrc", ** if your application needn't simultaneously handle two CRC ** polynomials. (Note, however, that XMODEM is strange.) ** ** 3. For 16-bit CRCs, the table entries need be only 16 bits wide; ** of course, 32-bit entries work OK if the high 16 bits are zero. ** ** 4. The values must be right-shifted by eight bits by the "updcrc" ** logic; the shift must be unsigned (bring in zeroes). On some ** hardware you could probably optimize the shift in assembler by ** using byte-swap instructions. ** ** INPUTS: ** ** block The block whose checksum is to be computed. ** block_len The length, in bytes, of the block. ** ** INPUTS/OUTPUTS: none ** ** OUTPUTS: none ** ** IMPLICIT INPUTS: none ** ** IMPLICIT OUTPUTS: none ** ** FUNCTION VALUE: unsigned32 ** ** The 32-bit CRC of the block. ** ** SIDE EFFECTS: none ** **-- **/ PRIVATE unsigned32 rpc__cn_pkt_crc_compute ( unsigned8 *block, unsigned32 block_len ) { register unsigned_char_t *data; register unsigned32 c = 0; register unsigned32 idx; unsigned32 i; static unsigned32 crc_table[256] = { 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU }; data = (unsigned_char_t *) block; for (i = 0; i < block_len; i++) { idx = (data[i] ^ c); idx &= 0xff; c >>= 8; c ^= crc_table[idx]; } return (c); }