2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <arpa/inet.h>
24 #include <linux/netfilter.h>
25 #include <linux/netfilter/xt_cgroup.h>
26 #include <linux/netfilter/xt_nfacct.h>
27 #include <linux/netfilter/xt_iprange.h>
28 #include <linux/netfilter/xt_NFLOG.h>
29 #include <linux/netfilter_ipv4/ipt_LOG.h>
31 #include "stc-iptables-error.h"
32 #include "helper-iptables.h"
33 #include "helper-log.h"
35 #define IPT_ALIGN XT_ALIGN
36 #define IPTC_TABLE "filter"
37 #define IPTC_TCP "tcp"
38 #define IPTC_UDP "udp"
39 #define IPTC_CGROUP "cgroup"
40 #define IPTC_NFACCT "nfacct"
41 #define IPTC_IPRANGE "iprange"
42 #define IPTC_LOG "LOG"
43 #define IPTC_NFLOG "NFLOG"
45 #define IPTC_MASK "255.255.255.255"
47 #define IPTC_INSERT_RULENUM 0
50 typedef struct xtc_handle ipt_handle_t;
53 typedef struct ipt_entry ipt_entry_t;
54 typedef struct ipt_entry_match ipt_entry_match_t;
55 typedef struct ipt_entry_target ipt_entry_target_t;
58 typedef struct xt_tcp ipt_tcp_info_t;
59 typedef struct xt_udp ipt_udp_info_t;
60 typedef struct xt_cgroup_info_v0 ipt_cgroup_info_t;
61 typedef struct xt_nfacct_match_info ipt_nfacct_info_t;
62 typedef struct xt_iprange_mtinfo ipt_iprange_info_t;
65 typedef struct ipt_log_info ipt_log_info_t;
66 typedef struct xt_nflog_info ipt_nflog_info_t;
68 #define SIZE_ENTRY IPT_ALIGN(sizeof(ipt_entry_t))
69 #define SIZE_TCP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_tcp_info_t))
70 #define SIZE_UDP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_udp_info_t))
71 #define SIZE_CGROUP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_cgroup_info_t))
72 #define SIZE_NFACCT_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_nfacct_info_t))
73 #define SIZE_IPRANGE_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_iprange_info_t))
74 #define SIZE_TARGET IPT_ALIGN(sizeof(ipt_entry_target_t)) + IPT_ALIGN(sizeof(int))
75 #define SIZE_TARGET_LOG IPT_ALIGN(sizeof(ipt_log_info_t))
76 #define SIZE_TARGET_NFLOG IPT_ALIGN(sizeof(ipt_nflog_info_t))
77 #define SIZE_TOTAL SIZE_ENTRY + SIZE_TCP_MATCH + SIZE_UDP_MATCH + SIZE_CGROUP_MATCH \
78 + SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET \
79 + SIZE_TARGET_LOG + SIZE_TARGET_NFLOG
81 static unsigned int __add_match(const char *name, ipt_entry_match_t *start,
82 int revision, size_t size, void *data)
84 ipt_entry_match_t *match = start;
86 match->u.match_size = IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(size);
88 g_strlcpy(match->u.user.name, name, XT_EXTENSION_MAXNAMELEN);
89 memcpy(match->data, data, size);
90 match->u.user.revision = revision;
92 return match->u.match_size;
95 static unsigned int __add_target(const char *name, ipt_entry_target_t *start, size_t size, void *data)
97 ipt_entry_target_t *target = start;
99 target->u.target_size = IPT_ALIGN(sizeof(ipt_entry_target_t)) + IPT_ALIGN(size);
101 g_strlcpy(target->u.user.name, name, XT_EXTENSION_MAXNAMELEN);
102 memcpy(target->data, data, size);
104 return target->u.target_size;
107 static unsigned int __add_iprange_match(iptables_ip_type_e sip_type,
108 struct in_addr sip1, struct in_addr sip2, iptables_ip_type_e dip_type,
109 struct in_addr dip1, struct in_addr dip2, ipt_entry_match_t *start)
111 ipt_iprange_info_t iprange;
112 memset(&iprange, 0, sizeof(ipt_iprange_info_t));
114 /* iprange => "--src-range " */
115 if (sip_type == IPTABLES_IP_RANGE) {
116 memcpy(&(iprange.src_min.in), &sip1, sizeof(struct in_addr));
117 memcpy(&(iprange.src_max.in), &sip2, sizeof(struct in_addr));
118 iprange.flags |= IPRANGE_SRC;
121 /* iprange => "--dst-range " */
122 if (dip_type == IPTABLES_IP_RANGE) {
123 memcpy(&(iprange.dst_min.in), &dip1, sizeof(struct in_addr));
124 memcpy(&(iprange.dst_max.in), &dip2, sizeof(struct in_addr));
125 iprange.flags |= IPRANGE_DST;
128 /* match_iprange => "-m iprange" */
129 return __add_match(IPTC_IPRANGE, start, 1, sizeof(ipt_iprange_info_t), &iprange);
132 static void __add_iprange(unsigned char *entry, unsigned int *size_mask,
133 unsigned int *size_match, iptables_rule_s *rule)
135 ipt_entry_t *e = (ipt_entry_t *)(entry);
137 (*size_match) += __add_iprange_match(rule->s_ip_type,
138 rule->s_ip1, rule->s_ip2, rule->d_ip_type, rule->d_ip1,
139 rule->d_ip2, (ipt_entry_match_t *)(e->elems + (*size_match)));
141 (*size_mask) += sizeof(ipt_entry_match_t);
142 e->target_offset += SIZE_IPRANGE_MATCH;
143 e->next_offset += SIZE_IPRANGE_MATCH;
146 static unsigned int __add_port_match(iptables_protocol_type_e prot_type,
147 iptables_port_type_e sport_type, unsigned short sport1, unsigned short sport2,
148 iptables_port_type_e dport_type, unsigned short dport1, unsigned short dport2,
149 ipt_entry_match_t *start)
152 case IPTABLES_PROTOCOL_TCP:
155 memset(&tcp, 0, sizeof(ipt_tcp_info_t));
158 case IPTABLES_PORT_SINGLE:
159 tcp.spts[0] = ntohs(htons(sport1));
160 tcp.spts[1] = ntohs(htons(sport1));
162 /* --sport 0:59136 */
163 case IPTABLES_PORT_RANGE:
164 tcp.spts[0] = ntohs(htons(sport1));
165 tcp.spts[1] = ntohs(htons(sport2));
168 tcp.spts[0] = 0x0000;
169 tcp.spts[1] = 0xFFFF;
174 case IPTABLES_PORT_SINGLE:
175 tcp.dpts[0] = ntohs(htons(dport1));
176 tcp.dpts[1] = ntohs(htons(dport1));
178 /* --dport 0:59136 */
179 case IPTABLES_PORT_RANGE:
180 tcp.dpts[0] = ntohs(htons(dport1));
181 tcp.dpts[1] = ntohs(htons(dport2));
184 tcp.dpts[0] = 0x0000;
185 tcp.dpts[1] = 0xFFFF;
188 return __add_match(IPTC_TCP, start, 0, sizeof(ipt_tcp_info_t), &tcp);
190 case IPTABLES_PROTOCOL_UDP:
193 memset(&udp, 0, sizeof(ipt_udp_info_t));
196 case IPTABLES_PORT_SINGLE:
197 udp.spts[0] = ntohs(htons(sport1));
198 udp.spts[1] = ntohs(htons(sport1));
200 /* --sport 0:59136 */
201 case IPTABLES_PORT_RANGE:
202 udp.spts[0] = ntohs(htons(sport1));
203 udp.spts[1] = ntohs(htons(sport2));
206 udp.spts[0] = 0x0000;
207 udp.spts[1] = 0xFFFF;
212 case IPTABLES_PORT_SINGLE:
213 udp.dpts[0] = ntohs(htons(dport1));
214 udp.dpts[1] = ntohs(htons(dport1));
216 /* --dport 0:59136 */
217 case IPTABLES_PORT_RANGE:
218 udp.dpts[0] = ntohs(htons(dport1));
219 udp.dpts[1] = ntohs(htons(dport2));
222 udp.dpts[0] = 0x0000;
223 udp.dpts[1] = 0xFFFF;
226 return __add_match(IPTC_UDP, start, 0, sizeof(ipt_udp_info_t), &udp);
235 static void __add_port(unsigned char *entry, unsigned int *size_mask,
236 unsigned int *size_match, iptables_rule_s *rule, unsigned int match_size)
238 if ((rule->s_port_type > IPTABLES_PORT_NONE &&
239 rule->s_port_type <= IPTABLES_PORT_RANGE) ||
240 (rule->d_port_type > IPTABLES_PORT_NONE &&
241 rule->d_port_type <= IPTABLES_PORT_RANGE)) {
243 ipt_entry_t *e = (ipt_entry_t *)(entry);
245 (*size_match) += __add_port_match(rule->protocol,
246 rule->s_port_type, rule->s_port1, rule->s_port2,
247 rule->d_port_type, rule->d_port1, rule->d_port2,
248 (ipt_entry_match_t *) (e->elems + (*size_match)));
250 (*size_mask) += sizeof(ipt_entry_match_t);
251 e->target_offset += match_size;
252 e->next_offset += match_size;
256 static unsigned int __add_cgroup_match(unsigned int classid, ipt_entry_match_t *start)
258 /* cgroup => "--cgroup 0" */
259 ipt_cgroup_info_t cgroup;
260 memset(&cgroup, 0, sizeof(ipt_cgroup_info_t));
262 /* match_cgroup => "-m cgroup" */
263 return __add_match(IPTC_CGROUP, start, 0, sizeof(ipt_cgroup_info_t), &cgroup);
266 static unsigned int __add_nfacct_match(const char *nfacct_name, ipt_entry_match_t *start)
268 /* nfacct => "--nfacct_name " */
269 ipt_nfacct_info_t nfacct;
270 memset(&nfacct, 0, sizeof(ipt_nfacct_info_t));
271 g_strlcpy(nfacct.name, nfacct_name, NFACCT_NAME_MAX);
272 /* match_nfacct => "-m nfacct" */
273 return __add_match(IPTC_NFACCT, start, 0, sizeof(ipt_nfacct_info_t), &nfacct);
276 static unsigned int __add_log_target(unsigned char level, const char *prefix,
277 ipt_entry_target_t *start)
279 /* log => "--log-level --log-prefix" */
281 memset(&log, 0, sizeof(ipt_log_info_t));
283 g_strlcpy(log.prefix, prefix, 30);
285 return __add_target(IPTC_LOG, start, sizeof(ipt_log_info_t), &log);
288 static unsigned int __add_nflog_target(unsigned int group, const char *prefix,
289 unsigned int range, unsigned int threshold, ipt_entry_target_t *start)
291 /* nflog => "--nflog-group --nflog-prefix --nflog-range --nflog-threshold" */
292 ipt_nflog_info_t nflog;
293 memset(&nflog, 0, sizeof(ipt_nflog_info_t));
295 g_strlcpy(nflog.prefix, prefix, 64);
297 nflog.threshold = threshold;
299 return __add_target(IPTC_NFLOG, start, sizeof(ipt_nflog_info_t), &nflog);
302 static int __create_entry_data(unsigned char *entry, unsigned char *mask,
303 iptables_rule_s *rule)
305 ipt_entry_t *e = NULL;
306 ipt_entry_target_t *target = NULL;
307 unsigned int size_mask = 0;
308 unsigned int size_match = 0;
311 STC_LOGE("Invalid parameters"); //LCOV_EXCL_LINE
312 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
315 e = (ipt_entry_t *)(entry);
318 e->target_offset = SIZE_ENTRY;
319 e->next_offset = SIZE_ENTRY;
320 size_mask = sizeof(ipt_entry_t);
322 if (rule->ifname && rule->ifname[0] != '\0') {
323 switch (rule->direction) {
324 case IPTABLES_DIRECTION_IN:
326 g_strlcpy(e->ip.iniface, rule->ifname, IFNAMSIZ);
327 memset(&(e->ip.iniface_mask), 0xFF, IFNAMSIZ);
329 case IPTABLES_DIRECTION_OUT:
331 g_strlcpy(e->ip.outiface, rule->ifname, IFNAMSIZ);
332 memset(&(e->ip.outiface_mask), 0xFF, IFNAMSIZ);
335 STC_LOGE("Invalid parameter"); //LCOV_EXCL_LINE
336 break; //LCOV_EXCL_LINE
340 switch (rule->s_ip_type) {
341 case IPTABLES_IP_SINGLE:
342 /* -s 102.132.217.5/32 */
343 e->ip.src.s_addr = rule->s_ip1.s_addr;
344 inet_pton(AF_INET, IPTC_MASK, &(e->ip.smsk));
346 case IPTABLES_IP_MASK:
347 /* -s 102.132.217.5/24 */
348 e->ip.src.s_addr = rule->s_ip1.s_addr;
349 e->ip.smsk.s_addr = rule->s_ip2.s_addr;
355 switch (rule->d_ip_type) {
356 case IPTABLES_IP_SINGLE:
357 /* -d 102.132.217.5/32 */
358 e->ip.dst.s_addr = rule->d_ip1.s_addr;
359 inet_pton(AF_INET, IPTC_MASK, &(e->ip.dmsk));
361 case IPTABLES_IP_MASK:
362 /* -d 102.132.217.5/24 */
363 e->ip.dst.s_addr = rule->d_ip1.s_addr;
364 e->ip.dmsk.s_addr = rule->d_ip2.s_addr;
370 if (rule->s_ip_type == IPTABLES_IP_RANGE ||
371 rule->d_ip_type == IPTABLES_IP_RANGE)
372 __add_iprange(entry, &size_mask, &size_match, rule);
375 switch (rule->protocol) {
376 case IPTABLES_PROTOCOL_TCP:
377 e->ip.proto = IPPROTO_TCP;
378 __add_port(entry, &size_mask, &size_match, rule, SIZE_TCP_MATCH);
380 case IPTABLES_PROTOCOL_UDP:
381 e->ip.proto = IPPROTO_UDP;
382 __add_port(entry, &size_mask, &size_match, rule, SIZE_UDP_MATCH);
384 case IPTABLES_PROTOCOL_ICMP:
385 e->ip.proto = IPPROTO_ICMP;
387 case IPTABLES_PROTOCOL_ESP:
388 e->ip.proto = IPPROTO_ESP;
390 case IPTABLES_PROTOCOL_AH:
391 e->ip.proto = IPPROTO_AH;
393 case IPTABLES_PROTOCOL_SCTP:
394 e->ip.proto = IPPROTO_SCTP;
396 case IPTABLES_PROTOCOL_MH:
397 e->ip.proto = IPPROTO_MH;
399 case IPTABLES_PROTOCOL_ALL:
407 /* -m cgroup --cgroup 33 */
408 if (rule->classid > 0) {
409 size_match += __add_cgroup_match(rule->classid,
410 (ipt_entry_match_t *) (e->elems + size_match));
411 size_mask += sizeof(ipt_entry_match_t);
412 e->target_offset += SIZE_CGROUP_MATCH;
413 e->next_offset += SIZE_CGROUP_MATCH;
416 /* -m nfacct --nfacct-name c2_1_33_seth_w0 */
417 if (rule->nfacct_name && rule->nfacct_name[0] != '\0') {
418 size_match += __add_nfacct_match(rule->nfacct_name,
419 (ipt_entry_match_t *) (e->elems + size_match));
420 size_mask += sizeof(ipt_entry_match_t);
421 e->target_offset += SIZE_NFACCT_MATCH;
422 e->next_offset += SIZE_NFACCT_MATCH;
425 /* target => "-j ACCEPT" */
426 target = (ipt_entry_target_t *) (e->elems + size_match);
427 switch (rule->target_type) {
428 case IPTABLES_ACTION_LOG:
429 e->next_offset += __add_log_target(rule->log_level, rule->log_prefix, target);
431 case IPTABLES_ACTION_NFLOG:
432 e->next_offset += __add_nflog_target(rule->nflog_group,
433 rule->nflog_prefix, rule->nflog_range, rule->nflog_threshold, target);
436 target->u.target_size = SIZE_TARGET;
437 if (rule->target && rule->target[0] != '\0')
438 g_strlcpy(target->u.user.name, rule->target, XT_EXTENSION_MAXNAMELEN);
439 e->next_offset += SIZE_TARGET;
443 memset(mask, 0xFF, size_mask);
445 return STC_ERROR_NONE;
448 int iptables_add_rule(iptables_rule_s *rule)
450 ipt_handle_t *handle;
451 unsigned char entry[SIZE_TOTAL] = {0, };
452 unsigned char mask[SIZE_TOTAL] = {0, };
454 const char *chain = rule->chain;
456 if (__create_entry_data(entry, mask, rule) != 0) {
457 STC_LOGE("Failed to create entry"); //LCOV_EXCL_LINE
458 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
461 handle = iptc_init(IPTC_TABLE);
462 if (handle == NULL) {
463 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
464 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
467 if (!iptc_is_chain(chain, handle)) {
468 STC_LOGW("chain not present [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
469 iptc_free(handle); //LCOV_EXCL_LINE
470 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
473 if (iptc_check_entry(chain, (const ipt_entry_t *)entry, mask, handle)) {
474 STC_LOGW("Entry already present"); //LCOV_EXCL_LINE
475 iptc_free(handle); //LCOV_EXCL_LINE
476 return STC_ERROR_NONE; //LCOV_EXCL_LINE
479 if (!iptc_append_entry(chain, (const ipt_entry_t *)entry, handle)) {
480 STC_LOGW("iptc_append_entry failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
481 iptc_free(handle); //LCOV_EXCL_LINE
482 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
485 if (!iptc_commit(handle)) {
486 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
487 iptc_free(handle); //LCOV_EXCL_LINE
488 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
493 STC_LOGI("Success adding rule");
494 return STC_ERROR_NONE;
497 int iptables_insert_rule(iptables_rule_s *rule)
499 ipt_handle_t *handle;
500 unsigned char entry[SIZE_TOTAL] = {0, };
501 unsigned char mask[SIZE_TOTAL] = {0, };
503 const char *chain = rule->chain;
505 if (__create_entry_data(entry, mask, rule) != 0) {
506 STC_LOGE("Failed to create entry"); //LCOV_EXCL_LINE
507 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
510 handle = iptc_init(IPTC_TABLE);
511 if (handle == NULL) {
512 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
513 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
516 if (!iptc_is_chain(chain, handle)) {
517 STC_LOGW("chain not present [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
518 iptc_free(handle); //LCOV_EXCL_LINE
519 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
522 if (iptc_check_entry(chain, (const ipt_entry_t *)entry, mask, handle)) {
523 STC_LOGW("Entry already present"); //LCOV_EXCL_LINE
524 iptc_free(handle); //LCOV_EXCL_LINE
525 return STC_ERROR_NONE; //LCOV_EXCL_LINE
528 if (!iptc_insert_entry(chain, (const ipt_entry_t *)entry, IPTC_INSERT_RULENUM, handle)) {
529 STC_LOGW("iptc_insert_entry failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
530 iptc_free(handle); //LCOV_EXCL_LINE
531 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
534 if (!iptc_commit(handle)) {
535 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
536 iptc_free(handle); //LCOV_EXCL_LINE
537 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
542 STC_LOGI("Success inserting rule");
543 return STC_ERROR_NONE;
546 int iptables_remove_rule(iptables_rule_s *rule)
548 ipt_handle_t *handle;
549 unsigned char entry[SIZE_TOTAL] = {0, };
550 unsigned char mask[SIZE_TOTAL] = {0, };
552 const char *chain = rule->chain;
554 if (__create_entry_data(entry, mask, rule) != 0) {
555 STC_LOGE("Failed to create entry"); //LCOV_EXCL_LINE
556 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
559 handle = iptc_init(IPTC_TABLE);
560 if (handle == NULL) {
561 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
562 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
565 if (!iptc_is_chain(chain, handle)) {
566 STC_LOGW("chain not present [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
567 iptc_free(handle); //LCOV_EXCL_LINE
568 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
571 if (!iptc_delete_entry(chain, (const ipt_entry_t *)entry, mask, handle)) {
572 STC_LOGW("iptc_delete_entry failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
573 iptc_free(handle); //LCOV_EXCL_LINE
574 return STC_ERROR_NONE; //LCOV_EXCL_LINE
577 if (!iptc_commit(handle)) {
578 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
579 iptc_free(handle); //LCOV_EXCL_LINE
580 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
585 STC_LOGI("Success removing rule");
586 return STC_ERROR_NONE;
589 int iptables_add_chain(const char *chain)
591 ipt_handle_t *handle;
593 handle = iptc_init(IPTC_TABLE);
594 if (handle == NULL) {
595 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
596 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
599 if (iptc_is_chain(chain, handle)) {
600 STC_LOGW("chain already exists"); //LCOV_EXCL_LINE
601 iptc_free(handle); //LCOV_EXCL_LINE
602 return STC_ERROR_NONE; //LCOV_EXCL_LINE
605 if (!iptc_create_chain(chain, handle)) {
606 STC_LOGE("Failed to create chaing [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
607 iptc_free(handle); //LCOV_EXCL_LINE
608 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
611 if (!iptc_commit(handle)) {
612 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
613 iptc_free(handle); //LCOV_EXCL_LINE
614 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
619 STC_LOGI("Success adding chain");
623 int iptables_remove_chain(const char *chain)
625 ipt_handle_t *handle;
627 handle = iptc_init(IPTC_TABLE);
628 if (handle == NULL) {
629 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
630 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
633 if (!iptc_is_chain(chain, handle)) {
634 STC_LOGW("chain not present"); //LCOV_EXCL_LINE
635 iptc_free(handle); //LCOV_EXCL_LINE
636 return STC_ERROR_NONE; //LCOV_EXCL_LINE
639 iptc_flush_entries(chain, handle);
641 if (!iptc_delete_chain(chain, handle)) {
642 STC_LOGE("Failed to delete chain [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
643 iptc_free(handle); //LCOV_EXCL_LINE
644 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
647 if (!iptc_commit(handle)) {
648 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
649 iptc_free(handle); //LCOV_EXCL_LINE
650 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
655 STC_LOGI("Success removing chain");
656 return STC_ERROR_NONE;
659 int iptables_flush_chain(const char *chain)
661 ipt_handle_t *handle;
663 handle = iptc_init(IPTC_TABLE);
664 if (handle == NULL) {
665 STC_LOGE("iptc_init failed [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
666 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
669 if (!iptc_is_chain(chain, handle)) {
670 STC_LOGW("chain not present"); //LCOV_EXCL_LINE
671 iptc_free(handle); //LCOV_EXCL_LINE
672 return STC_ERROR_NONE; //LCOV_EXCL_LINE
675 if (!iptc_flush_entries(chain, handle)) {
676 STC_LOGE("Failed to flush chain [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
677 iptc_free(handle); //LCOV_EXCL_LINE
678 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
681 if (!iptc_commit(handle)) {
682 STC_LOGE("Failed to iptc_commit [%s]", iptc_strerror(errno)); //LCOV_EXCL_LINE
683 iptc_free(handle); //LCOV_EXCL_LINE
684 return STC_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
689 STC_LOGI("Success flushing chain");
690 return STC_ERROR_NONE;