-static unsigned int get_args_number(const char *cmd_buf)
-{
- char *str;
- unsigned int count = 0;
-
- for (str = (char *)cmd_buf; *str != '\0'; ++str) {
- if (*str == ' ')
- ++count;
- }
- return count;
-}
-
-static void wait_for_rule_cmd(pid_t pid)
-{
- int status;
- pid_t ret_pid;
- char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
- if (!pid) {
- STC_LOGD("no need to wait");
- return;
- }
- ret_pid = waitpid(pid, &status, 0);
- if (ret_pid < 0)
- STC_LOGD("can't wait for a pid %d %d %s", pid, status,
- strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
-}
-
-static char* get_cmd_pos(const char *cmd_buf)
-{
- char *cmd_pos = strstr(cmd_buf, APPEND);
- if (!cmd_pos)
- cmd_pos = strstr(cmd_buf, INSERT);
-
- return cmd_pos;
-}
-
-static bool is_rule_exists(const char *cmd_buf)
-{
- size_t buf_len;
- char *exec_buf;
- char *cmd_pos = get_cmd_pos(cmd_buf);
- bool ret = false;
- if (!cmd_pos)
- return false;
-
- buf_len = strlen(cmd_buf) + 1;
- exec_buf = (char *)malloc(buf_len);
- if (!exec_buf)
- return false;
-
- strncpy(exec_buf, cmd_buf, buf_len);
- strncpy(exec_buf + (cmd_pos - cmd_buf), IPTABLES_CHECK,
- sizeof(IPTABLES_CHECK) - 1);
-
- STC_LOGD("check rule %s", exec_buf);
-
- ret = system(exec_buf) == 0;
- free(exec_buf);
- return ret;
-}
-
-stc_error_e exec_iptables_cmd(const char *cmd_buf, pid_t *cmd_pid)
-{
- pid_t pid = fork();
-
- if (pid == 0) {
- char *cmd;
- unsigned int i;
- const size_t args_number = get_args_number(cmd_buf);
- char *args[args_number + 2];
- int ret;
- char *save_ptr = NULL;
- char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
- STC_LOGD("executing iptables cmd %s in forked process",
- cmd_buf);
-
- ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
-
- if (is_rule_exists(cmd_buf)) {
- STC_LOGD("Rule %s already exists", cmd_buf);
- exit(0);
- }
- args[0] = "iptables";
- cmd = strtok_r((char *)cmd_buf, " ", &save_ptr);
- ret_value_msg_if(cmd == NULL, STC_ERROR_FAIL, "no arguments");
- for (i = 1; i <= args_number; ++i)
- args[i] = strtok_r(NULL, " ", &save_ptr);
-
- args[i] = NULL;
-
- ret = execv(cmd, args);
- if (ret)
- STC_LOGE("Can't execute %s: %s",
- cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
- exit(ret);
- }
-
- *cmd_pid = pid;
- return STC_ERROR_NONE;
-}
-
-stc_error_e exec_ip6tables_cmd(const char *cmd_buf, pid_t *cmd_pid)
-{
- pid_t pid = fork();
-
- if (pid == 0) {
- char *cmd;
- unsigned int i;
- const size_t args_number = get_args_number(cmd_buf);
- char *args[args_number + 2];
- int ret;
- char *save_ptr = NULL;
- char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
- STC_LOGD("executing ip6tables cmd %s in forked process",
- cmd_buf);
-
- ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
-
- if (is_rule_exists(cmd_buf)) {
- STC_LOGD("Rule %s already exists", cmd_buf);
- exit(0);
- }
- args[0] = "ip6tables";
- cmd = strtok_r((char *)cmd_buf, " ", &save_ptr);
- ret_value_msg_if(cmd == NULL, STC_ERROR_FAIL, "no arguments");
- for (i = 1; i <= args_number; ++i)
- args[i] = strtok_r(NULL, " ", &save_ptr);
-
- args[i] = NULL;
-
- ret = execv(cmd, args);
- if (ret)
- STC_LOGE("Can't execute %s: %s",
- cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
- exit(ret);
- }
-
- *cmd_pid = pid;
- return STC_ERROR_NONE;
-}
-
-static char *choose_iftype_name(nfacct_rule_s *rule)
-{
- return strlen(rule->ifname) != 0 ? rule->ifname :
- get_iftype_name(rule->iftype);
-}
-
-static stc_error_e exec_iface_cmd(const char *pattern, const char *cmd,
- const char *chain, const char *nfacct,
- const char *jump, char *iftype_name,
- pid_t *pid)
-{
- char block_buf[MAX_PATH_LENGTH];
- int ret;
-
- ret_value_msg_if(iftype_name == NULL, STC_ERROR_FAIL,
- "Invalid network interface name argument");
-
- /* iptables rule */
- ret = snprintf(block_buf, sizeof(block_buf), pattern, IPTABLES, cmd, chain,
- iftype_name, nfacct, jump);
- ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
- "Not enough buffer");
- exec_iptables_cmd(block_buf, pid);
-
- /* ip6tables rule */
- ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, cmd, chain,
- iftype_name, nfacct, jump);
- ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
- "Not enough buffer");
- return exec_ip6tables_cmd(block_buf, pid);
-}
-
-static stc_error_e exec_app_cmd(const char *pattern, const char *cmd,
- const char *nfacct, const char *jump,
- const uint32_t classid, char *iftype_name,
- pid_t *pid)
-{
- char block_buf[MAX_PATH_LENGTH];
- int ret;
- ret_value_msg_if(iftype_name == NULL, STC_ERROR_FAIL,
- "Invalid network interface name argument");
-
- /* iptables rules */
- ret = snprintf(block_buf, sizeof(block_buf), pattern, IPTABLES, cmd,
- iftype_name, classid, nfacct, jump);
- ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
- "Not enough buffer");
- exec_iptables_cmd(block_buf, pid);
-
- /* ip6tables rules */
- ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, cmd,
- iftype_name, classid, nfacct, jump);
- ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
- "Not enough buffer");
- return exec_ip6tables_cmd(block_buf, pid);
-}
-