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_SIPTYPE "s_ip_type"
43 #define RULE_SIP1 "s_ip1"
44 #define RULE_SIP2 "s_ip2"
45 #define RULE_DIPTYPE "d_ip_type"
46 #define RULE_DIP1 "d_ip1"
47 #define RULE_DIP2 "d_ip2"
49 static void __add_rule_info_to_builder(GVariantBuilder *builder,
50 iptables_rule_s *rule)
52 if (builder == NULL || rule == NULL)
53 return; //LCOV_EXCL_LINE
55 g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
56 g_variant_new_string(rule->chain));
58 g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
59 g_variant_new_uint16(rule->direction));
62 g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
63 g_variant_new_string(rule->ifname));
65 if (rule->classid > 0)
66 g_variant_builder_add(builder, "{sv}", RULE_CGROUP,
67 g_variant_new_uint32(rule->classid));
69 if (rule->nfacct_name)
70 g_variant_builder_add(builder, "{sv}", RULE_NFACCT,
71 g_variant_new_string(rule->nfacct_name));
74 g_variant_builder_add(builder, "{sv}", RULE_TARGET,
75 g_variant_new_string(rule->target));
77 g_variant_builder_add(builder, "{sv}", RULE_SIPTYPE,
78 g_variant_new_uint16(rule->s_iprange_type));
80 g_variant_builder_add(builder, "{sv}", RULE_DIPTYPE,
81 g_variant_new_uint16(rule->d_iprange_type));
83 if (rule->s_ip1.s_addr)
84 g_variant_builder_add(builder, "{sv}", RULE_SIP1,
85 g_variant_new_uint32(rule->s_ip1.s_addr));
87 if (rule->s_ip2.s_addr)
88 g_variant_builder_add(builder, "{sv}", RULE_SIP2,
89 g_variant_new_uint32(rule->s_ip2.s_addr));
91 if (rule->d_ip1.s_addr)
92 g_variant_builder_add(builder, "{sv}", RULE_DIP1,
93 g_variant_new_uint32(rule->d_ip1.s_addr));
95 if (rule->d_ip2.s_addr)
96 g_variant_builder_add(builder, "{sv}", RULE_DIP2,
97 g_variant_new_uint32(rule->d_ip2.s_addr));
100 static int __iptables_rule_add(GDBusConnection *connection,
101 iptables_rule_s *rule)
104 GVariantBuilder *builder = NULL;
105 GVariant *params = NULL;
106 GVariant *message = NULL;
108 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
109 __add_rule_info_to_builder(builder, rule);
110 params = g_variant_new("(a{sv})", builder);
111 g_variant_builder_unref(builder);
113 message = stc_manager_gdbus_call_sync(connection,
114 STC_IPTABLES_DBUS_SERVICE,
115 STC_IPTABLES_DBUS_RULE_PATH,
116 STC_IPTABLES_DBUS_RULE_INTERFACE,
117 STC_IPTABLES_DBUS_METHOD_IPT_ADD_RULE,
120 if (message == NULL) {
121 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
122 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
125 g_variant_get(message, "(i)", &result);
127 STC_LOGD("Successfully Add Rule [%d:%s]", result, rule->nfacct_name);
128 g_variant_unref(message);
130 return STC_ERROR_NONE;
133 static int __iptables_rule_remove(GDBusConnection *connection,
134 iptables_rule_s *rule)
137 GVariantBuilder *builder = NULL;
138 GVariant *params = NULL;
139 GVariant *message = NULL;
141 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
142 __add_rule_info_to_builder(builder, rule);
143 params = g_variant_new("(a{sv})", builder);
144 g_variant_builder_unref(builder);
146 message = stc_manager_gdbus_call_sync(connection,
147 STC_IPTABLES_DBUS_SERVICE,
148 STC_IPTABLES_DBUS_RULE_PATH,
149 STC_IPTABLES_DBUS_RULE_INTERFACE,
150 STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE,
153 if (message == NULL) {
154 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
155 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
158 g_variant_get(message, "(i)", &result);
160 STC_LOGD("Successfully Remove Rule [%d:%s]", result, rule->nfacct_name);
161 g_variant_unref(message);
163 return STC_ERROR_NONE;
166 static int __ip6tables_rule_add(GDBusConnection *connection,
167 iptables_rule_s *rule)
170 GVariantBuilder *builder = NULL;
171 GVariant *params = NULL;
172 GVariant *message = NULL;
174 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
175 __add_rule_info_to_builder(builder, rule);
176 params = g_variant_new("(a{sv})", builder);
177 g_variant_builder_unref(builder);
179 message = stc_manager_gdbus_call_sync(connection,
180 STC_IPTABLES_DBUS_SERVICE,
181 STC_IPTABLES_DBUS_RULE_PATH,
182 STC_IPTABLES_DBUS_RULE_INTERFACE,
183 STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE,
186 if (message == NULL) {
187 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
188 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
191 g_variant_get(message, "(i)", &result);
193 STC_LOGD("Successfully Add 6 Rule [%d:%s]", result, rule->nfacct_name);
194 g_variant_unref(message);
196 return STC_ERROR_NONE;
199 static int __ip6tables_rule_remove(GDBusConnection *connection,
200 iptables_rule_s *rule)
203 GVariantBuilder *builder = NULL;
204 GVariant *params = NULL;
205 GVariant *message = NULL;
207 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
208 __add_rule_info_to_builder(builder, rule);
209 params = g_variant_new("(a{sv})", builder);
210 g_variant_builder_unref(builder);
212 message = stc_manager_gdbus_call_sync(connection,
213 STC_IPTABLES_DBUS_SERVICE,
214 STC_IPTABLES_DBUS_RULE_PATH,
215 STC_IPTABLES_DBUS_RULE_INTERFACE,
216 STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE,
219 if (message == NULL) {
220 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
221 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
224 g_variant_get(message, "(i)", &result);
226 STC_LOGD("Successfully Remove 6 Rule [%d:%s]", result, rule->nfacct_name);
227 g_variant_unref(message);
229 return STC_ERROR_NONE;
232 static int __iptables_add_chain(GDBusConnection *connection,
236 GVariant *message = NULL;
238 message = stc_manager_gdbus_call_sync(connection,
239 STC_IPTABLES_DBUS_SERVICE,
240 STC_IPTABLES_DBUS_CHAIN_PATH,
241 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
242 STC_IPTABLES_DBUS_METHOD_IPT_ADD_CHAIN,
243 g_variant_new("(s)", chain));
245 if (message == NULL) {
246 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
247 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
250 g_variant_get(message, "(i)", &result);
251 STC_LOGD("Successfully added ipv4 chain [%d:%s]", result, chain);
252 g_variant_unref(message);
254 return STC_ERROR_NONE;
257 static int __ip6tables_add_chain(GDBusConnection *connection,
261 GVariant *message = NULL;
263 message = stc_manager_gdbus_call_sync(connection,
264 STC_IPTABLES_DBUS_SERVICE,
265 STC_IPTABLES_DBUS_CHAIN_PATH,
266 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
267 STC_IPTABLES_DBUS_METHOD_IP6T_ADD_CHAIN,
268 g_variant_new("(s)", chain));
270 if (message == NULL) {
271 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
272 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
275 g_variant_get(message, "(i)", &result);
276 STC_LOGD("Successfully added ipv6 chain [%d:%s]", result, chain);
277 g_variant_unref(message);
279 return STC_ERROR_NONE;
282 static int __iptables_remove_chain(GDBusConnection *connection,
286 GVariant *message = NULL;
288 message = stc_manager_gdbus_call_sync(connection,
289 STC_IPTABLES_DBUS_SERVICE,
290 STC_IPTABLES_DBUS_CHAIN_PATH,
291 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
292 STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_CHAIN,
293 g_variant_new("(s)", chain));
295 if (message == NULL) {
296 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
297 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
300 g_variant_get(message, "(i)", &result);
301 STC_LOGD("Successfully removed ipv4 chain [%d:%s]", result, chain);
302 g_variant_unref(message);
304 return STC_ERROR_NONE;
307 static int __ip6tables_remove_chain(GDBusConnection *connection,
311 GVariant *message = NULL;
313 message = stc_manager_gdbus_call_sync(connection,
314 STC_IPTABLES_DBUS_SERVICE,
315 STC_IPTABLES_DBUS_CHAIN_PATH,
316 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
317 STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_CHAIN,
318 g_variant_new("(s)", chain));
320 if (message == NULL) {
321 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
322 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
325 g_variant_get(message, "(i)", &result);
326 STC_LOGD("Successfully removed ipv6 chain [%d:%s]", result, chain);
327 g_variant_unref(message);
329 return STC_ERROR_NONE;
332 static int __iptables_flush_chain(GDBusConnection *connection,
336 GVariant *message = NULL;
338 message = stc_manager_gdbus_call_sync(connection,
339 STC_IPTABLES_DBUS_SERVICE,
340 STC_IPTABLES_DBUS_CHAIN_PATH,
341 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
342 STC_IPTABLES_DBUS_METHOD_IPT_FLUSH_CHAIN,
343 g_variant_new("(s)", chain));
345 if (message == NULL) {
346 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
347 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
350 g_variant_get(message, "(i)", &result);
351 STC_LOGD("Successfully flushed ipv4 chain [%d:%s]", result, chain);
352 g_variant_unref(message);
354 return STC_ERROR_NONE;
357 static int __ip6tables_flush_chain(GDBusConnection *connection,
361 GVariant *message = NULL;
363 message = stc_manager_gdbus_call_sync(connection,
364 STC_IPTABLES_DBUS_SERVICE,
365 STC_IPTABLES_DBUS_CHAIN_PATH,
366 STC_IPTABLES_DBUS_CHAIN_INTERFACE,
367 STC_IPTABLES_DBUS_METHOD_IP6T_FLUSH_CHAIN,
368 g_variant_new("(s)", chain));
370 if (message == NULL) {
371 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
372 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
375 g_variant_get(message, "(i)", &result);
376 STC_LOGD("Successfully flushed ipv6 chain [%d:%s]", result, chain);
377 g_variant_unref(message);
379 return STC_ERROR_NONE;
382 static int __iptables_add_chain_jump_rule(const char *chain,
385 stc_error_e ret = STC_ERROR_NONE;
386 iptables_rule_s iptables_rule;
387 memset(&iptables_rule, 0, sizeof(iptables_rule_s));
389 iptables_rule.target = g_strdup(target);
390 iptables_rule.chain = g_strdup(chain);
392 ret = iptables_add(&iptables_rule, IP_TYPE_IPV4_IPV6);
394 g_free(iptables_rule.target);
395 g_free(iptables_rule.chain);
400 stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype)
402 stc_error_e ret = STC_ERROR_NONE;
403 stc_s *stc = stc_get_manager();
405 if (!stc || !stc->connection)
406 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
408 if (iptype == IP_TYPE_IPV4 ||
409 iptype == IP_TYPE_IPV4_IPV6) {
410 ret = __iptables_rule_add(stc->connection, rule);
411 if (ret != STC_ERROR_NONE)
412 goto done; //LCOV_EXCL_LINE
415 if (iptype == IP_TYPE_IPV6 ||
416 iptype == IP_TYPE_IPV4_IPV6)
417 ret = __ip6tables_rule_add(stc->connection, rule);
423 stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype)
425 stc_error_e ret = STC_ERROR_NONE;
426 stc_s *stc = stc_get_manager();
428 if (!stc || !stc->connection)
429 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
431 if (iptype == IP_TYPE_IPV4 ||
432 iptype == IP_TYPE_IPV4_IPV6) {
433 ret = __iptables_rule_remove(stc->connection, rule);
434 if (ret != STC_ERROR_NONE)
435 goto done; //LCOV_EXCL_LINE
438 if (iptype == IP_TYPE_IPV6 ||
439 iptype == IP_TYPE_IPV4_IPV6)
440 ret = __ip6tables_rule_remove(stc->connection, rule);
446 stc_error_e iptables_flush_chains(void)
448 stc_error_e ret = STC_ERROR_NONE;
449 stc_s *stc = stc_get_manager();
451 if (!stc || !stc->connection)
452 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
454 ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
455 if (ret != STC_ERROR_NONE)
456 goto done; //LCOV_EXCL_LINE
458 ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
459 if (ret != STC_ERROR_NONE)
460 goto done; //LCOV_EXCL_LINE
462 ret = __iptables_flush_chain(stc->connection, STC_FRWD_CHAIN);
463 if (ret != STC_ERROR_NONE)
464 goto done; //LCOV_EXCL_LINE
466 ret = __iptables_flush_chain(stc->connection, STC_TETHER_CHAIN);
467 if (ret != STC_ERROR_NONE)
468 goto done; //LCOV_EXCL_LINE
470 ret = __ip6tables_flush_chain(stc->connection, STC_IN_CHAIN);
471 if (ret != STC_ERROR_NONE)
472 goto done; //LCOV_EXCL_LINE
474 ret = __ip6tables_flush_chain(stc->connection, STC_OUT_CHAIN);
475 if (ret != STC_ERROR_NONE)
476 goto done; //LCOV_EXCL_LINE
478 ret = __ip6tables_flush_chain(stc->connection, STC_FRWD_CHAIN);
483 stc_error_e iptables_init(void)
485 __STC_LOG_FUNC_ENTER__;
487 stc_error_e ret = STC_ERROR_NONE;
488 stc_s *stc = stc_get_manager();
490 if (!stc || !stc->connection) {
491 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
492 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
495 ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
496 if (ret != STC_ERROR_NONE) {
497 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
498 goto done; //LCOV_EXCL_LINE
501 ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
502 if (ret != STC_ERROR_NONE) {
503 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
504 goto done; //LCOV_EXCL_LINE
507 ret = __iptables_add_chain(stc->connection, STC_FRWD_CHAIN);
508 if (ret != STC_ERROR_NONE) {
509 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
510 goto done; //LCOV_EXCL_LINE
513 ret = __iptables_add_chain(stc->connection, STC_TETHER_CHAIN);
514 if (ret != STC_ERROR_NONE) {
515 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
516 goto done; //LCOV_EXCL_LINE
519 ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
520 if (ret != STC_ERROR_NONE) {
521 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
522 goto done; //LCOV_EXCL_LINE
525 ret = __ip6tables_add_chain(stc->connection, STC_OUT_CHAIN);
526 if (ret != STC_ERROR_NONE) {
527 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
528 goto done; //LCOV_EXCL_LINE
531 ret = __ip6tables_add_chain(stc->connection, STC_FRWD_CHAIN);
532 if (ret != STC_ERROR_NONE) {
533 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
534 goto done; //LCOV_EXCL_LINE
537 ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
538 if (ret != STC_ERROR_NONE) {
539 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
540 goto done; //LCOV_EXCL_LINE
543 ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
544 if (ret != STC_ERROR_NONE) {
545 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
546 goto done; //LCOV_EXCL_LINE
549 ret = __iptables_add_chain_jump_rule("FORWARD", STC_FRWD_CHAIN);
550 if (ret != STC_ERROR_NONE) {
551 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
552 goto done; //LCOV_EXCL_LINE
555 ret = __iptables_add_chain_jump_rule("FORWARD", STC_TETHER_CHAIN);
556 if (ret != STC_ERROR_NONE) {
557 __STC_LOG_FUNC_EXIT__;
564 stc_error_e iptables_deinit(void)
566 __STC_LOG_FUNC_ENTER__;
568 stc_error_e ret = STC_ERROR_NONE;
569 stc_s *stc = stc_get_manager();
571 if (!stc || !stc->connection) {
572 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
573 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
576 ret = __iptables_remove_chain(stc->connection, STC_IN_CHAIN);
577 if (ret != STC_ERROR_NONE) {
578 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
579 goto done; //LCOV_EXCL_LINE
582 ret = __iptables_remove_chain(stc->connection, STC_OUT_CHAIN);
583 if (ret != STC_ERROR_NONE) {
584 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
585 goto done; //LCOV_EXCL_LINE
588 ret = __iptables_remove_chain(stc->connection, STC_TETHER_CHAIN);
589 if (ret != STC_ERROR_NONE) {
590 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
591 goto done; //LCOV_EXCL_LINE
594 ret = __iptables_remove_chain(stc->connection, STC_FRWD_CHAIN);
595 if (ret != STC_ERROR_NONE) {
596 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
597 goto done; //LCOV_EXCL_LINE
600 ret = __ip6tables_remove_chain(stc->connection, STC_IN_CHAIN);
601 if (ret != STC_ERROR_NONE) {
602 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
603 goto done; //LCOV_EXCL_LINE
606 ret = __ip6tables_remove_chain(stc->connection, STC_OUT_CHAIN);
607 if (ret != STC_ERROR_NONE) {
608 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
609 goto done; //LCOV_EXCL_LINE
612 ret = __ip6tables_remove_chain(stc->connection, STC_FRWD_CHAIN);