Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include "bpfilter/response.h"
7 : :
8 : : #include <errno.h>
9 : : #include <stddef.h>
10 : : #include <stdio.h>
11 : : #include <stdlib.h>
12 : :
13 : : #include "bpfilter/dynbuf.h"
14 : : #include "bpfilter/helper.h"
15 : :
16 : : /**
17 : : * @brief Response message sent from the daemon to the client.
18 : : */
19 : : struct bf_response
20 : : {
21 : : /** Response status: 0 on success, or a negative error value on failure. */
22 : : int status;
23 : :
24 : : /** Number of bytes stored in `data`. */
25 : : size_t data_len;
26 : :
27 : : /** Data carried by the response. */
28 : : char data[];
29 : : };
30 : :
31 : 2 : int bf_response_new_raw(struct bf_response **response, size_t data_len)
32 : : {
33 : : bf_assert(response);
34 : :
35 : 2 : *response = malloc(sizeof(**response) + data_len);
36 [ + - ]: 2 : if (!*response)
37 : : return -ENOMEM;
38 : :
39 : 2 : (*response)->status = 0;
40 : :
41 : 2 : return 0;
42 : : }
43 : :
44 : 104 : int bf_response_new_success(struct bf_response **response, const char *data,
45 : : size_t data_len)
46 : : {
47 : 104 : _free_bf_response_ struct bf_response *_response = NULL;
48 : :
49 : : bf_assert(response);
50 : : bf_assert(!(!!data ^ !!data_len));
51 : :
52 : 104 : _response = calloc(1, sizeof(*_response) + data_len);
53 [ + - ]: 104 : if (!_response)
54 : : return -ENOMEM;
55 : :
56 : 104 : _response->status = 0;
57 : 104 : _response->data_len = data_len;
58 : 104 : bf_memcpy(_response->data, data, data_len);
59 : :
60 : 104 : *response = TAKE_PTR(_response);
61 : :
62 : 104 : return 0;
63 : : }
64 : :
65 : 106 : int bf_response_new_from_dynbuf(struct bf_response **response,
66 : : struct bf_dynbuf *dynbuf)
67 : : {
68 : : struct bf_response *tmpres;
69 : :
70 : : bf_assert(response);
71 : : bf_assert(dynbuf);
72 : :
73 [ + + ]: 106 : if (dynbuf->len < sizeof(*tmpres))
74 : : return -EINVAL;
75 : :
76 : 105 : tmpres = dynbuf->data;
77 [ - + ]: 105 : if (bf_response_size(tmpres) != dynbuf->len)
78 : : return -EINVAL;
79 : :
80 : 105 : *response = bf_dynbuf_take(dynbuf);
81 : :
82 : 105 : return 0;
83 : : }
84 : :
85 : 13 : int bf_response_new_from_pack(struct bf_response **response, bf_wpack_t *pack)
86 : : {
87 : : const void *data;
88 : : size_t data_len;
89 : : int r;
90 : :
91 : : bf_assert(response);
92 : : bf_assert(pack);
93 : :
94 [ + - ]: 13 : if (!bf_wpack_is_valid(pack))
95 : : return -EINVAL;
96 : :
97 : 13 : r = bf_wpack_get_data(pack, &data, &data_len);
98 [ + - ]: 13 : if (r)
99 : : return r;
100 : :
101 : 13 : return bf_response_new_success(response, data, data_len);
102 : : }
103 : :
104 : 11 : int bf_response_new_failure(struct bf_response **response, int error)
105 : : {
106 : 11 : _free_bf_response_ struct bf_response *_response = NULL;
107 : :
108 : : bf_assert(response);
109 : :
110 : 11 : _response = calloc(1, sizeof(*_response));
111 [ + - ]: 11 : if (!_response)
112 : : return -ENOMEM;
113 : :
114 : 11 : _response->status = error;
115 : :
116 : 11 : *response = TAKE_PTR(_response);
117 : :
118 : 11 : return 0;
119 : : }
120 : :
121 : 386 : void bf_response_free(struct bf_response **response)
122 : : {
123 : 386 : free(*response);
124 : 386 : *response = NULL;
125 : 386 : }
126 : :
127 : 2 : int bf_response_copy(struct bf_response **dest, const struct bf_response *src)
128 : : {
129 : 2 : _free_bf_response_ struct bf_response *_response = NULL;
130 : :
131 : : bf_assert(dest);
132 : : bf_assert(src);
133 : :
134 : 2 : _response = bf_memdup(src, bf_response_size(src));
135 [ + - ]: 2 : if (!_response)
136 : : return -ENOMEM;
137 : :
138 : 2 : *dest = TAKE_PTR(_response);
139 : :
140 : 2 : return 0;
141 : : }
142 : :
143 : 114 : int bf_response_status(const struct bf_response *response)
144 : : {
145 : : bf_assert(response);
146 : :
147 : 114 : return response->status;
148 : : }
149 : :
150 : 23 : const void *bf_response_data(const struct bf_response *response)
151 : : {
152 : : bf_assert(response);
153 : :
154 : 23 : return response->data;
155 : : }
156 : :
157 : 23 : size_t bf_response_data_len(const struct bf_response *response)
158 : : {
159 : : bf_assert(response);
160 : :
161 : 23 : return response->data_len;
162 : : }
163 : :
164 : 219 : size_t bf_response_size(const struct bf_response *response)
165 : : {
166 : : bf_assert(response);
167 : :
168 : 219 : return sizeof(*response) + response->data_len;
169 : : }
|