Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/hastd/hast_proto.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2009-2010 The FreeBSD Foundation
5
* Copyright (c) 2011 Pawel Jakub Dawidek <[email protected]>
6
* All rights reserved.
7
*
8
* This software was developed by Pawel Jakub Dawidek under sponsorship from
9
* the FreeBSD Foundation.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*/
32
33
#include <sys/cdefs.h>
34
#include <sys/endian.h>
35
36
#include <errno.h>
37
#include <strings.h>
38
39
#include <hast.h>
40
#include <ebuf.h>
41
#include <nv.h>
42
#include <pjdlog.h>
43
#include <proto.h>
44
45
#include "hast_checksum.h"
46
#include "hast_compression.h"
47
#include "hast_proto.h"
48
49
struct hast_main_header {
50
/* Protocol version. */
51
uint8_t version;
52
/* Size of nv headers. */
53
uint32_t size;
54
} __packed;
55
56
typedef int hps_send_t(const struct hast_resource *, struct nv *nv, void **,
57
size_t *, bool *);
58
typedef int hps_recv_t(const struct hast_resource *, struct nv *nv, void **,
59
size_t *, bool *);
60
61
struct hast_pipe_stage {
62
const char *hps_name;
63
hps_send_t *hps_send;
64
hps_recv_t *hps_recv;
65
};
66
67
static struct hast_pipe_stage pipeline[] = {
68
{ "compression", compression_send, compression_recv },
69
{ "checksum", checksum_send, checksum_recv }
70
};
71
72
/*
73
* Send the given nv structure via conn.
74
* We keep headers in nv structure and pass data in separate argument.
75
* There can be no data at all (data is NULL then).
76
*/
77
int
78
hast_proto_send(const struct hast_resource *res, struct proto_conn *conn,
79
struct nv *nv, const void *data, size_t size)
80
{
81
struct hast_main_header hdr;
82
struct ebuf *eb;
83
bool freedata;
84
void *dptr, *hptr;
85
size_t hsize;
86
int ret;
87
88
dptr = (void *)(uintptr_t)data;
89
freedata = false;
90
ret = -1;
91
92
if (data != NULL) {
93
unsigned int ii;
94
95
for (ii = 0; ii < sizeof(pipeline) / sizeof(pipeline[0]);
96
ii++) {
97
(void)pipeline[ii].hps_send(res, nv, &dptr, &size,
98
&freedata);
99
}
100
nv_add_uint32(nv, size, "size");
101
if (nv_error(nv) != 0) {
102
errno = nv_error(nv);
103
goto end;
104
}
105
}
106
107
eb = nv_hton(nv);
108
if (eb == NULL)
109
goto end;
110
111
hdr.version = res != NULL ? res->hr_version : HAST_PROTO_VERSION;
112
hdr.size = htole32((uint32_t)ebuf_size(eb));
113
if (ebuf_add_head(eb, &hdr, sizeof(hdr)) == -1)
114
goto end;
115
116
hptr = ebuf_data(eb, &hsize);
117
if (proto_send(conn, hptr, hsize) == -1)
118
goto end;
119
if (data != NULL && proto_send(conn, dptr, size) == -1)
120
goto end;
121
122
ret = 0;
123
end:
124
if (freedata)
125
free(dptr);
126
return (ret);
127
}
128
129
int
130
hast_proto_recv_hdr(const struct proto_conn *conn, struct nv **nvp)
131
{
132
struct hast_main_header hdr;
133
struct nv *nv;
134
struct ebuf *eb;
135
void *hptr;
136
137
eb = NULL;
138
nv = NULL;
139
140
if (proto_recv(conn, &hdr, sizeof(hdr)) == -1)
141
goto fail;
142
143
if (hdr.version > HAST_PROTO_VERSION) {
144
errno = ERPCMISMATCH;
145
goto fail;
146
}
147
148
hdr.size = le32toh(hdr.size);
149
150
eb = ebuf_alloc(hdr.size);
151
if (eb == NULL)
152
goto fail;
153
if (ebuf_add_tail(eb, NULL, hdr.size) == -1)
154
goto fail;
155
hptr = ebuf_data(eb, NULL);
156
PJDLOG_ASSERT(hptr != NULL);
157
if (proto_recv(conn, hptr, hdr.size) == -1)
158
goto fail;
159
nv = nv_ntoh(eb);
160
if (nv == NULL)
161
goto fail;
162
163
*nvp = nv;
164
return (0);
165
fail:
166
if (eb != NULL)
167
ebuf_free(eb);
168
return (-1);
169
}
170
171
int
172
hast_proto_recv_data(const struct hast_resource *res, struct proto_conn *conn,
173
struct nv *nv, void *data, size_t size)
174
{
175
unsigned int ii;
176
bool freedata;
177
size_t dsize;
178
void *dptr;
179
int ret;
180
181
PJDLOG_ASSERT(data != NULL);
182
PJDLOG_ASSERT(size > 0);
183
184
ret = -1;
185
freedata = false;
186
dptr = data;
187
188
dsize = nv_get_uint32(nv, "size");
189
if (dsize > size) {
190
errno = EINVAL;
191
goto end;
192
} else if (dsize == 0) {
193
(void)nv_set_error(nv, 0);
194
} else {
195
if (proto_recv(conn, data, dsize) == -1)
196
goto end;
197
for (ii = sizeof(pipeline) / sizeof(pipeline[0]); ii > 0;
198
ii--) {
199
ret = pipeline[ii - 1].hps_recv(res, nv, &dptr,
200
&dsize, &freedata);
201
if (ret == -1)
202
goto end;
203
}
204
ret = -1;
205
if (dsize > size) {
206
errno = EINVAL;
207
goto end;
208
}
209
if (dptr != data)
210
bcopy(dptr, data, dsize);
211
}
212
213
ret = 0;
214
end:
215
if (freedata)
216
free(dptr);
217
return (ret);
218
}
219
220