1 /*
2  * Copyright 2009 VMware, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /*
26  * This file holds the function implementation for one of the rbug extensions.
27  * Prototypes and declerations of functions and structs is in the same folder
28  * in the header file matching this file's name.
29  *
30  * The functions starting rbug_send_* encodes a call to the write format and
31  * sends that to the supplied connection, while functions starting with
32  * rbug_demarshal_* demarshal data in the wire protocol.
33  *
34  * Functions ending with _reply are replies to requests.
35  */
36 
37 #include "rbug_internal.h"
38 #include "rbug_core.h"
39 
rbug_send_noop(struct rbug_connection * __con,uint32_t * __serial)40 int rbug_send_noop(struct rbug_connection *__con,
41                    uint32_t *__serial)
42 {
43 	uint32_t __len = 0;
44 	uint32_t __pos = 0;
45 	uint8_t *__data = NULL;
46 	int __ret = 0;
47 
48 	LEN(8); /* header */
49 
50 	/* align */
51 	PAD(__len, 8);
52 
53 	__data = (uint8_t*)MALLOC(__len);
54 	if (!__data)
55 		return -ENOMEM;
56 
57 	WRITE(4, int32_t, ((int32_t)RBUG_OP_NOOP));
58 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
59 
60 	/* final pad */
61 	PAD(__pos, 8);
62 
63 	if (__pos != __len) {
64 		__ret = -EINVAL;
65 	} else {
66 		rbug_connection_send_start(__con, RBUG_OP_NOOP, __len);
67 		rbug_connection_write(__con, __data, __len);
68 		__ret = rbug_connection_send_finish(__con, __serial);
69 	}
70 
71 	FREE(__data);
72 	return __ret;
73 }
74 
rbug_send_ping(struct rbug_connection * __con,uint32_t * __serial)75 int rbug_send_ping(struct rbug_connection *__con,
76                    uint32_t *__serial)
77 {
78 	uint32_t __len = 0;
79 	uint32_t __pos = 0;
80 	uint8_t *__data = NULL;
81 	int __ret = 0;
82 
83 	LEN(8); /* header */
84 
85 	/* align */
86 	PAD(__len, 8);
87 
88 	__data = (uint8_t*)MALLOC(__len);
89 	if (!__data)
90 		return -ENOMEM;
91 
92 	WRITE(4, int32_t, ((int32_t)RBUG_OP_PING));
93 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
94 
95 	/* final pad */
96 	PAD(__pos, 8);
97 
98 	if (__pos != __len) {
99 		__ret = -EINVAL;
100 	} else {
101 		rbug_connection_send_start(__con, RBUG_OP_PING, __len);
102 		rbug_connection_write(__con, __data, __len);
103 		__ret = rbug_connection_send_finish(__con, __serial);
104 	}
105 
106 	FREE(__data);
107 	return __ret;
108 }
109 
rbug_send_error(struct rbug_connection * __con,uint32_t error,uint32_t * __serial)110 int rbug_send_error(struct rbug_connection *__con,
111                     uint32_t error,
112                     uint32_t *__serial)
113 {
114 	uint32_t __len = 0;
115 	uint32_t __pos = 0;
116 	uint8_t *__data = NULL;
117 	int __ret = 0;
118 
119 	LEN(8); /* header */
120 	LEN(4); /* error */
121 
122 	/* align */
123 	PAD(__len, 8);
124 
125 	__data = (uint8_t*)MALLOC(__len);
126 	if (!__data)
127 		return -ENOMEM;
128 
129 	WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR));
130 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
131 	WRITE(4, uint32_t, error); /* error */
132 
133 	/* final pad */
134 	PAD(__pos, 8);
135 
136 	if (__pos != __len) {
137 		__ret = -EINVAL;
138 	} else {
139 		rbug_connection_send_start(__con, RBUG_OP_ERROR, __len);
140 		rbug_connection_write(__con, __data, __len);
141 		__ret = rbug_connection_send_finish(__con, __serial);
142 	}
143 
144 	FREE(__data);
145 	return __ret;
146 }
147 
rbug_send_ping_reply(struct rbug_connection * __con,uint32_t serial,uint32_t * __serial)148 int rbug_send_ping_reply(struct rbug_connection *__con,
149                          uint32_t serial,
150                          uint32_t *__serial)
151 {
152 	uint32_t __len = 0;
153 	uint32_t __pos = 0;
154 	uint8_t *__data = NULL;
155 	int __ret = 0;
156 
157 	LEN(8); /* header */
158 	LEN(4); /* serial */
159 
160 	/* align */
161 	PAD(__len, 8);
162 
163 	__data = (uint8_t*)MALLOC(__len);
164 	if (!__data)
165 		return -ENOMEM;
166 
167 	WRITE(4, int32_t, ((int32_t)RBUG_OP_PING_REPLY));
168 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
169 	WRITE(4, uint32_t, serial); /* serial */
170 
171 	/* final pad */
172 	PAD(__pos, 8);
173 
174 	if (__pos != __len) {
175 		__ret = -EINVAL;
176 	} else {
177 		rbug_connection_send_start(__con, RBUG_OP_PING_REPLY, __len);
178 		rbug_connection_write(__con, __data, __len);
179 		__ret = rbug_connection_send_finish(__con, __serial);
180 	}
181 
182 	FREE(__data);
183 	return __ret;
184 }
185 
rbug_send_error_reply(struct rbug_connection * __con,uint32_t serial,uint32_t error,uint32_t * __serial)186 int rbug_send_error_reply(struct rbug_connection *__con,
187                           uint32_t serial,
188                           uint32_t error,
189                           uint32_t *__serial)
190 {
191 	uint32_t __len = 0;
192 	uint32_t __pos = 0;
193 	uint8_t *__data = NULL;
194 	int __ret = 0;
195 
196 	LEN(8); /* header */
197 	LEN(4); /* serial */
198 	LEN(4); /* error */
199 
200 	/* align */
201 	PAD(__len, 8);
202 
203 	__data = (uint8_t*)MALLOC(__len);
204 	if (!__data)
205 		return -ENOMEM;
206 
207 	WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR_REPLY));
208 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
209 	WRITE(4, uint32_t, serial); /* serial */
210 	WRITE(4, uint32_t, error); /* error */
211 
212 	/* final pad */
213 	PAD(__pos, 8);
214 
215 	if (__pos != __len) {
216 		__ret = -EINVAL;
217 	} else {
218 		rbug_connection_send_start(__con, RBUG_OP_ERROR_REPLY, __len);
219 		rbug_connection_write(__con, __data, __len);
220 		__ret = rbug_connection_send_finish(__con, __serial);
221 	}
222 
223 	FREE(__data);
224 	return __ret;
225 }
226 
rbug_demarshal_noop(struct rbug_proto_header * header)227 struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header)
228 {
229 	struct rbug_proto_noop *ret;
230 
231 	if (!header)
232 		return NULL;
233 	if (header->opcode != (int32_t)RBUG_OP_NOOP)
234 		return NULL;
235 
236 	ret = MALLOC(sizeof(*ret));
237 	if (!ret)
238 		return NULL;
239 
240 	ret->header.__message = header;
241 	ret->header.opcode = header->opcode;
242 
243 	return ret;
244 }
245 
rbug_demarshal_ping(struct rbug_proto_header * header)246 struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header)
247 {
248 	struct rbug_proto_ping *ret;
249 
250 	if (!header)
251 		return NULL;
252 	if (header->opcode != (int32_t)RBUG_OP_PING)
253 		return NULL;
254 
255 	ret = MALLOC(sizeof(*ret));
256 	if (!ret)
257 		return NULL;
258 
259 	ret->header.__message = header;
260 	ret->header.opcode = header->opcode;
261 
262 	return ret;
263 }
264 
rbug_demarshal_error(struct rbug_proto_header * header)265 struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header)
266 {
267 	uint32_t len = 0;
268 	uint32_t pos = 0;
269 	uint8_t *data =  NULL;
270 	struct rbug_proto_error *ret;
271 
272 	if (!header)
273 		return NULL;
274 	if (header->opcode != (int32_t)RBUG_OP_ERROR)
275 		return NULL;
276 
277 	pos = 0;
278 	len = header->length * 4;
279 	data = (uint8_t*)&header[1];
280 	ret = MALLOC(sizeof(*ret));
281 	if (!ret)
282 		return NULL;
283 
284 	ret->header.__message = header;
285 	ret->header.opcode = header->opcode;
286 
287 	READ(4, uint32_t, error); /* error */
288 
289 	return ret;
290 }
291 
rbug_demarshal_ping_reply(struct rbug_proto_header * header)292 struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header)
293 {
294 	uint32_t len = 0;
295 	uint32_t pos = 0;
296 	uint8_t *data =  NULL;
297 	struct rbug_proto_ping_reply *ret;
298 
299 	if (!header)
300 		return NULL;
301 	if (header->opcode != (int32_t)RBUG_OP_PING_REPLY)
302 		return NULL;
303 
304 	pos = 0;
305 	len = header->length * 4;
306 	data = (uint8_t*)&header[1];
307 	ret = MALLOC(sizeof(*ret));
308 	if (!ret)
309 		return NULL;
310 
311 	ret->header.__message = header;
312 	ret->header.opcode = header->opcode;
313 
314 	READ(4, uint32_t, serial); /* serial */
315 
316 	return ret;
317 }
318 
rbug_demarshal_error_reply(struct rbug_proto_header * header)319 struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header)
320 {
321 	uint32_t len = 0;
322 	uint32_t pos = 0;
323 	uint8_t *data =  NULL;
324 	struct rbug_proto_error_reply *ret;
325 
326 	if (!header)
327 		return NULL;
328 	if (header->opcode != (int32_t)RBUG_OP_ERROR_REPLY)
329 		return NULL;
330 
331 	pos = 0;
332 	len = header->length * 4;
333 	data = (uint8_t*)&header[1];
334 	ret = MALLOC(sizeof(*ret));
335 	if (!ret)
336 		return NULL;
337 
338 	ret->header.__message = header;
339 	ret->header.opcode = header->opcode;
340 
341 	READ(4, uint32_t, serial); /* serial */
342 	READ(4, uint32_t, error); /* error */
343 
344 	return ret;
345 }
346