1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/libcli/named_pipe_auth/tstream_u32_read.c
Volker Lendecke 05c358759c rpc: Add tstream_u32_read
In npa_tstream.c we have two next_vector functions reading a big
endian uin32_t length and then the blob described by the length. This
factors that next_vector out into a central routine.

Why? I'll add another NPA protocol in the future, and this would add
yet another two copies of that next_vector code

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
2019-04-05 00:00:10 +00:00

160 lines
3.7 KiB
C

/*
* Unix SMB/CIFS implementation.
*
* Copyright (C) Volker Lendecke 2019
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "replace.h"
#include "system/filesys.h"
#include "tstream_u32_read.h"
#include "lib/util/byteorder.h"
#include "lib/util/tevent_unix.h"
struct tstream_u32_read_state {
size_t max_msglen;
size_t buflen;
uint8_t *buf;
};
static int tstream_u32_read_next_vector(struct tstream_context *stream,
void *private_data,
TALLOC_CTX *mem_ctx,
struct iovec **_vector,
size_t *_count);
static void tstream_u32_read_done(struct tevent_req *subreq);
struct tevent_req *tstream_u32_read_send(
TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
uint32_t max_msglen,
struct tstream_context *stream)
{
struct tevent_req *req = NULL, *subreq = NULL;
struct tstream_u32_read_state *state = NULL;
req = tevent_req_create(
mem_ctx, &state, struct tstream_u32_read_state);
if (req == NULL) {
return NULL;
}
state->max_msglen = max_msglen;
subreq = tstream_readv_pdu_send(
state,
ev,
stream,
tstream_u32_read_next_vector,
state);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, tstream_u32_read_done, req);
return req;
}
static int tstream_u32_read_next_vector(struct tstream_context *stream,
void *private_data,
TALLOC_CTX *mem_ctx,
struct iovec **_vector,
size_t *_count)
{
struct tstream_u32_read_state *state = talloc_get_type_abort(
private_data, struct tstream_u32_read_state);
size_t buflen = talloc_get_size(state->buf);
struct iovec *vector;
uint32_t msg_len;
size_t ofs = 0;
size_t count;
if (buflen == 0) {
msg_len = 4;
state->buf = talloc_array(state, uint8_t, msg_len);
if (state->buf == NULL) {
return -1;
}
} else if (buflen == 4) {
ofs = 4;
msg_len = RIVAL(state->buf, 0);
if ((msg_len == 0) || (msg_len > state->max_msglen)) {
errno = EMSGSIZE;
return -1;
}
msg_len += ofs;
if (msg_len < ofs) {
errno = EMSGSIZE;
return -1;
}
state->buf = talloc_realloc(
state, state->buf, uint8_t, msg_len);
if (state->buf == NULL) {
return -1;
}
} else {
*_vector = NULL;
*_count = 0;
return 0;
}
vector = talloc(mem_ctx, struct iovec);
if (vector == NULL) {
return -1;
}
*vector = (struct iovec) {
.iov_base = state->buf + ofs, .iov_len = msg_len - ofs,
};
count = 1;
*_vector = vector;
*_count = count;
return 0;
}
static void tstream_u32_read_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
int ret, err;
ret = tstream_readv_pdu_recv(subreq, &err);
TALLOC_FREE(subreq);
if (ret == -1) {
tevent_req_error(req, err);
return;
}
tevent_req_done(req);
}
int tstream_u32_read_recv(
struct tevent_req *req,
TALLOC_CTX *mem_ctx,
uint8_t **buf,
size_t *buflen)
{
struct tstream_u32_read_state *state = tevent_req_data(
req, struct tstream_u32_read_state);
int err;
if (tevent_req_is_unix_error(req, &err)) {
return err;
}
*buflen = talloc_get_size(state->buf);
*buf = talloc_move(mem_ctx, &state->buf);
return 0;
}