Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

938 lines (764 sloc) 26.598 kb
/*
*****************************************************************************
*
* File: fw_util_ipfw.c
*
* Author: Damien S. Stuart
*
* Purpose: Fwknop routines for managing ipfw firewall rules.
*
* Copyright 2010-2013 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#include "fwknopd_common.h"
#if FIREWALL_IPFW
#include "fw_util.h"
#include "utils.h"
#include "log_msg.h"
#include "extcmd.h"
#include "access.h"
static struct fw_config fwc;
static char cmd_buf[CMD_BUFSIZE];
static char err_buf[CMD_BUFSIZE];
static char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
static unsigned short
get_next_rule_num(void)
{
unsigned short i;
for(i=0; i < fwc.max_rules; i++)
{
if(fwc.rule_map[i] == RULE_FREE)
return(fwc.start_rule_num + i);
}
return(0);
}
static void
zero_cmd_buffers(void)
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
memset(err_buf, 0x0, CMD_BUFSIZE);
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
}
static int
ipfw_set_exists(const fko_srv_options_t *opts,
const char *fw_command, const unsigned short set_num)
{
int res = 0;
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_SET_RULES_ARGS,
fw_command,
set_num
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "ipfw_set_exists() CMD: '%s' (res: %d)",
cmd_buf, res);
if(!EXTCMD_IS_SUCCESS(res))
return(0);
if(cmd_out[0] == '\0')
return(0);
return(1);
}
/* Print all firewall rules currently instantiated by the running fwknopd
* daemon to stdout.
*/
int
fw_dump_rules(const fko_srv_options_t * const opts)
{
int res, got_err = 0;
if (opts->fw_list_all)
{
fprintf(stdout, "Listing all ipfw rules...\n");
fflush(stdout);
zero_cmd_buffers();
/* Create the list command for all rules
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_ALL_RULES_ARGS,
opts->fw_config->fw_command
);
res = system(cmd_buf);
if (opts->verbose)
log_msg(LOG_INFO, "fw_dump_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
got_err++;
}
}
else
{
fprintf(stdout, "Listing fwknopd ipfw rules...\n");
fflush(stdout);
zero_cmd_buffers();
/* Create the list command for active rules
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_RULES_ARGS,
opts->fw_config->fw_command,
opts->fw_config->active_set_num
);
printf("\nActive Rules:\n");
res = system(cmd_buf);
if (opts->verbose)
log_msg(LOG_INFO, "fw_dump_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
got_err++;
}
/* Create the list command for expired rules
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_RULES_ARGS,
opts->fw_config->fw_command,
opts->fw_config->expire_set_num
);
printf("\nExpired Rules:\n");
res = system(cmd_buf);
if (opts->verbose)
log_msg(LOG_INFO, "fw_dump_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
got_err++;
}
}
return(got_err);
}
void
fw_config_init(fko_srv_options_t * const opts)
{
int is_err;
memset(&fwc, 0x0, sizeof(struct fw_config));
/* Set our firewall exe command path (iptables in most cases).
*/
strlcpy(fwc.fw_command, opts->config[CONF_FIREWALL_EXE], sizeof(fwc.fw_command));
fwc.start_rule_num = strtol_wrapper(opts->config[CONF_IPFW_START_RULE_NUM],
0, RCHK_MAX_IPFW_MAX_RULES, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
fprintf(stderr, "[*] IPFW_START_RULE_NUM '%s' out of range [%d-%d].\n",
opts->config[CONF_IPFW_START_RULE_NUM], 0, RCHK_MAX_IPFW_MAX_RULES);
exit(EXIT_FAILURE);
}
fwc.max_rules = strtol_wrapper(opts->config[CONF_IPFW_MAX_RULES],
0, RCHK_MAX_IPFW_MAX_RULES, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
fprintf(stderr, "[*] IPFW_MAX_RULES_INT '%s' out of range [%d-%d].\n",
opts->config[CONF_IPFW_MAX_RULES], 0, RCHK_MAX_IPFW_MAX_RULES);
exit(EXIT_FAILURE);
}
fwc.active_set_num = strtol_wrapper(opts->config[CONF_IPFW_ACTIVE_SET_NUM],
0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
fprintf(stderr, "[*] IPFW_ACTIVE_SET_NUM '%s' out of range [%d-%d].\n",
opts->config[CONF_IPFW_ACTIVE_SET_NUM], 0, RCHK_MAX_IPFW_SET_NUM);
exit(EXIT_FAILURE);
}
fwc.expire_set_num = strtol_wrapper(opts->config[CONF_IPFW_EXPIRE_SET_NUM],
0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
fprintf(stderr, "[*] IPFW_MAX_EXPIRE_SET_NUM '%s' out of range [%d-%d].\n",
opts->config[CONF_IPFW_EXPIRE_SET_NUM], 0, RCHK_MAX_IPFW_SET_NUM);
exit(EXIT_FAILURE);
}
fwc.purge_interval = strtol_wrapper(opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL],
0, RCHK_MAX_IPFW_PURGE_INTERVAL, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
fprintf(stderr, "[*] IPFW_EXPIRE_PURGE_INTERVAL '%s' out of range [%d-%d].\n",
opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL], 0,
RCHK_MAX_IPFW_PURGE_INTERVAL);
exit(EXIT_FAILURE);
}
/* Let us find it via our opts struct as well.
*/
opts->fw_config = &fwc;
return;
}
void
fw_initialize(const fko_srv_options_t * const opts)
{
int res = 0, is_err;
unsigned short curr_rule;
char *ndx;
/* For now, we just call fw_cleanup to start with clean slate.
*/
if(strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_INIT], "Y", 1) == 0)
res = fw_cleanup(opts);
if(res != 0)
{
fprintf(stderr, "Fatal: Errors detected during ipfw rules initialization.\n");
exit(EXIT_FAILURE);
}
/* Allocate our rule_map array for tracking active (and expired) rules.
*/
fwc.rule_map = calloc(fwc.max_rules, sizeof(char));
if(fwc.rule_map == NULL)
{
fprintf(stderr, "Fatal: Memory allocation error in fw_initialize.\n");
exit(EXIT_FAILURE);
}
/* Create a check-state rule if necessary.
*/
if(strncasecmp(opts->config[CONF_IPFW_ADD_CHECK_STATE], "Y", 1) == 0)
{
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_ADD_CHECK_STATE_ARGS,
fwc.fw_command,
fwc.start_rule_num,
fwc.active_set_num
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "fw_initialize() CMD: '%s' (res: %d, err: %s)",
cmd_buf, res, err_buf);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added check-state rule %u to set %u",
fwc.start_rule_num,
fwc.active_set_num
);
fwc.rule_map[0] = RULE_ACTIVE;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
}
if(fwc.expire_set_num > 0
&& (strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_INIT], "Y", 1) == 0))
{
/* Make sure our expire set is disabled.
*/
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DISABLE_SET_ARGS,
fwc.fw_command,
fwc.expire_set_num
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "fw_initialize() CMD: '%s' (res: %d, err: %s)",
cmd_buf, res, err_buf);
if(EXTCMD_IS_SUCCESS(res))
log_msg(LOG_INFO, "Set ipfw expire set %u to disabled.",
fwc.expire_set_num);
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
}
/* Now read the expire set in case there are existing
* rules to track.
*/
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_EXP_SET_RULES_ARGS,
opts->fw_config->fw_command,
fwc.expire_set_num
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "fw_initialize() CMD: '%s' (res: %d)",
cmd_buf, res);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
return;
}
if(opts->verbose > 1)
log_msg(LOG_INFO, "RULES LIST: %s", cmd_out);
/* Find the first "# DISABLED" string (if any).
*/
ndx = strstr(cmd_out, "# DISABLED ");
/* Assume no disabled rules if we did not see the string.
*/
if(ndx == NULL)
return;
/* Otherwise we walk each line to pull the rule number and
* set the appropriate rule map entries.
*/
while(ndx != NULL)
{
/* Skip over the DISABLED string to the rule num.
*/
ndx += 11;
if(isdigit(*ndx))
{
curr_rule = strtol_wrapper(ndx, 0, -1, NO_EXIT_UPON_ERR, &is_err);
if(is_err == FKO_SUCCESS)
{
if(curr_rule >= fwc.start_rule_num
&& curr_rule < fwc.start_rule_num + fwc.max_rules)
{
fwc.rule_map[curr_rule - fwc.start_rule_num] = RULE_EXPIRED;
fwc.total_rules++;
}
}
}
else
log_msg(LOG_WARNING, "fw_initialize: No rule number found where expected.");
/* Find the next "# DISABLED" string (if any).
*/
ndx = strstr(ndx, "# DISABLED ");
}
}
int
fw_cleanup(const fko_srv_options_t * const opts)
{
int res, got_err = 0;
if(strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_EXIT], "N", 1) == 0)
{
if(fwc.rule_map != NULL)
free(fwc.rule_map);
return(0);
}
zero_cmd_buffers();
if(fwc.active_set_num > 0
&& ipfw_set_exists(opts, fwc.fw_command, fwc.active_set_num))
{
/* Create the set delete command for active rules
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DEL_RULE_SET_ARGS,
fwc.fw_command,
fwc.active_set_num
);
res = system(cmd_buf);
if (opts->verbose)
log_msg(LOG_INFO, "fw_cleanup() CMD: '%s' (res: %d)",
cmd_buf, res);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
got_err++;
}
}
/* --DSS Keep expired rule list so any existing established
are not lost */
#if 0
if(fwc.expire_set_num > 0)
{
/* Create the set delete command for expired rules
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DEL_RULE_SET_ARGS,
fwc.fw_command,
fwc.expire_set_num
);
//printf("CMD: '%s'\n", cmd_buf);
res = system(cmd_buf);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
got_err++;
}
}
#endif
/* Free the rule map.
*/
if(fwc.rule_map != NULL)
free(fwc.rule_map);
return(got_err);
}
/****************************************************************************/
/* Rule Processing - Create an access request...
*/
int
process_spa_request(const fko_srv_options_t * const opts,
const acc_stanza_t * const acc, spa_data_t * const spadat)
{
unsigned short rule_num;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
int res = 0;
time_t now;
unsigned int exp_ts;
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
/* Start at the top of the proto-port list...
*/
ple = port_list;
/* Set our expire time value.
*/
time(&now);
exp_ts = now + spadat->fw_access_timeout;
/* For straight access requests, we currently support multiple proto/port
* request.
*/
if(spadat->message_type == FKO_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG)
{
/* Pull the next available rule number.
*/
rule_num = get_next_rule_num();
/* If rule_num comes back as 0, we aready have the maximum number
* of active rules allowed so we reject and bail here.
*/
if(rule_num == 0)
{
log_msg(LOG_WARNING, "Access request rejected: Maximum allowed number of rules has been reached.");
free_acc_port_list(port_list);
return(-1);
}
/* Create an access command for each proto/port for the source ip.
*/
while(ple != NULL)
{
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_ADD_RULE_ARGS,
fwc.fw_command,
rule_num,
fwc.active_set_num,
ple->proto,
spadat->use_src_ip,
ple->port,
exp_ts
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "process_spa_request() CMD: '%s' (res: %d, err: %s)",
cmd_buf, res, err_buf);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Rule %u for %s, %s expires at %u",
rule_num,
spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
fwc.rule_map[rule_num - fwc.start_rule_num] = RULE_ACTIVE;
fwc.active_rules++;
fwc.total_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(fwc.next_expire < now || exp_ts < fwc.next_expire)
fwc.next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
ple = ple->next;
}
}
else
{
/* No other SPA request modes are supported yet.
*/
if(spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
{
log_msg(LOG_WARNING, "Local NAT requests are not currently supported.");
}
else if(spadat->message_type == FKO_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG)
{
log_msg(LOG_WARNING, "Forwarding/NAT requests are not currently supported.");
}
free_acc_port_list(port_list);
return(-1);
}
free_acc_port_list(port_list);
return(res);
}
/* Iterate over the current rule set and purge expired
* firewall rules.
*/
void
check_firewall_rules(const fko_srv_options_t * const opts)
{
char exp_str[12] = {0};
char rule_num_str[6] = {0};
char *ndx, *rn_start, *rn_end, *tmp_mark;
int i=0, res=0, is_err;
time_t now, rule_exp, min_exp = 0;
unsigned short curr_rule;
/* Just in case we somehow lose track and fall out-of-whack.
*/
if(fwc.active_rules > fwc.max_rules)
fwc.active_rules = 0;
/* If there are no active rules or we have not yet
* reached our expected next expire time, continue.
*/
if(fwc.active_rules == 0)
return;
time(&now);
if (fwc.next_expire > now)
return;
zero_cmd_buffers();
/* There should be a rule to delete. Get the current list of
* rules for this chain and delete the ones that are expired.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_SET_RULES_ARGS,
opts->fw_config->fw_command,
fwc.active_set_num
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "check_firewall_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
return;
}
if(opts->verbose > 1)
log_msg(LOG_INFO, "RULES LIST: %s", cmd_out);
/* Find the first _exp_ string (if any).
*/
ndx = strstr(cmd_out, EXPIRE_COMMENT_PREFIX);
if(ndx == NULL)
{
/* we did not find an expected rule.
*/
log_msg(LOG_ERR,
"Did not find expire comment in rules list %i.\n", i);
if (fwc.active_rules > 0)
fwc.active_rules--;
return;
}
/* Walk the list and process rules as needed.
*/
while (ndx != NULL) {
/* Jump forward and extract the timestamp
*/
ndx += strlen(EXPIRE_COMMENT_PREFIX);
/* remember this spot for when we look for the next
* rule.
*/
tmp_mark = ndx;
strlcpy(exp_str, ndx, sizeof(exp_str));
rule_exp = (time_t)atoll(exp_str);
if(rule_exp <= now)
{
/* Backtrack and get the rule number and delete it.
*/
rn_start = ndx;
while(--rn_start > cmd_out)
{
if(*rn_start == '\n')
break;
}
if(*rn_start == '\n')
{
rn_start++;
}
else if(rn_start > cmd_out)
{
/* This should not happen. But if it does, complain,
* decrement the active rule value, and go on.
*/
log_msg(LOG_ERR,
"Rule parse error while finding rule line start.");
if (fwc.active_rules > 0)
fwc.active_rules--;
break;
}
rn_end = strchr(rn_start, ' ');
if(rn_end == NULL)
{
/* This should not happen. But if it does, complain,
* decrement the active rule value, and go on.
*/
log_msg(LOG_ERR,
"Rule parse error while finding rule number.");
if (fwc.active_rules > 0)
fwc.active_rules--;
break;
}
strlcpy(rule_num_str, rn_start, (rn_end - rn_start)+1);
curr_rule = strtol_wrapper(rule_num_str, 0, -1, NO_EXIT_UPON_ERR, &is_err);
if(is_err == FKO_SUCCESS)
{
zero_cmd_buffers();
/* Move the rule to the expired rules set.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_MOVE_RULE_ARGS,
opts->fw_config->fw_command,
curr_rule,
fwc.expire_set_num
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "check_firewall_rules() CMD: '%s' (res: %d, err: %s)",
cmd_buf, res, err_buf);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Moved rule %s with expire time of %u to set %u.",
rule_num_str, rule_exp, fwc.expire_set_num
);
if (fwc.active_rules > 0)
fwc.active_rules--;
fwc.rule_map[curr_rule - fwc.start_rule_num] = RULE_EXPIRED;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
}
else
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
}
}
else
{
/* Track the minimum future rule expire time.
*/
if(rule_exp > now)
min_exp = (min_exp < rule_exp) ? min_exp : rule_exp;
}
/* Push our tracking index forward beyond (just processed) _exp_
* string so we can continue to the next rule in the list.
*/
ndx = strstr(tmp_mark, EXPIRE_COMMENT_PREFIX);
}
/* Set the next pending expire time accordingly. 0 if there are no
* more rules, or whatever the next expected (min_exp) time will be.
*/
if(fwc.active_rules < 1)
fwc.next_expire = 0;
else if(min_exp)
fwc.next_expire = min_exp;
}
/* Iterate over the expired rule set and purge those that no longer have
* corresponding dynamic rules.
*/
void
ipfw_purge_expired_rules(const fko_srv_options_t *opts)
{
char *ndx, *co_end;
int i, res, is_err;
unsigned short curr_rule;
/* First, we get the current active dynamic rules for the expired rule
* set. Then we compare it to the expired rules in the rule_map. Any
* rules in the map that do not have a dynamic rule, can be deleted.
*/
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_LIST_SET_DYN_RULES_ARGS,
opts->fw_config->fw_command,
fwc.expire_set_num
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "ipfw_purge_expired_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
return;
}
/* We may not have any dynamic rules at all - someone might not have
* initiated a connection (for example)
*/
if (cmd_out[0] != '\0')
{
co_end = cmd_out + strlen(cmd_out);
if(opts->verbose > 1)
log_msg(LOG_INFO, "EXP RULES LIST: %s", cmd_out);
/* Find the "## Dynamic rules" string.
*/
ndx = strcasestr(cmd_out, "## Dynamic rules");
if(ndx == NULL)
{
log_msg(LOG_ERR,
"Unexpected error: did not find 'Dynamic rules' string in list output."
);
return;
}
/* Jump to the next newline char.
*/
ndx = strchr(ndx, '\n');
if(ndx == NULL)
{
log_msg(LOG_ERR,
"Unexpected error: did not find 'Dynamic rules' line terminating newline."
);
return;
}
/* Walk the list of dynamic rules (if any).
*/
while(ndx != NULL)
{
ndx++;
while(!isdigit(*ndx) && ndx < co_end)
ndx++;
if(ndx >= co_end)
break;
/* If we are at a digit, assume it is a rule number, extract it,
* and if it falls in the correct range, mark it (so it is not
* removed in the next step.
*/
if(isdigit(*ndx))
{
curr_rule = strtol_wrapper(ndx, 0, -1, NO_EXIT_UPON_ERR, &is_err);
if(is_err == FKO_SUCCESS)
{
if(curr_rule >= fwc.start_rule_num
&& curr_rule < fwc.start_rule_num + fwc.max_rules)
fwc.rule_map[curr_rule - fwc.start_rule_num] = RULE_TMP_MARKED;
}
}
ndx = strchr(ndx, '\n');
}
}
/* Now, walk the rule map and remove any still marked as expired.
*/
for(i=0; i<fwc.max_rules; i++)
{
/* If it is TMP_MARKED, set it back to EXPIRED and move on.
*/
if(fwc.rule_map[i] == RULE_TMP_MARKED)
{
fwc.rule_map[i] = RULE_EXPIRED;
continue;
}
/* If it is not expired, move on.
*/
if(fwc.rule_map[i] != RULE_EXPIRED)
continue;
/* This rule is ready to go away.
*/
zero_cmd_buffers();
curr_rule = fwc.start_rule_num + i;
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DEL_RULE_ARGS,
opts->fw_config->fw_command,
#ifndef __APPLE__
fwc.expire_set_num,
#endif
curr_rule
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if (opts->verbose)
log_msg(LOG_INFO, "ipfw_purge_expired_rules() CMD: '%s' (res: %d)",
cmd_buf, res);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
continue;
}
log_msg(LOG_INFO, "Purged rule %u from set %u", curr_rule, fwc.expire_set_num);
fwc.rule_map[curr_rule - fwc.start_rule_num] = RULE_FREE;
fwc.total_rules--;
}
}
#endif /* FIREWALL_IPFW */
/***EOF***/
Jump to Line
Something went wrong with that request. Please try again.