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/generic.h"
16 : #include "bpfilter/helper.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 0 : int bf_ipt_replace(struct ipt_replace *ipt_replace)
49 : {
50 0 : _free_bf_request_ struct bf_request *request = NULL;
51 0 : _free_bf_response_ struct bf_response *response = NULL;
52 : int r;
53 :
54 0 : bf_assert(ipt_replace);
55 :
56 0 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_RULESET_SET, ipt_replace,
57 0 : bf_ipt_replace_size(ipt_replace));
58 0 : if (r < 0)
59 : return r;
60 :
61 0 : r = bf_send(request, &response);
62 0 : if (r < 0)
63 : return r;
64 :
65 0 : if (bf_response_status(response) == 0) {
66 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
67 0 : return bf_err_r(
68 : EINVAL, "bpfilter: response size is %lu, expected %lu",
69 : bf_response_data_len(response), bf_request_data_len(request));
70 : }
71 :
72 0 : memcpy(ipt_replace, bf_response_data(response),
73 : bf_response_data_len(response));
74 : }
75 :
76 0 : return bf_response_status(response);
77 : }
78 :
79 0 : int bf_ipt_add_counters(struct xt_counters_info *counters)
80 : {
81 0 : _free_bf_request_ struct bf_request *request = NULL;
82 0 : _free_bf_response_ struct bf_response *response = NULL;
83 : int r;
84 :
85 0 : bf_assert(counters);
86 :
87 0 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_COUNTERS_SET, counters,
88 0 : bf_xt_counters_info_size(counters));
89 0 : if (r < 0)
90 : return r;
91 :
92 0 : r = bf_send(request, &response);
93 0 : if (r < 0)
94 : return r;
95 :
96 0 : if (bf_response_status(response) == 0) {
97 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
98 0 : return bf_err_r(
99 : EINVAL, "bpfilter: response size is %lu, expected %lu",
100 : bf_response_data_len(response), bf_request_data_len(request));
101 : }
102 :
103 0 : memcpy(counters, bf_response_data(response),
104 : bf_response_data_len(response));
105 : }
106 :
107 0 : return bf_response_status(response);
108 : }
109 :
110 0 : int bf_ipt_get_info(struct ipt_getinfo *info)
111 : {
112 0 : _free_bf_request_ struct bf_request *request = NULL;
113 0 : _free_bf_response_ struct bf_response *response = NULL;
114 : int r;
115 :
116 0 : bf_assert(info);
117 :
118 0 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_CUSTOM, info,
119 : sizeof(*info));
120 0 : if (r < 0)
121 : return r;
122 :
123 0 : bf_request_set_ipt_cmd(request, IPT_SO_GET_INFO);
124 :
125 0 : r = bf_send(request, &response);
126 0 : if (r < 0)
127 : return r;
128 :
129 0 : if (bf_response_status(response) == 0) {
130 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
131 0 : return bf_err_r(
132 : EINVAL, "bpfilter: response size is %lu, expected %lu",
133 : bf_response_data_len(response), bf_request_data_len(request));
134 : }
135 :
136 0 : memcpy(info, bf_response_data(response),
137 : bf_response_data_len(response));
138 : }
139 :
140 0 : return bf_response_status(response);
141 : }
142 :
143 0 : int bf_ipt_get_entries(struct ipt_get_entries *entries)
144 : {
145 0 : _free_bf_request_ struct bf_request *request = NULL;
146 0 : _free_bf_response_ struct bf_response *response = NULL;
147 : int r;
148 :
149 0 : bf_assert(entries);
150 :
151 0 : r = bf_request_new(&request, BF_FRONT_IPT, BF_REQ_CUSTOM, entries,
152 0 : bf_ipt_get_entries_size(entries));
153 0 : if (r < 0)
154 : return r;
155 :
156 0 : bf_request_set_ipt_cmd(request, IPT_SO_GET_ENTRIES);
157 :
158 0 : r = bf_send(request, &response);
159 0 : if (r < 0)
160 : return r;
161 :
162 0 : if (bf_response_status(response) == 0) {
163 0 : if (bf_response_data_len(response) != bf_request_data_len(request)) {
164 0 : return bf_err_r(
165 : EINVAL, "bpfilter: response size is %lu, expected %lu",
166 : bf_response_data_len(response), bf_request_data_len(request));
167 : }
168 :
169 0 : memcpy(entries, bf_response_data(response),
170 : bf_response_data_len(response));
171 : }
172 :
173 0 : return bf_response_status(response);
174 : }
|