bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc) { int i; if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } if (zdrs->pos + *size * elsize > zdrs->size) { return FALSE; } if (zdrs->x_op == ZDR_DECODE) { *arrp = zdr_malloc(zdrs, *size * elsize); if (*arrp == NULL) { return FALSE; } memset(*arrp, 0, *size * elsize); } for (i = 0; i < *size; i++) { if (!proc(zdrs, *arrp + i * elsize)) { return FALSE; } } return TRUE; }
bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize) { uint32_t size; if (zdrs->x_op == ZDR_ENCODE) { size = strlen(*strp); } if (!libnfs_zdr_u_int(zdrs, &size)) { return FALSE; } if (zdrs->pos + size > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: return libnfs_zdr_opaque(zdrs, *strp, size); case ZDR_DECODE: *strp = zdr_malloc(zdrs, size + 1); if (*strp == NULL) { return FALSE; } (*strp)[size] = 0; return libnfs_zdr_opaque(zdrs, *strp, size); } return FALSE; }
bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize) { if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } if (zdrs->pos + *size > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: memcpy(&zdrs->buf[zdrs->pos], *bufp, *size); zdrs->pos += *size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; case ZDR_DECODE: if (*bufp == NULL) { *bufp = zdr_malloc(zdrs, *size); } memcpy(*bufp, &zdrs->buf[zdrs->pos], *size); zdrs->pos += *size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; } return FALSE; }
static int rpc_process_call(struct rpc_context *rpc, ZDR *zdr) { struct rpc_msg call; struct rpc_endpoint *endpoint; int i, min_version = 0, max_version = 0, found_program = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&call, 0, sizeof(struct rpc_msg)); if (zdr_callmsg(rpc, zdr, &call) == 0) { rpc_set_error(rpc, "Failed to decode CALL message. %s", rpc_get_error(rpc)); return rpc_send_error_reply(rpc, &call, GARBAGE_ARGS, 0, 0); } for (endpoint = rpc->endpoints; endpoint; endpoint = endpoint->next) { if (call.body.cbody.prog == endpoint->program) { if (!found_program) { min_version = max_version = endpoint->version; } if (endpoint->version < min_version) { min_version = endpoint->version; } if (endpoint->version > max_version) { max_version = endpoint->version; } found_program = 1; if (call.body.cbody.vers == endpoint->version) { break; } } } if (endpoint == NULL) { rpc_set_error(rpc, "No endpoint found for CALL " "program:0x%08x version:%d\n", call.body.cbody.prog, call.body.cbody.vers); if (!found_program) { return rpc_send_error_reply(rpc, &call, PROG_UNAVAIL, 0, 0); } return rpc_send_error_reply(rpc, &call, PROG_MISMATCH, min_version, max_version); } for (i = 0; i < endpoint->num_procs; i++) { if (endpoint->procs[i].proc == call.body.cbody.proc) { if (endpoint->procs[i].decode_buf_size) { call.body.cbody.args = zdr_malloc(zdr, endpoint->procs[i].decode_buf_size); } if (!endpoint->procs[i].decode_fn(zdr, call.body.cbody.args)) { rpc_set_error(rpc, "Failed to unmarshall " "call payload"); return rpc_send_error_reply(rpc, &call, GARBAGE_ARGS, 0 ,0); } return endpoint->procs[i].func(rpc, &call); } } return rpc_send_error_reply(rpc, &call, PROC_UNAVAIL, 0 ,0); }
bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize) { uint32_t size; if (zdrs->x_op == ZDR_ENCODE) { size = strlen(*strp); } if (!libnfs_zdr_u_int(zdrs, &size)) { return FALSE; } if (zdrs->pos + size > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: return libnfs_zdr_opaque(zdrs, *strp, size); case ZDR_DECODE: /* If the we string is null terminated we can just return it * in place. */ if (zdrs->size > zdrs->pos + size && zdrs->buf[zdrs->pos + size] == 0) { if (*strp == NULL) { *strp = &zdrs->buf[zdrs->pos]; (*strp)[size] = 0; zdrs->pos += size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; } (*strp)[size] = 0; return libnfs_zdr_opaque(zdrs, *strp, size); } /* Crap. The string is not null terminated in the rx buffer. * we have to allocate a buffer so we can add the null byte. */ *strp = zdr_malloc(zdrs, size + 1); if (*strp == NULL) { return FALSE; } (*strp)[size] = 0; return libnfs_zdr_opaque(zdrs, *strp, size); } return FALSE; }
bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc) { bool_t more_data; more_data = (*objp != NULL); if (!libnfs_zdr_bool(zdrs, &more_data)) { return FALSE; } if (more_data == 0) { *objp = NULL; return TRUE; } if (zdrs->x_op == ZDR_DECODE) { *objp = zdr_malloc(zdrs, size); if (*objp == NULL) { return FALSE; } memset(*objp, 0, size); } return proc(zdrs, *objp); }