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/request.h"
7 : :
8 : : #include <errno.h>
9 : : #include <stddef.h>
10 : : #include <stdio.h>
11 : : #include <stdlib.h>
12 : : #include <string.h>
13 : :
14 : : #include "bpfilter/dynbuf.h"
15 : : #include "bpfilter/helper.h"
16 : : #include "bpfilter/pack.h"
17 : :
18 : : /**
19 : : * @struct bf_request
20 : : *
21 : : * Generic request format sent by the client to the daemon.
22 : : *
23 : : * @var bf_request::cmd
24 : : * Command.
25 : : * @var bf_request::data_len
26 : : * Length of the client-specific data.
27 : : * @var bf_request::data
28 : : * Client-specific data.
29 : : */
30 : : struct bf_request
31 : : {
32 : : enum bf_request_cmd cmd;
33 : :
34 : : /** Namespaces the request is coming from. This field will be automatically
35 : : * populated by the daemon when receiving the request. */
36 : : struct bf_ns *ns;
37 : :
38 : : /** File descriptor of the receiver socket. This field is automatically
39 : : * populated by the daemon when receiving the request. The request doesn't
40 : : * own the file descriptor. */
41 : : int fd;
42 : :
43 : : size_t data_len;
44 : :
45 : : /// @todo Return a user-readable error message if the request fails.
46 : : char data[];
47 : : };
48 : :
49 : 375 : int bf_request_new(struct bf_request **request, enum bf_request_cmd cmd,
50 : : const void *data, size_t data_len)
51 : : {
52 : 375 : _free_bf_request_ struct bf_request *_request = NULL;
53 : :
54 : : assert(request);
55 : : assert(!(!!data ^ !!data_len));
56 : :
57 : 375 : _request = calloc(1, sizeof(*_request) + data_len);
58 [ + - ]: 375 : if (!_request)
59 : : return -ENOMEM;
60 : :
61 [ + + ]: 375 : if (data) {
62 : 214 : memcpy(_request->data, data, data_len);
63 : 214 : _request->data_len = data_len;
64 : : }
65 : :
66 : 375 : _request->cmd = cmd;
67 : :
68 : 375 : *request = TAKE_PTR(_request);
69 : :
70 : 375 : return 0;
71 : : }
72 : :
73 : 231 : int bf_request_new_from_dynbuf(struct bf_request **request,
74 : : struct bf_dynbuf *dynbuf)
75 : : {
76 : : struct bf_request *tmpreq;
77 : :
78 : : assert(request);
79 : : assert(dynbuf);
80 : :
81 [ + + ]: 231 : if (dynbuf->len < sizeof(*tmpreq))
82 : : return -EINVAL;
83 : :
84 : 230 : tmpreq = dynbuf->data;
85 [ - + ]: 230 : if (bf_request_size(tmpreq) != dynbuf->len)
86 : : return -EINVAL;
87 : :
88 : 230 : *request = bf_dynbuf_take(dynbuf);
89 : :
90 : 230 : return 0;
91 : : }
92 : :
93 : 205 : int bf_request_new_from_pack(struct bf_request **request,
94 : : enum bf_request_cmd cmd, bf_wpack_t *pack)
95 : : {
96 : : const void *data;
97 : : size_t data_len;
98 : : int r;
99 : :
100 : : assert(request);
101 : : assert(pack);
102 : :
103 [ + - ]: 205 : if (!bf_wpack_is_valid(pack))
104 : : return -EINVAL;
105 : :
106 : 205 : r = bf_wpack_get_data(pack, &data, &data_len);
107 [ + - ]: 205 : if (r)
108 : : return r;
109 : :
110 : 205 : return bf_request_new(request, cmd, data, data_len);
111 : : }
112 : :
113 : 1 : int bf_request_copy(struct bf_request **dest, const struct bf_request *src)
114 : : {
115 : 1 : _free_bf_request_ struct bf_request *_request = NULL;
116 : :
117 : : assert(dest);
118 : : assert(src);
119 : :
120 : 1 : _request = bf_memdup(src, bf_request_size(src));
121 [ + - ]: 1 : if (!_request)
122 : : return -ENOMEM;
123 : :
124 : 1 : *dest = TAKE_PTR(_request);
125 : :
126 : 1 : return 0;
127 : : }
128 : :
129 : 1014 : void bf_request_free(struct bf_request **request)
130 : : {
131 : 1014 : free(*request);
132 : 1014 : *request = NULL;
133 : 1014 : }
134 : :
135 : 911 : enum bf_request_cmd bf_request_cmd(const struct bf_request *request)
136 : : {
137 : : assert(request);
138 : 911 : return request->cmd;
139 : : }
140 : :
141 : 111 : struct bf_ns *bf_request_ns(const struct bf_request *request)
142 : : {
143 : : assert(request);
144 : 111 : return request->ns;
145 : : }
146 : :
147 : 2 : int bf_request_fd(const struct bf_request *request)
148 : : {
149 : : assert(request);
150 : 2 : return request->fd;
151 : : }
152 : :
153 : 206 : const void *bf_request_data(const struct bf_request *request)
154 : : {
155 : : assert(request);
156 : 206 : return request->data;
157 : : }
158 : :
159 : 204 : size_t bf_request_data_len(const struct bf_request *request)
160 : : {
161 : : assert(request);
162 : 204 : return request->data_len;
163 : : }
164 : :
165 : 468 : size_t bf_request_size(const struct bf_request *request)
166 : : {
167 : : assert(request);
168 : :
169 : 468 : return sizeof(struct bf_request) + request->data_len;
170 : : }
171 : :
172 : 227 : void bf_request_set_ns(struct bf_request *request, struct bf_ns *ns)
173 : : {
174 : : assert(request);
175 : 227 : request->ns = ns;
176 : 227 : }
177 : :
178 : 227 : void bf_request_set_fd(struct bf_request *request, int fd)
179 : : {
180 : : assert(request);
181 : 227 : request->fd = fd;
182 : 227 : }
183 : :
184 : 244 : const char *bf_request_cmd_to_str(enum bf_request_cmd cmd)
185 : : {
186 : : static const char *cmd_strs[] = {
187 : : [BF_REQ_RULESET_FLUSH] = "BF_REQ_RULESET_FLUSH",
188 : : [BF_REQ_RULESET_GET] = "BF_REQ_RULESET_GET",
189 : : [BF_REQ_RULESET_SET] = "BF_REQ_RULESET_SET",
190 : : [BF_REQ_CHAIN_SET] = "BF_REQ_CHAIN_SET",
191 : : [BF_REQ_CHAIN_GET] = "BF_REQ_CHAIN_GET",
192 : : [BF_REQ_CHAIN_LOAD] = "BF_REQ_CHAIN_LOAD",
193 : : [BF_REQ_CHAIN_ATTACH] = "BF_REQ_CHAIN_ATTACH",
194 : : [BF_REQ_CHAIN_UPDATE] = "BF_REQ_CHAIN_UPDATE",
195 : : [BF_REQ_CHAIN_PROG_FD] = "BF_REQ_CHAIN_PROG_FD",
196 : : [BF_REQ_CHAIN_LOGS_FD] = "BF_REQ_CHAIN_LOGS_FD",
197 : : [BF_REQ_CHAIN_FLUSH] = "BF_REQ_CHAIN_FLUSH",
198 : : [BF_REQ_CHAIN_UPDATE_SET] = "BF_REQ_CHAIN_UPDATE_SET",
199 : : [BF_REQ_COUNTERS_SET] = "BF_REQ_COUNTERS_SET",
200 : : [BF_REQ_COUNTERS_GET] = "BF_REQ_COUNTERS_GET",
201 : : [BF_REQ_CUSTOM] = "BF_REQ_CUSTOM",
202 : : };
203 : :
204 : : static_assert_enum_mapping(cmd_strs, _BF_REQ_CMD_MAX);
205 : :
206 : 244 : return cmd_strs[cmd];
207 : : }
|