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 <linux/netfilter/x_tables.h>
7 : : #include <linux/netfilter_ipv4/ip_tables.h>
8 : :
9 : : #include <errno.h>
10 : : #include <stddef.h>
11 : : #include <stdio.h>
12 : : #include <string.h>
13 : :
14 : : #include "bpfilter/front.h"
15 : : #include "bpfilter/helper.h"
16 : : #include "bpfilter/io.h"
17 : : #include "bpfilter/logger.h"
18 : : #include "bpfilter/request.h"
19 : : #include "bpfilter/response.h"
20 : :
21 : : /**
22 : : * Get size of an ipt_get_entries structure.
23 : : *
24 : : * @param ipt_get_entries_ptr Pointer to a valid ipt_get_entries structure.
25 : : * @return Size of the structure, including variable length entries field.
26 : : */
27 : : #define bf_ipt_get_entries_size(ipt_get_entries_ptr) \
28 : : (sizeof(struct ipt_get_entries) + (ipt_get_entries_ptr)->size)
29 : :
30 : : /**
31 : : * Get size of an xt_counters_info structure.
32 : : *
33 : : * @param xt_counters_info_ptr Pointer to a valid xt_counters_info structure.
34 : : * @return Size of the structure, including variable length counters field.
35 : : */
36 : : #define bf_xt_counters_info_size(xt_counters_info_ptr) \
37 : : (sizeof(struct xt_counters_info) + \
38 : : ((xt_counters_info_ptr)->num_counters * sizeof(struct xt_counters)))
39 : : /**
40 : : * Get size of an ipt_replace structure.
41 : : *
42 : : * @param ipt_replace_ptr Pointer to a valid ipt_replace structure.
43 : : * @return Size of the structure, including variable length entries field.
44 : : */
45 : : #define bf_ipt_replace_size(ipt_replace_ptr) \
46 : : (sizeof(struct ipt_replace) + (ipt_replace_ptr)->size)
47 : :
48 : 1 : int bf_ipt_replace(struct ipt_replace *ipt_replace)
49 : : {
50 : 1 : _cleanup_close_ int fd = -1;
51 : 1 : _free_bf_request_ struct bf_request *request = NULL;
52 : 1 : _free_bf_response_ struct bf_response *response = NULL;
53 : : int r;
54 : :
55 : : bf_assert(ipt_replace);
56 : :
57 : 1 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_RULESET_SET, ipt_replace,
58 : 1 : bf_ipt_replace_size(ipt_replace));
59 [ + - ]: 1 : if (r < 0)
60 : : return r;
61 : :
62 : 1 : fd = bf_connect_to_daemon();
63 [ + - ]: 1 : if (fd < 0)
64 [ + - ]: 1 : return bf_err_r(fd, "failed to connect to the daemon");
65 : :
66 : 0 : r = bf_send(fd, request, &response, NULL);
67 [ # # ]: 0 : if (r < 0)
68 : : return r;
69 : :
70 [ # # ]: 0 : if (bf_response_status(response) == 0) {
71 [ # # ]: 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
72 [ # # ]: 0 : return bf_err_r(
73 : : EINVAL, "bpfilter: response size is %lu, expected %lu",
74 : : bf_response_data_len(response), bf_request_data_len(request));
75 : : }
76 : :
77 : 0 : memcpy(ipt_replace, bf_response_data(response),
78 : : bf_response_data_len(response));
79 : : }
80 : :
81 : 0 : return bf_response_status(response);
82 : : }
83 : :
84 : 1 : int bf_ipt_add_counters(struct xt_counters_info *counters)
85 : : {
86 : 1 : _cleanup_close_ int fd = -1;
87 : 1 : _free_bf_request_ struct bf_request *request = NULL;
88 : 1 : _free_bf_response_ struct bf_response *response = NULL;
89 : : int r;
90 : :
91 : : bf_assert(counters);
92 : :
93 : 1 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_COUNTERS_SET, counters,
94 : 1 : bf_xt_counters_info_size(counters));
95 [ + - ]: 1 : if (r < 0)
96 : : return r;
97 : :
98 : 1 : fd = bf_connect_to_daemon();
99 [ + - ]: 1 : if (fd < 0)
100 [ + - ]: 1 : return bf_err_r(fd, "failed to connect to the daemon");
101 : :
102 : 0 : r = bf_send(fd, request, &response, NULL);
103 [ # # ]: 0 : if (r < 0)
104 : : return r;
105 : :
106 [ # # ]: 0 : if (bf_response_status(response) == 0) {
107 [ # # ]: 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
108 [ # # ]: 0 : return bf_err_r(
109 : : EINVAL, "bpfilter: response size is %lu, expected %lu",
110 : : bf_response_data_len(response), bf_request_data_len(request));
111 : : }
112 : :
113 : 0 : memcpy(counters, bf_response_data(response),
114 : : bf_response_data_len(response));
115 : : }
116 : :
117 : 0 : return bf_response_status(response);
118 : : }
119 : :
120 : 1 : int bf_ipt_get_info(struct ipt_getinfo *info)
121 : : {
122 : 1 : _cleanup_close_ int fd = -1;
123 : 1 : _free_bf_request_ struct bf_request *request = NULL;
124 : 1 : _free_bf_response_ struct bf_response *response = NULL;
125 : : int r;
126 : :
127 : : bf_assert(info);
128 : :
129 : 1 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_CUSTOM, info,
130 : : sizeof(*info));
131 [ + - ]: 1 : if (r < 0)
132 : : return r;
133 : :
134 : 1 : bf_request_set_ipt_cmd(request, IPT_SO_GET_INFO);
135 : :
136 : 1 : fd = bf_connect_to_daemon();
137 [ + - ]: 1 : if (fd < 0)
138 [ + - ]: 1 : return bf_err_r(fd, "failed to connect to the daemon");
139 : :
140 : 0 : r = bf_send(fd, request, &response, NULL);
141 [ # # ]: 0 : if (r < 0)
142 : : return r;
143 : :
144 [ # # ]: 0 : if (bf_response_status(response) == 0) {
145 [ # # ]: 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
146 [ # # ]: 0 : return bf_err_r(
147 : : EINVAL, "bpfilter: response size is %lu, expected %lu",
148 : : bf_response_data_len(response), bf_request_data_len(request));
149 : : }
150 : :
151 : 0 : memcpy(info, bf_response_data(response),
152 : : bf_response_data_len(response));
153 : : }
154 : :
155 : 0 : return bf_response_status(response);
156 : : }
157 : :
158 : 1 : int bf_ipt_get_entries(struct ipt_get_entries *entries)
159 : : {
160 : 1 : _cleanup_close_ int fd = -1;
161 : 1 : _free_bf_request_ struct bf_request *request = NULL;
162 : 1 : _free_bf_response_ struct bf_response *response = NULL;
163 : : int r;
164 : :
165 : : bf_assert(entries);
166 : :
167 : 1 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_CUSTOM, entries,
168 : 1 : bf_ipt_get_entries_size(entries));
169 [ + - ]: 1 : if (r < 0)
170 : : return r;
171 : :
172 : 1 : bf_request_set_ipt_cmd(request, IPT_SO_GET_ENTRIES);
173 : :
174 : 1 : fd = bf_connect_to_daemon();
175 [ + - ]: 1 : if (fd < 0)
176 [ + - ]: 1 : return bf_err_r(fd, "failed to connect to the daemon");
177 : :
178 : 0 : r = bf_send(fd, request, &response, NULL);
179 [ # # ]: 0 : if (r < 0)
180 : : return r;
181 : :
182 [ # # ]: 0 : if (bf_response_status(response) == 0) {
183 [ # # ]: 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
184 [ # # ]: 0 : return bf_err_r(
185 : : EINVAL, "bpfilter: response size is %lu, expected %lu",
186 : : bf_response_data_len(response), bf_request_data_len(request));
187 : : }
188 : :
189 : 0 : memcpy(entries, bf_response_data(response),
190 : : bf_response_data_len(response));
191 : : }
192 : :
193 : 0 : return bf_response_status(response);
194 : : }
|