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