2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "stc-manager-gdbus.h"
18 #include "helper-iptables.h"
20 #define STC_IPTABLES_DBUS_SERVICE "net.stc.iptables"
21 #define STC_IPTABLES_DBUS_RULE_INTERFACE STC_IPTABLES_DBUS_SERVICE ".rule"
22 #define STC_IPTABLES_DBUS_CHAIN_INTERFACE STC_IPTABLES_DBUS_SERVICE ".chain"
23 #define STC_IPTABLES_DBUS_RULE_PATH "/net/stc/iptables/rule"
24 #define STC_IPTABLES_DBUS_CHAIN_PATH "/net/stc/iptables/chain"
25 #define STC_IPTABLES_DBUS_METHOD_IPT_ADD_CHAIN "IptAddChain"
26 #define STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_CHAIN "IptRemoveChain"
27 #define STC_IPTABLES_DBUS_METHOD_IPT_FLUSH_CHAIN "IptFlushChain"
28 #define STC_IPTABLES_DBUS_METHOD_IP6T_ADD_CHAIN "Ip6tAddChain"
29 #define STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_CHAIN "Ip6tRemoveChain"
30 #define STC_IPTABLES_DBUS_METHOD_IP6T_FLUSH_CHAIN "Ip6tFlushChain"
31 #define STC_IPTABLES_DBUS_METHOD_IPT_ADD_RULE "IptAddRule"
32 #define STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE "IptRemoveRule"
33 #define STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE "Ip6tAddRule"
34 #define STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE "Ip6tRemoveRule"
36 #define RULE_CHAIN "chain"
37 #define RULE_DIRECTION "direction"
38 #define RULE_IFNAME "ifname"
39 #define RULE_CGROUP "cgroup"
40 #define RULE_NFACCT "nfacct"
41 #define RULE_TARGET "target"
42 #define RULE_PROTOCOL "protocol"
43 #define RULE_SIPTYPE "s_ip_type"
44 #define RULE_SIP1 "s_ip1"
45 #define RULE_SIP2 "s_ip2"
46 #define RULE_DIPTYPE "d_ip_type"
47 #define RULE_DIP1 "d_ip1"
48 #define RULE_DIP2 "d_ip2"
50 static void __add_rule_info_to_builder(GVariantBuilder *builder,
51 iptables_rule_s *rule)
53 if (builder == NULL || rule == NULL)
54 return; //LCOV_EXCL_LINE
56 g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
57 g_variant_new_string(rule->chain));
59 g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
60 g_variant_new_uint16(rule->direction));
63 g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
64 g_variant_new_string(rule->ifname));
66 if (rule->classid > 0)
67 g_variant_builder_add(builder, "{sv}", RULE_CGROUP,
68 g_variant_new_uint32(rule->classid));
70 if (rule->nfacct_name)
71 g_variant_builder_add(builder, "{sv}", RULE_NFACCT,
72 g_variant_new_string(rule->nfacct_name));
75 g_variant_builder_add(builder, "{sv}", RULE_TARGET,
76 g_variant_new_string(rule->target));
78 g_variant_builder_add(builder, "{sv}", RULE_SIPTYPE,
79 g_variant_new_uint16(rule->s_iprange_type));
81 g_variant_builder_add(builder, "{sv}", RULE_DIPTYPE,
82 g_variant_new_uint16(rule->d_iprange_type));
84 if (rule->s_ip1.s_addr)
85 g_variant_builder_add(builder, "{sv}", RULE_SIP1,
86 g_variant_new_uint32(rule->s_ip1.s_addr));
88 if (rule->s_ip2.s_addr)
89 g_variant_builder_add(builder, "{sv}", RULE_SIP2,
90 g_variant_new_uint32(rule->s_ip2.s_addr));
92 if (rule->d_ip1.s_addr)
93 g_variant_builder_add(builder, "{sv}", RULE_DIP1,
94 g_variant_new_uint32(rule->d_ip1.s_addr));
96 if (rule->d_ip2.s_addr)
97 g_variant_builder_add(builder, "{sv}", RULE_DIP2,
98 g_variant_new_uint32(rule->d_ip2.s_addr));
101 static int __iptables_rule_add(GDBusConnection *connection,
102 iptables_rule_s *rule)
105 GVariantBuilder *builder = NULL;
106 GVariant *params = NULL;
107 GVariant *message = NULL;
109 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
110 __add_rule_info_to_builder(builder, rule);
111 params = g_variant_new("(a{sv})", builder);
112 g_variant_builder_unref(builder);
114 message = stc_manager_gdbus_call_sync(connection,
115 STC_IPTABLES_DBUS_SERVICE,
116 STC_IPTABLES_DBUS_RULE_PATH,
117 STC_IPTABLES_DBUS_RULE_INTERFACE,
118 STC_IPTABLES_DBUS_METHOD_IPT_ADD_RULE,
121 if (message == NULL) {
122 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
123 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
126 g_variant_get(message, "(i)", &result);
128 STC_LOGD("Successfully Add Rule [%d:%s]", result, rule->nfacct_name);
129 g_variant_unref(message);
131 return STC_ERROR_NONE;
134 static int __iptables_rule_remove(GDBusConnection *connection,
135 iptables_rule_s *rule)
138 GVariantBuilder *builder = NULL;
139 GVariant *params = NULL;
140 GVariant *message = NULL;
142 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
143 __add_rule_info_to_builder(builder, rule);
144 params = g_variant_new("(a{sv})", builder);
145 g_variant_builder_unref(builder);
147 message = stc_manager_gdbus_call_sync(connection,
148 STC_IPTABLES_DBUS_SERVICE,
149 STC_IPTABLES_DBUS_RULE_PATH,
150 STC_IPTABLES_DBUS_RULE_INTERFACE,
151 STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE,
154 if (message == NULL) {
155 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
156 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
159 g_variant_get(message, "(i)", &result);
161 STC_LOGD("Successfully Remove Rule [%d:%s]", result, rule->nfacct_name);
162 g_variant_unref(message);
164 return STC_ERROR_NONE;
167 static int __ip6tables_rule_add(GDBusConnection *connection,
168 iptables_rule_s *rule)
171 GVariantBuilder *builder = NULL;
172 GVariant *params = NULL;
173 GVariant *message = NULL;
175 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
176 __add_rule_info_to_builder(builder, rule);
177 params = g_variant_new("(a{sv})", builder);
178 g_variant_builder_unref(builder);
180 message = stc_manager_gdbus_call_sync(connection,
181 STC_IPTABLES_DBUS_SERVICE,
182 STC_IPTABLES_DBUS_RULE_PATH,
183 STC_IPTABLES_DBUS_RULE_INTERFACE,
184 STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE,
187 if (message == NULL) {
188 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
189 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
192 g_variant_get(message, "(i)", &result);
194 STC_LOGD("Successfully Add 6 Rule [%d:%s]", result, rule->nfacct_name);
195 g_variant_unref(message);
197 return STC_ERROR_NONE;
200 static int __ip6tables_rule_remove(GDBusConnection *connection,
201 iptables_rule_s *rule)
204 GVariantBuilder *builder = NULL;
205 GVariant *params = NULL;
206 GVariant *message = NULL;
208 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
209 __add_rule_info_to_builder(builder, rule);
210 params = g_variant_new("(a{sv})", builder);
211 g_variant_builder_unref(builder);
213 message = stc_manager_gdbus_call_sync(connection,
214 STC_IPTABLES_DBUS_SERVICE,
215 STC_IPTABLES_DBUS_RULE_PATH,
216 STC_IPTABLES_DBUS_RULE_INTERFACE,
217 STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE,
220 if (message == NULL) {
221 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
222 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
225 g_variant_get(message, "(i)", &result);
227 STC_LOGD("Successfully Remove 6 Rule [%d:%s]", result, rule->nfacct_name);
228 g_variant_unref(message);
230 return STC_ERROR_NONE;
233 static int __iptables_add_chain(GDBusConnection *connection,
237 GVariant *message = NULL;
239 message = stc_manager_gdbus_call_sync(connection,
240 STC_IPTABLES_DBUS_SERVICE,
241 STC_IPTABLES_DBUS_CHAIN_PATH,
242 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
243 STC_IPTABLES_DBUS_METHOD_IPT_ADD_CHAIN,
244 g_variant_new("(s)", chain));
246 if (message == NULL) {
247 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
248 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
251 g_variant_get(message, "(i)", &result);
252 STC_LOGD("Successfully added ipv4 chain [%d:%s]", result, chain);
253 g_variant_unref(message);
255 return STC_ERROR_NONE;
258 static int __ip6tables_add_chain(GDBusConnection *connection,
262 GVariant *message = NULL;
264 message = stc_manager_gdbus_call_sync(connection,
265 STC_IPTABLES_DBUS_SERVICE,
266 STC_IPTABLES_DBUS_CHAIN_PATH,
267 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
268 STC_IPTABLES_DBUS_METHOD_IP6T_ADD_CHAIN,
269 g_variant_new("(s)", chain));
271 if (message == NULL) {
272 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
273 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
276 g_variant_get(message, "(i)", &result);
277 STC_LOGD("Successfully added ipv6 chain [%d:%s]", result, chain);
278 g_variant_unref(message);
280 return STC_ERROR_NONE;
283 static int __iptables_remove_chain(GDBusConnection *connection,
287 GVariant *message = NULL;
289 message = stc_manager_gdbus_call_sync(connection,
290 STC_IPTABLES_DBUS_SERVICE,
291 STC_IPTABLES_DBUS_CHAIN_PATH,
292 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
293 STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_CHAIN,
294 g_variant_new("(s)", chain));
296 if (message == NULL) {
297 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
298 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
301 g_variant_get(message, "(i)", &result);
302 STC_LOGD("Successfully removed ipv4 chain [%d:%s]", result, chain);
303 g_variant_unref(message);
305 return STC_ERROR_NONE;
308 static int __ip6tables_remove_chain(GDBusConnection *connection,
312 GVariant *message = NULL;
314 message = stc_manager_gdbus_call_sync(connection,
315 STC_IPTABLES_DBUS_SERVICE,
316 STC_IPTABLES_DBUS_CHAIN_PATH,
317 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
318 STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_CHAIN,
319 g_variant_new("(s)", chain));
321 if (message == NULL) {
322 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
323 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
326 g_variant_get(message, "(i)", &result);
327 STC_LOGD("Successfully removed ipv6 chain [%d:%s]", result, chain);
328 g_variant_unref(message);
330 return STC_ERROR_NONE;
333 static int __iptables_flush_chain(GDBusConnection *connection,
337 GVariant *message = NULL;
339 message = stc_manager_gdbus_call_sync(connection,
340 STC_IPTABLES_DBUS_SERVICE,
341 STC_IPTABLES_DBUS_CHAIN_PATH,
342 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
343 STC_IPTABLES_DBUS_METHOD_IPT_FLUSH_CHAIN,
344 g_variant_new("(s)", chain));
346 if (message == NULL) {
347 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
348 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
351 g_variant_get(message, "(i)", &result);
352 STC_LOGD("Successfully flushed ipv4 chain [%d:%s]", result, chain);
353 g_variant_unref(message);
355 return STC_ERROR_NONE;
358 static int __ip6tables_flush_chain(GDBusConnection *connection,
362 GVariant *message = NULL;
364 message = stc_manager_gdbus_call_sync(connection,
365 STC_IPTABLES_DBUS_SERVICE,
366 STC_IPTABLES_DBUS_CHAIN_PATH,
367 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
368 STC_IPTABLES_DBUS_METHOD_IP6T_FLUSH_CHAIN,
369 g_variant_new("(s)", chain));
371 if (message == NULL) {
372 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
373 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
376 g_variant_get(message, "(i)", &result);
377 STC_LOGD("Successfully flushed ipv6 chain [%d:%s]", result, chain);
378 g_variant_unref(message);
380 return STC_ERROR_NONE;
383 static int __iptables_add_chain_jump_rule(const char *chain,
386 stc_error_e ret = STC_ERROR_NONE;
387 iptables_rule_s iptables_rule;
388 memset(&iptables_rule, 0, sizeof(iptables_rule_s));
390 iptables_rule.target = g_strdup(target);
391 iptables_rule.chain = g_strdup(chain);
393 ret = iptables_add(&iptables_rule, IP_TYPE_IPV4_IPV6);
395 g_free(iptables_rule.target);
396 g_free(iptables_rule.chain);
401 stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype)
403 stc_error_e ret = STC_ERROR_NONE;
404 stc_s *stc = stc_get_manager();
406 if (!stc || !stc->connection)
407 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
409 if (iptype == IP_TYPE_IPV4 ||
410 iptype == IP_TYPE_IPV4_IPV6) {
411 ret = __iptables_rule_add(stc->connection, rule);
412 if (ret != STC_ERROR_NONE)
413 goto done; //LCOV_EXCL_LINE
416 if (iptype == IP_TYPE_IPV6 ||
417 iptype == IP_TYPE_IPV4_IPV6)
418 ret = __ip6tables_rule_add(stc->connection, rule);
424 stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype)
426 stc_error_e ret = STC_ERROR_NONE;
427 stc_s *stc = stc_get_manager();
429 if (!stc || !stc->connection)
430 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
432 if (iptype == IP_TYPE_IPV4 ||
433 iptype == IP_TYPE_IPV4_IPV6) {
434 ret = __iptables_rule_remove(stc->connection, rule);
435 if (ret != STC_ERROR_NONE)
436 goto done; //LCOV_EXCL_LINE
439 if (iptype == IP_TYPE_IPV6 ||
440 iptype == IP_TYPE_IPV4_IPV6)
441 ret = __ip6tables_rule_remove(stc->connection, rule);
447 stc_error_e iptables_flush_chains(void)
449 stc_error_e ret = STC_ERROR_NONE;
450 stc_s *stc = stc_get_manager();
452 if (!stc || !stc->connection)
453 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
455 ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
456 if (ret != STC_ERROR_NONE)
457 goto done; //LCOV_EXCL_LINE
459 ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
460 if (ret != STC_ERROR_NONE)
461 goto done; //LCOV_EXCL_LINE
463 ret = __iptables_flush_chain(stc->connection, STC_FRWD_CHAIN);
464 if (ret != STC_ERROR_NONE)
465 goto done; //LCOV_EXCL_LINE
467 ret = __iptables_flush_chain(stc->connection, STC_TETHER_CHAIN);
468 if (ret != STC_ERROR_NONE)
469 goto done; //LCOV_EXCL_LINE
471 ret = __ip6tables_flush_chain(stc->connection, STC_IN_CHAIN);
472 if (ret != STC_ERROR_NONE)
473 goto done; //LCOV_EXCL_LINE
475 ret = __ip6tables_flush_chain(stc->connection, STC_OUT_CHAIN);
476 if (ret != STC_ERROR_NONE)
477 goto done; //LCOV_EXCL_LINE
479 ret = __ip6tables_flush_chain(stc->connection, STC_FRWD_CHAIN);
484 stc_error_e iptables_init(void)
486 __STC_LOG_FUNC_ENTER__;
488 stc_error_e ret = STC_ERROR_NONE;
489 stc_s *stc = stc_get_manager();
491 if (!stc || !stc->connection) {
492 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
493 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
496 ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
497 if (ret != STC_ERROR_NONE) {
498 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
499 goto done; //LCOV_EXCL_LINE
502 ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
503 if (ret != STC_ERROR_NONE) {
504 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
505 goto done; //LCOV_EXCL_LINE
508 ret = __iptables_add_chain(stc->connection, STC_FRWD_CHAIN);
509 if (ret != STC_ERROR_NONE) {
510 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
511 goto done; //LCOV_EXCL_LINE
514 ret = __iptables_add_chain(stc->connection, STC_TETHER_CHAIN);
515 if (ret != STC_ERROR_NONE) {
516 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
517 goto done; //LCOV_EXCL_LINE
520 ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
521 if (ret != STC_ERROR_NONE) {
522 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
523 goto done; //LCOV_EXCL_LINE
526 ret = __ip6tables_add_chain(stc->connection, STC_OUT_CHAIN);
527 if (ret != STC_ERROR_NONE) {
528 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
529 goto done; //LCOV_EXCL_LINE
532 ret = __ip6tables_add_chain(stc->connection, STC_FRWD_CHAIN);
533 if (ret != STC_ERROR_NONE) {
534 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
535 goto done; //LCOV_EXCL_LINE
538 ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
539 if (ret != STC_ERROR_NONE) {
540 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
541 goto done; //LCOV_EXCL_LINE
544 ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
545 if (ret != STC_ERROR_NONE) {
546 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
547 goto done; //LCOV_EXCL_LINE
550 ret = __iptables_add_chain_jump_rule("FORWARD", STC_FRWD_CHAIN);
551 if (ret != STC_ERROR_NONE) {
552 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
553 goto done; //LCOV_EXCL_LINE
556 ret = __iptables_add_chain_jump_rule("FORWARD", STC_TETHER_CHAIN);
557 if (ret != STC_ERROR_NONE) {
558 __STC_LOG_FUNC_EXIT__;
565 stc_error_e iptables_deinit(void)
567 __STC_LOG_FUNC_ENTER__;
569 stc_error_e ret = STC_ERROR_NONE;
570 stc_s *stc = stc_get_manager();
572 if (!stc || !stc->connection) {
573 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
574 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
577 ret = __iptables_remove_chain(stc->connection, STC_IN_CHAIN);
578 if (ret != STC_ERROR_NONE) {
579 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
580 goto done; //LCOV_EXCL_LINE
583 ret = __iptables_remove_chain(stc->connection, STC_OUT_CHAIN);
584 if (ret != STC_ERROR_NONE) {
585 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
586 goto done; //LCOV_EXCL_LINE
589 ret = __iptables_remove_chain(stc->connection, STC_TETHER_CHAIN);
590 if (ret != STC_ERROR_NONE) {
591 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
592 goto done; //LCOV_EXCL_LINE
595 ret = __iptables_remove_chain(stc->connection, STC_FRWD_CHAIN);
596 if (ret != STC_ERROR_NONE) {
597 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
598 goto done; //LCOV_EXCL_LINE
601 ret = __ip6tables_remove_chain(stc->connection, STC_IN_CHAIN);
602 if (ret != STC_ERROR_NONE) {
603 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
604 goto done; //LCOV_EXCL_LINE
607 ret = __ip6tables_remove_chain(stc->connection, STC_OUT_CHAIN);
608 if (ret != STC_ERROR_NONE) {
609 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
610 goto done; //LCOV_EXCL_LINE
613 ret = __ip6tables_remove_chain(stc->connection, STC_FRWD_CHAIN);