Add inotify for information config
[platform/core/connectivity/stc-manager.git] / src / helper / helper-iptables.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "stc-manager-gdbus.h"
18 #include "helper-iptables.h"
19
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"
35
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
43 static void __add_rule_info_to_builder(GVariantBuilder *builder,
44                                        iptables_rule_s *rule)
45 {
46         if (builder == NULL || rule == NULL)
47                 return; //LCOV_EXCL_LINE
48
49         g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
50                               g_variant_new_string(rule->chain));
51
52         g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
53                               g_variant_new_uint16(rule->direction));
54
55         if (rule->ifname)
56                 g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
57                                       g_variant_new_string(rule->ifname));
58
59         if (rule->classid > 0)
60                 g_variant_builder_add(builder, "{sv}", RULE_CGROUP,
61                                       g_variant_new_uint32(rule->classid));
62
63         if (rule->nfacct_name)
64                 g_variant_builder_add(builder, "{sv}", RULE_NFACCT,
65                                       g_variant_new_string(rule->nfacct_name));
66
67         if (rule->target)
68                 g_variant_builder_add(builder, "{sv}", RULE_TARGET,
69                                       g_variant_new_string(rule->target));
70
71 }
72
73 static int __iptables_rule_add(GDBusConnection *connection,
74                                iptables_rule_s *rule)
75 {
76         int result = 0;
77         GVariantBuilder *builder = NULL;
78         GVariant *params = NULL;
79         GVariant *message = NULL;
80
81         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
82         __add_rule_info_to_builder(builder, rule);
83         params = g_variant_new("(a{sv})", builder);
84         g_variant_builder_unref(builder);
85
86         message = stc_manager_gdbus_call_sync(connection,
87                                               STC_IPTABLES_DBUS_SERVICE,
88                                               STC_IPTABLES_DBUS_RULE_PATH,
89                                               STC_IPTABLES_DBUS_RULE_INTERFACE,
90                                               STC_IPTABLES_DBUS_METHOD_IPT_ADD_RULE,
91                                               params);
92
93         if (message == NULL) {
94                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
95                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
96         }
97
98         g_variant_get(message, "(i)", &result);
99         if (STC_DEBUG_LOG)
100                 STC_LOGD("Successfully Add Rule [%d:%s]", result, rule->nfacct_name);
101         g_variant_unref(message);
102
103         return STC_ERROR_NONE;
104 }
105
106 static int __iptables_rule_remove(GDBusConnection *connection,
107                                   iptables_rule_s *rule)
108 {
109         int result = 0;
110         GVariantBuilder *builder = NULL;
111         GVariant *params = NULL;
112         GVariant *message = NULL;
113
114         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
115         __add_rule_info_to_builder(builder, rule);
116         params = g_variant_new("(a{sv})", builder);
117         g_variant_builder_unref(builder);
118
119         message = stc_manager_gdbus_call_sync(connection,
120                                               STC_IPTABLES_DBUS_SERVICE,
121                                               STC_IPTABLES_DBUS_RULE_PATH,
122                                               STC_IPTABLES_DBUS_RULE_INTERFACE,
123                                               STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE,
124                                               params);
125
126         if (message == NULL) {
127                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
128                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
129         }
130
131         g_variant_get(message, "(i)", &result);
132         if (STC_DEBUG_LOG)
133                 STC_LOGD("Successfully Remove Rule [%d:%s]", result, rule->nfacct_name);
134         g_variant_unref(message);
135
136         return STC_ERROR_NONE;
137 }
138
139 static int __ip6tables_rule_add(GDBusConnection *connection,
140                                 iptables_rule_s *rule)
141 {
142         int result = 0;
143         GVariantBuilder *builder = NULL;
144         GVariant *params = NULL;
145         GVariant *message = NULL;
146
147         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
148         __add_rule_info_to_builder(builder, rule);
149         params = g_variant_new("(a{sv})", builder);
150         g_variant_builder_unref(builder);
151
152         message = stc_manager_gdbus_call_sync(connection,
153                                               STC_IPTABLES_DBUS_SERVICE,
154                                               STC_IPTABLES_DBUS_RULE_PATH,
155                                               STC_IPTABLES_DBUS_RULE_INTERFACE,
156                                               STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE,
157                                               params);
158
159         if (message == NULL) {
160                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
161                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
162         }
163
164         g_variant_get(message, "(i)", &result);
165         if (STC_DEBUG_LOG)
166                 STC_LOGD("Successfully Add 6 Rule [%d:%s]", result, rule->nfacct_name);
167         g_variant_unref(message);
168
169         return STC_ERROR_NONE;
170 }
171
172 static int __ip6tables_rule_remove(GDBusConnection *connection,
173                                    iptables_rule_s *rule)
174 {
175         int result = 0;
176         GVariantBuilder *builder = NULL;
177         GVariant *params = NULL;
178         GVariant *message = NULL;
179
180         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
181         __add_rule_info_to_builder(builder, rule);
182         params = g_variant_new("(a{sv})", builder);
183         g_variant_builder_unref(builder);
184
185         message = stc_manager_gdbus_call_sync(connection,
186                                               STC_IPTABLES_DBUS_SERVICE,
187                                               STC_IPTABLES_DBUS_RULE_PATH,
188                                               STC_IPTABLES_DBUS_RULE_INTERFACE,
189                                               STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE,
190                                               params);
191
192         if (message == NULL) {
193                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
194                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
195         }
196
197         g_variant_get(message, "(i)", &result);
198         if (STC_DEBUG_LOG)
199                 STC_LOGD("Successfully Remove 6 Rule [%d:%s]", result, rule->nfacct_name);
200         g_variant_unref(message);
201
202         return STC_ERROR_NONE;
203 }
204
205 static int __iptables_add_chain(GDBusConnection *connection,
206                                 const char *chain)
207 {
208         int result = 0;
209         GVariant *message = NULL;
210
211         message = stc_manager_gdbus_call_sync(connection,
212                                               STC_IPTABLES_DBUS_SERVICE,
213                                               STC_IPTABLES_DBUS_CHAIN_PATH,
214                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
215                                               STC_IPTABLES_DBUS_METHOD_IPT_ADD_CHAIN,
216                                               g_variant_new("(s)", chain));
217
218         if (message == NULL) {
219                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
220                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
221         }
222
223         g_variant_get(message, "(i)", &result);
224         STC_LOGD("Successfully added ipv4 chain [%d:%s]", result, chain);
225         g_variant_unref(message);
226
227         return STC_ERROR_NONE;
228 }
229
230 static int __ip6tables_add_chain(GDBusConnection *connection,
231                                  const char *chain)
232 {
233         int result = 0;
234         GVariant *message = NULL;
235
236         message = stc_manager_gdbus_call_sync(connection,
237                                               STC_IPTABLES_DBUS_SERVICE,
238                                               STC_IPTABLES_DBUS_CHAIN_PATH,
239                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
240                                               STC_IPTABLES_DBUS_METHOD_IP6T_ADD_CHAIN,
241                                               g_variant_new("(s)", chain));
242
243         if (message == NULL) {
244                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
245                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
246         }
247
248         g_variant_get(message, "(i)", &result);
249         STC_LOGD("Successfully added ipv6 chain [%d:%s]", result, chain);
250         g_variant_unref(message);
251
252         return STC_ERROR_NONE;
253 }
254
255 static int __iptables_remove_chain(GDBusConnection *connection,
256                                    const char *chain)
257 {
258         int result = 0;
259         GVariant *message = NULL;
260
261         message = stc_manager_gdbus_call_sync(connection,
262                                               STC_IPTABLES_DBUS_SERVICE,
263                                               STC_IPTABLES_DBUS_CHAIN_PATH,
264                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
265                                               STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_CHAIN,
266                                               g_variant_new("(s)", chain));
267
268         if (message == NULL) {
269                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
270                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
271         }
272
273         g_variant_get(message, "(i)", &result);
274         STC_LOGD("Successfully removed ipv4 chain [%d:%s]", result, chain);
275         g_variant_unref(message);
276
277         return STC_ERROR_NONE;
278 }
279
280 static int __ip6tables_remove_chain(GDBusConnection *connection,
281                                     const char *chain)
282 {
283         int result = 0;
284         GVariant *message = NULL;
285
286         message = stc_manager_gdbus_call_sync(connection,
287                                               STC_IPTABLES_DBUS_SERVICE,
288                                               STC_IPTABLES_DBUS_CHAIN_PATH,
289                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
290                                               STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_CHAIN,
291                                               g_variant_new("(s)", chain));
292
293         if (message == NULL) {
294                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
295                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
296         }
297
298         g_variant_get(message, "(i)", &result);
299         STC_LOGD("Successfully removed ipv6 chain [%d:%s]", result, chain);
300         g_variant_unref(message);
301
302         return STC_ERROR_NONE;
303 }
304
305 static int __iptables_flush_chain(GDBusConnection *connection,
306                                   const char *chain)
307 {
308         int result = 0;
309         GVariant *message = NULL;
310
311         message = stc_manager_gdbus_call_sync(connection,
312                                               STC_IPTABLES_DBUS_SERVICE,
313                                               STC_IPTABLES_DBUS_CHAIN_PATH,
314                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
315                                               STC_IPTABLES_DBUS_METHOD_IPT_FLUSH_CHAIN,
316                                               g_variant_new("(s)", chain));
317
318         if (message == NULL) {
319                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
320                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
321         }
322
323         g_variant_get(message, "(i)", &result);
324         STC_LOGD("Successfully flushed ipv4 chain [%d:%s]", result, chain);
325         g_variant_unref(message);
326
327         return STC_ERROR_NONE;
328 }
329
330 static int __ip6tables_flush_chain(GDBusConnection *connection,
331                                    const char *chain)
332 {
333         int result = 0;
334         GVariant *message = NULL;
335
336         message = stc_manager_gdbus_call_sync(connection,
337                                               STC_IPTABLES_DBUS_SERVICE,
338                                               STC_IPTABLES_DBUS_CHAIN_PATH,
339                                               STC_IPTABLES_DBUS_CHAIN_INTERFACE,
340                                               STC_IPTABLES_DBUS_METHOD_IP6T_FLUSH_CHAIN,
341                                               g_variant_new("(s)", chain));
342
343         if (message == NULL) {
344                 STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
345                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
346         }
347
348         g_variant_get(message, "(i)", &result);
349         STC_LOGD("Successfully flushed ipv6 chain [%d:%s]", result, chain);
350         g_variant_unref(message);
351
352         return STC_ERROR_NONE;
353 }
354
355 static int __iptables_add_chain_jump_rule(const char *chain,
356                                           const char *target)
357 {
358         stc_error_e ret = STC_ERROR_NONE;
359         iptables_rule_s iptables_rule;
360         memset(&iptables_rule, 0, sizeof(iptables_rule_s));
361
362         iptables_rule.target = g_strdup(target);
363         iptables_rule.chain = g_strdup(chain);
364
365         ret = iptables_add(&iptables_rule, IP_TYPE_IPV4_IPV6);
366
367         g_free(iptables_rule.target);
368         g_free(iptables_rule.chain);
369
370         return ret;
371 }
372
373 stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype)
374 {
375         stc_error_e ret = STC_ERROR_NONE;
376         stc_s *stc = stc_get_manager();
377
378         if (!stc || !stc->connection)
379                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
380
381         if (iptype == IP_TYPE_IPV4 ||
382                 iptype == IP_TYPE_IPV4_IPV6) {
383                 ret = __iptables_rule_add(stc->connection, rule);
384                 if (ret != STC_ERROR_NONE)
385                         goto done; //LCOV_EXCL_LINE
386         }
387
388         if (iptype == IP_TYPE_IPV6 ||
389                 iptype == IP_TYPE_IPV4_IPV6)
390                 ret = __ip6tables_rule_add(stc->connection, rule);
391
392 done:
393         return ret;
394 }
395
396 stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype)
397 {
398         stc_error_e ret = STC_ERROR_NONE;
399         stc_s *stc = stc_get_manager();
400
401         if (!stc || !stc->connection)
402                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
403
404         if (iptype == IP_TYPE_IPV4 ||
405                 iptype == IP_TYPE_IPV4_IPV6) {
406                 ret = __iptables_rule_remove(stc->connection, rule);
407                 if (ret != STC_ERROR_NONE)
408                         goto done; //LCOV_EXCL_LINE
409         }
410
411         if (iptype == IP_TYPE_IPV6 ||
412                 iptype == IP_TYPE_IPV4_IPV6)
413                 ret = __ip6tables_rule_remove(stc->connection, rule);
414
415 done:
416         return ret;
417 }
418
419 stc_error_e iptables_flush_chains(void)
420 {
421         stc_error_e ret = STC_ERROR_NONE;
422         stc_s *stc = stc_get_manager();
423
424         if (!stc || !stc->connection)
425                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
426
427         ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
428         if (ret != STC_ERROR_NONE)
429                 goto done; //LCOV_EXCL_LINE
430
431         ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
432         if (ret != STC_ERROR_NONE)
433                 goto done; //LCOV_EXCL_LINE
434
435         ret = __iptables_flush_chain(stc->connection, STC_FRWD_CHAIN);
436         if (ret != STC_ERROR_NONE)
437                 goto done; //LCOV_EXCL_LINE
438
439         ret = __ip6tables_flush_chain(stc->connection, STC_IN_CHAIN);
440         if (ret != STC_ERROR_NONE)
441                 goto done; //LCOV_EXCL_LINE
442
443         ret = __ip6tables_flush_chain(stc->connection, STC_OUT_CHAIN);
444         if (ret != STC_ERROR_NONE)
445                 goto done; //LCOV_EXCL_LINE
446
447         ret = __ip6tables_flush_chain(stc->connection, STC_FRWD_CHAIN);
448 done:
449         return ret;
450 }
451
452 stc_error_e iptables_init(void)
453 {
454         __STC_LOG_FUNC_ENTER__;
455
456         stc_error_e ret = STC_ERROR_NONE;
457         stc_s *stc = stc_get_manager();
458
459         if (!stc || !stc->connection) {
460                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
461                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
462         }
463
464         ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
465         if (ret != STC_ERROR_NONE) {
466                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
467                 goto done; //LCOV_EXCL_LINE
468         }
469
470         ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
471         if (ret != STC_ERROR_NONE) {
472                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
473                 goto done; //LCOV_EXCL_LINE
474         }
475
476         ret = __iptables_add_chain(stc->connection, STC_FRWD_CHAIN);
477         if (ret != STC_ERROR_NONE) {
478                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
479                 goto done; //LCOV_EXCL_LINE
480         }
481
482         ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
483         if (ret != STC_ERROR_NONE) {
484                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
485                 goto done; //LCOV_EXCL_LINE
486         }
487
488         ret = __ip6tables_add_chain(stc->connection, STC_OUT_CHAIN);
489         if (ret != STC_ERROR_NONE) {
490                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
491                 goto done; //LCOV_EXCL_LINE
492         }
493
494         ret = __ip6tables_add_chain(stc->connection, STC_FRWD_CHAIN);
495         if (ret != STC_ERROR_NONE) {
496                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
497                 goto done; //LCOV_EXCL_LINE
498         }
499
500         ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
501         if (ret != STC_ERROR_NONE) {
502                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
503                 goto done; //LCOV_EXCL_LINE
504         }
505
506         ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
507         if (ret != STC_ERROR_NONE) {
508                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
509                 goto done; //LCOV_EXCL_LINE
510         }
511
512         ret = __iptables_add_chain_jump_rule("FORWARD", STC_FRWD_CHAIN);
513 done:
514         return ret;
515 }
516
517 stc_error_e iptables_deinit(void)
518 {
519         __STC_LOG_FUNC_ENTER__;
520
521         stc_error_e ret = STC_ERROR_NONE;
522         stc_s *stc = stc_get_manager();
523
524         if (!stc || !stc->connection) {
525                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
526                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
527         }
528
529         ret = __iptables_remove_chain(stc->connection, STC_IN_CHAIN);
530         if (ret != STC_ERROR_NONE) {
531                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
532                 goto done; //LCOV_EXCL_LINE
533         }
534
535         ret = __iptables_remove_chain(stc->connection, STC_OUT_CHAIN);
536         if (ret != STC_ERROR_NONE) {
537                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
538                 goto done; //LCOV_EXCL_LINE
539         }
540
541         ret = __iptables_remove_chain(stc->connection, STC_FRWD_CHAIN);
542         if (ret != STC_ERROR_NONE) {
543                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
544                 goto done; //LCOV_EXCL_LINE
545         }
546
547         ret = __ip6tables_remove_chain(stc->connection, STC_IN_CHAIN);
548         if (ret != STC_ERROR_NONE) {
549                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
550                 goto done; //LCOV_EXCL_LINE
551         }
552
553         ret = __ip6tables_remove_chain(stc->connection, STC_OUT_CHAIN);
554         if (ret != STC_ERROR_NONE) {
555                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
556                 goto done; //LCOV_EXCL_LINE
557         }
558
559         ret = __ip6tables_remove_chain(stc->connection, STC_FRWD_CHAIN);
560 done:
561         return ret;
562 }