#include <strings.h>
#include <ndl/rpcpdu.ndl>
#include <libmlrpc/ndr.h>
#include <libmlrpc/mlrpc.h>
int
mlrpc_encode_decode_common(struct mlrpc_xaction *mxa, int mode, unsigned opnum,
struct ndr_typeinfo *ti, void *datum)
{
struct mlndr_stream *mlnds;
int m_op = NDR_MODE_TO_M_OP(mode);
int rc;
if (m_op == NDR_M_OP_MARSHALL)
mlnds = &mxa->send_mlnds;
else
mlnds = &mxa->recv_mlnds;
if (!NDR_MODE_MATCH(mlnds, mode))
return (MLRPC_DRC_FAULT_MODE_MISMATCH);
if (mlndo_operation(mlnds, ti, opnum, datum))
return (MLRPC_DRC_OK);
switch (mlnds->error) {
case NDR_ERR_MALLOC_FAILED:
rc = MLRPC_DRC_FAULT_OUT_OF_MEMORY;
break;
case NDR_ERR_SWITCH_VALUE_INVALID:
rc = MLRPC_DRC_FAULT_PARAM_0_INVALID;
break;
case NDR_ERR_UNDERFLOW:
rc = MLRPC_DRC_FAULT_RECEIVED_RUNT;
break;
case NDR_ERR_GROW_FAILED:
rc = MLRPC_DRC_FAULT_ENCODE_TOO_BIG;
break;
default:
if (m_op == NDR_M_OP_MARSHALL)
rc = MLRPC_DRC_FAULT_ENCODE_FAILED;
else
rc = MLRPC_DRC_FAULT_DECODE_FAILED;
break;
}
return (rc);
}
int
mlrpc_decode_call(struct mlrpc_xaction *mxa, void *params)
{
int rc;
rc = mlrpc_encode_decode_common(mxa, NDR_MODE_CALL_RECV,
mxa->opnum, mxa->binding->service->interface_ti, params);
return (rc + MLRPC_PTYPE_REQUEST);
}
int
mlrpc_encode_return(struct mlrpc_xaction *mxa, void *params)
{
int rc;
rc = mlrpc_encode_decode_common(mxa, NDR_MODE_RETURN_SEND,
mxa->opnum, mxa->binding->service->interface_ti, params);
return (rc + MLRPC_PTYPE_RESPONSE);
}
int
mlrpc_encode_call(struct mlrpc_xaction *mxa, void *params)
{
int rc;
rc = mlrpc_encode_decode_common(mxa, NDR_MODE_CALL_SEND,
mxa->opnum, mxa->binding->service->interface_ti, params);
return (rc + MLRPC_PTYPE_REQUEST);
}
int
mlrpc_decode_return(struct mlrpc_xaction *mxa, void *params)
{
int rc;
rc = mlrpc_encode_decode_common(mxa, NDR_MODE_RETURN_RECV,
mxa->opnum, mxa->binding->service->interface_ti, params);
return (rc + MLRPC_PTYPE_RESPONSE);
}
int
mlrpc_decode_pdu_hdr(struct mlrpc_xaction *mxa)
{
mlrpcconn_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
struct mlndr_stream *mlnds = &mxa->recv_mlnds;
int ptype;
int rc;
int charset;
int byte_order;
if (mlnds->m_op != NDR_M_OP_UNMARSHALL)
return (MLRPC_DRC_FAULT_MODE_MISMATCH + 0xFF);
rc = MLNDS_GROW_PDU(mlnds, sizeof (mlrpcconn_common_header_t), 0);
if (!rc)
return (MLRPC_DRC_FAULT_RECEIVED_RUNT + 0xFF);
rc = MLNDS_GET_PDU(mlnds, 0, 8, (char *)hdr, 0, 0);
if (!rc)
return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
charset = hdr->packed_drep.intg_char_rep & MLRPC_REPLAB_CHAR_MASK;
if (charset != MLRPC_REPLAB_CHAR_ASCII)
return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
byte_order = hdr->packed_drep.intg_char_rep & MLRPC_REPLAB_INTG_MASK;
mlnds->swap = (byte_order != mlrpc_native_byte_order) ? 1 : 0;
ptype = hdr->ptype;
if (ptype == MLRPC_PTYPE_REQUEST &&
(hdr->pfc_flags & MLRPC_PFC_OBJECT_UUID) != 0) {
ptype = MLRPC_PTYPE_REQUEST_WITH;
}
mxa->ptype = hdr->ptype;
rc = mlrpc_encode_decode_common(mxa,
NDR_M_OP_AND_DIR_TO_MODE(mlnds->m_op, mlnds->dir),
ptype, &TYPEINFO(mlrpcconn_hdr), hdr);
return (rc + 0xFF);
}
void
mlrpc_decode_frag_hdr(struct mlndr_stream *mlnds,
mlrpcconn_request_hdr_t * hdr, const uint8_t * pdu_scan_offset)
{
const mlrpcconn_common_header_t *tmp;
int byte_order;
bcopy(pdu_scan_offset, hdr, MLRPC_RSP_HDR_SIZE);
byte_order = hdr->common_hdr.packed_drep.intg_char_rep & MLRPC_REPLAB_INTG_MASK;
if (byte_order != mlrpc_native_byte_order) {
tmp = (const mlrpcconn_common_header_t *)pdu_scan_offset;
mlnds_bswap(&tmp->frag_length, &hdr->common_hdr.frag_length,
sizeof (WORD));
mlnds_bswap(&tmp->auth_length, &hdr->common_hdr.auth_length,
sizeof (WORD));
mlnds_bswap(&tmp->call_id, &hdr->common_hdr.call_id, sizeof (DWORD));
}
}
int
mlrpc_encode_pdu_hdr(struct mlrpc_xaction *mxa)
{
mlrpcconn_common_header_t *hdr = &mxa->send_hdr.common_hdr;
struct mlndr_stream *mlnds = &mxa->send_mlnds;
int ptype;
int rc;
if (mlnds->m_op != NDR_M_OP_MARSHALL)
return (MLRPC_DRC_FAULT_MODE_MISMATCH + 0xFF);
ptype = hdr->ptype;
if (ptype == MLRPC_PTYPE_REQUEST &&
(hdr->pfc_flags & MLRPC_PFC_OBJECT_UUID) != 0) {
ptype = MLRPC_PTYPE_REQUEST_WITH;
}
rc = mlrpc_encode_decode_common(mxa,
NDR_M_OP_AND_DIR_TO_MODE(mlnds->m_op, mlnds->dir),
ptype, &TYPEINFO(mlrpcconn_hdr), hdr);
return (rc + 0xFF);
}
extern struct ndr_typeinfo ndt__uint8_t;
extern struct ndr_typeinfo ndt__uint16_t;
extern struct ndr_typeinfo ndt__uint32_t;
int mlndr__mlrpcconn_bind_ack_hdr(struct ndr_reference *encl_ref);
struct ndr_typeinfo ndt__mlrpcconn_bind_ack_hdr = {
"_mlrpcconn_bind_ack_hdr",
1,
3,
NDR_F_STRUCT,
mlndr__mlrpcconn_bind_ack_hdr,
68,
0,
68,
0,
};
int
mlndr__mlrpcconn_bind_ack_hdr(struct ndr_reference *encl_ref)
{
struct mlndr_stream *mlnds = encl_ref->stream;
struct mlrpcconn_bind_ack_hdr *val =
(struct mlrpcconn_bind_ack_hdr *)encl_ref->datum;
struct ndr_reference myref;
unsigned long offset;
bzero(&myref, sizeof (myref));
myref.enclosing = encl_ref;
myref.stream = encl_ref->stream;
myref.packed_alignment = 0;
NDR_MEMBER(_mlrpcconn_common_header, common_hdr, 0UL);
NDR_MEMBER(_uint16_t, max_xmit_frag, 16UL);
NDR_MEMBER(_uint16_t, max_recv_frag, 18UL);
NDR_MEMBER(_uint32_t, assoc_group_id, 20UL);
offset = 24UL;
switch (mlnds->m_op) {
case NDR_M_OP_MARSHALL:
val->sec_addr.length =
strlen((char *)val->sec_addr.port_spec) + 1;
break;
case NDR_M_OP_UNMARSHALL:
break;
default:
NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
return (0);
}
NDR_MEMBER(_uint16_t, sec_addr.length, offset);
NDR_MEMBER_ARR_WITH_DIMENSION(_uint8_t, sec_addr.port_spec,
offset+2UL, val->sec_addr.length);
offset += 2;
offset += val->sec_addr.length;
offset += (4 - offset) & 3;
NDR_MEMBER(_mlrpc_p_result_list, p_result_list, offset);
return (1);
}
unsigned
mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *bahdr)
{
unsigned offset;
unsigned length;
offset = 24UL;
length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
offset += 2;
offset += length;
offset += (4 - offset) & 3;
offset += sizeof (bahdr->p_result_list);
return (offset);
}