Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Copyright (C) Volker Lendecke 2019
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "replace.h"
21 : #include "system/filesys.h"
22 : #include "tstream_u32_read.h"
23 : #include "lib/util/byteorder.h"
24 : #include "lib/util/tevent_unix.h"
25 :
26 : struct tstream_u32_read_state {
27 : size_t max_msglen;
28 : size_t buflen;
29 : uint8_t *buf;
30 : };
31 :
32 : static int tstream_u32_read_next_vector(struct tstream_context *stream,
33 : void *private_data,
34 : TALLOC_CTX *mem_ctx,
35 : struct iovec **_vector,
36 : size_t *_count);
37 : static void tstream_u32_read_done(struct tevent_req *subreq);
38 :
39 98737 : struct tevent_req *tstream_u32_read_send(
40 : TALLOC_CTX *mem_ctx,
41 : struct tevent_context *ev,
42 : uint32_t max_msglen,
43 : struct tstream_context *stream)
44 : {
45 98737 : struct tevent_req *req = NULL, *subreq = NULL;
46 98737 : struct tstream_u32_read_state *state = NULL;
47 :
48 98737 : req = tevent_req_create(
49 : mem_ctx, &state, struct tstream_u32_read_state);
50 98737 : if (req == NULL) {
51 0 : return NULL;
52 : }
53 98737 : state->max_msglen = max_msglen;
54 :
55 98737 : subreq = tstream_readv_pdu_send(
56 : state,
57 : ev,
58 : stream,
59 : tstream_u32_read_next_vector,
60 : state);
61 98737 : if (tevent_req_nomem(subreq, req)) {
62 0 : return tevent_req_post(req, ev);
63 : }
64 98737 : tevent_req_set_callback(subreq, tstream_u32_read_done, req);
65 98737 : return req;
66 : }
67 :
68 296211 : static int tstream_u32_read_next_vector(struct tstream_context *stream,
69 : void *private_data,
70 : TALLOC_CTX *mem_ctx,
71 : struct iovec **_vector,
72 : size_t *_count)
73 : {
74 296211 : struct tstream_u32_read_state *state = talloc_get_type_abort(
75 : private_data, struct tstream_u32_read_state);
76 296211 : size_t buflen = talloc_get_size(state->buf);
77 3744 : struct iovec *vector;
78 3744 : uint32_t msg_len;
79 296211 : size_t ofs = 0;
80 3744 : size_t count;
81 :
82 296211 : if (buflen == 0) {
83 98737 : msg_len = 4;
84 98737 : state->buf = talloc_array(state, uint8_t, msg_len);
85 98737 : if (state->buf == NULL) {
86 0 : return -1;
87 : }
88 197474 : } else if (buflen == 4) {
89 :
90 98737 : ofs = 4;
91 :
92 98737 : msg_len = RIVAL(state->buf, 0);
93 98737 : if ((msg_len == 0) || (msg_len > state->max_msglen)) {
94 0 : errno = EMSGSIZE;
95 0 : return -1;
96 : }
97 98737 : msg_len += ofs;
98 98737 : if (msg_len < ofs) {
99 0 : errno = EMSGSIZE;
100 0 : return -1;
101 : }
102 :
103 98737 : state->buf = talloc_realloc(
104 : state, state->buf, uint8_t, msg_len);
105 98737 : if (state->buf == NULL) {
106 0 : return -1;
107 : }
108 : } else {
109 98737 : *_vector = NULL;
110 98737 : *_count = 0;
111 98737 : return 0;
112 : }
113 :
114 197474 : vector = talloc(mem_ctx, struct iovec);
115 197474 : if (vector == NULL) {
116 0 : return -1;
117 : }
118 197474 : *vector = (struct iovec) {
119 197474 : .iov_base = state->buf + ofs, .iov_len = msg_len - ofs,
120 : };
121 197474 : count = 1;
122 :
123 197474 : *_vector = vector;
124 197474 : *_count = count;
125 197474 : return 0;
126 : }
127 :
128 98737 : static void tstream_u32_read_done(struct tevent_req *subreq)
129 : {
130 98737 : struct tevent_req *req = tevent_req_callback_data(
131 : subreq, struct tevent_req);
132 1248 : int ret, err;
133 :
134 98737 : ret = tstream_readv_pdu_recv(subreq, &err);
135 98737 : TALLOC_FREE(subreq);
136 98737 : if (ret == -1) {
137 0 : tevent_req_error(req, err);
138 0 : return;
139 : }
140 98737 : tevent_req_done(req);
141 : }
142 :
143 98737 : int tstream_u32_read_recv(
144 : struct tevent_req *req,
145 : TALLOC_CTX *mem_ctx,
146 : uint8_t **buf,
147 : size_t *buflen)
148 : {
149 98737 : struct tstream_u32_read_state *state = tevent_req_data(
150 : req, struct tstream_u32_read_state);
151 1248 : int err;
152 :
153 98737 : if (tevent_req_is_unix_error(req, &err)) {
154 0 : return err;
155 : }
156 98737 : *buflen = talloc_get_size(state->buf);
157 98737 : *buf = talloc_move(mem_ctx, &state->buf);
158 98737 : return 0;
159 : }
|