|
Packit Service |
d1fe03 |
#include <config.h>
|
|
Packit Service |
d1fe03 |
#include <ctype.h>
|
|
Packit Service |
d1fe03 |
#include <getopt.h>
|
|
Packit Service |
d1fe03 |
#include <errno.h>
|
|
Packit Service |
d1fe03 |
#include <libgen.h>
|
|
Packit Service |
d1fe03 |
#include <netdb.h>
|
|
Packit Service |
d1fe03 |
#include <stdbool.h>
|
|
Packit Service |
d1fe03 |
#include <stdint.h>
|
|
Packit Service |
d1fe03 |
#include <stdio.h>
|
|
Packit Service |
d1fe03 |
#include <stdlib.h>
|
|
Packit Service |
d1fe03 |
#include <string.h>
|
|
Packit Service |
d1fe03 |
#include <sys/file.h>
|
|
Packit Service |
d1fe03 |
#include <sys/socket.h>
|
|
Packit Service |
d1fe03 |
#include <sys/un.h>
|
|
Packit Service |
d1fe03 |
#include <sys/time.h>
|
|
Packit Service |
d1fe03 |
#include <unistd.h>
|
|
Packit Service |
d1fe03 |
#include <fcntl.h>
|
|
Packit Service |
d1fe03 |
#include <xtables.h>
|
|
Packit Service |
d1fe03 |
#include <math.h>
|
|
Packit Service |
d1fe03 |
#include "xshared.h"
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/*
|
|
Packit Service |
d1fe03 |
* Print out any special helps. A user might like to be able to add a --help
|
|
Packit Service |
d1fe03 |
* to the commandline, and see expected results. So we call help for all
|
|
Packit Service |
d1fe03 |
* specified matches and targets.
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
void print_extension_helps(const struct xtables_target *t,
|
|
Packit Service |
d1fe03 |
const struct xtables_rule_match *m)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
for (; t != NULL; t = t->next) {
|
|
Packit Service |
d1fe03 |
if (t->used) {
|
|
Packit Service |
d1fe03 |
printf("\n");
|
|
Packit Service |
d1fe03 |
if (t->help == NULL)
|
|
Packit Service |
d1fe03 |
printf("%s does not take any options\n",
|
|
Packit Service |
d1fe03 |
t->name);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
t->help();
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
for (; m != NULL; m = m->next) {
|
|
Packit Service |
d1fe03 |
printf("\n");
|
|
Packit Service |
d1fe03 |
if (m->match->help == NULL)
|
|
Packit Service |
d1fe03 |
printf("%s does not take any options\n",
|
|
Packit Service |
d1fe03 |
m->match->name);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
m->match->help();
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
const char *
|
|
Packit Service |
d1fe03 |
proto_to_name(uint8_t proto, int nolookup)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
unsigned int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (proto && !nolookup) {
|
|
Packit Service |
d1fe03 |
struct protoent *pent = getprotobynumber(proto);
|
|
Packit Service |
d1fe03 |
if (pent)
|
|
Packit Service |
d1fe03 |
return pent->p_name;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; xtables_chain_protos[i].name != NULL; ++i)
|
|
Packit Service |
d1fe03 |
if (xtables_chain_protos[i].num == proto)
|
|
Packit Service |
d1fe03 |
return xtables_chain_protos[i].name;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static struct xtables_match *
|
|
Packit Service |
d1fe03 |
find_proto(const char *pname, enum xtables_tryload tryload,
|
|
Packit Service |
d1fe03 |
int nolookup, struct xtables_rule_match **matches)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
unsigned int proto;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) {
|
|
Packit Service |
d1fe03 |
const char *protoname = proto_to_name(proto, nolookup);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (protoname)
|
|
Packit Service |
d1fe03 |
return xtables_find_match(protoname, tryload, matches);
|
|
Packit Service |
d1fe03 |
} else
|
|
Packit Service |
d1fe03 |
return xtables_find_match(pname, tryload, matches);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/*
|
|
Packit Service |
d1fe03 |
* Some explanations (after four different bugs in 3 different releases): If
|
|
Packit Service |
d1fe03 |
* we encounter a parameter, that has not been parsed yet, it's not an option
|
|
Packit Service |
d1fe03 |
* of an explicitly loaded match or a target. However, we support implicit
|
|
Packit Service |
d1fe03 |
* loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at
|
|
Packit Service |
d1fe03 |
* the same time 'load tcp protocol match on demand if we specify --dport'.
|
|
Packit Service |
d1fe03 |
*
|
|
Packit Service |
d1fe03 |
* To make this work, we need to make sure:
|
|
Packit Service |
d1fe03 |
* - the parameter has not been parsed by a match (m above)
|
|
Packit Service |
d1fe03 |
* - a protocol has been specified
|
|
Packit Service |
d1fe03 |
* - the protocol extension has not been loaded yet, or is loaded and unused
|
|
Packit Service |
d1fe03 |
* [think of ip6tables-restore!]
|
|
Packit Service |
d1fe03 |
* - the protocol extension can be successively loaded
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
static bool should_load_proto(struct iptables_command_state *cs)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (cs->protocol == NULL)
|
|
Packit Service |
d1fe03 |
return false;
|
|
Packit Service |
d1fe03 |
if (find_proto(cs->protocol, XTF_DONT_LOAD,
|
|
Packit Service |
d1fe03 |
cs->options & OPT_NUMERIC, NULL) == NULL)
|
|
Packit Service |
d1fe03 |
return true;
|
|
Packit Service |
d1fe03 |
return !cs->proto_used;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
struct xtables_match *load_proto(struct iptables_command_state *cs)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (!should_load_proto(cs))
|
|
Packit Service |
d1fe03 |
return NULL;
|
|
Packit Service |
d1fe03 |
return find_proto(cs->protocol, XTF_TRY_LOAD,
|
|
Packit Service |
d1fe03 |
cs->options & OPT_NUMERIC, &cs->matches);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
int command_default(struct iptables_command_state *cs,
|
|
Packit Service |
d1fe03 |
struct xtables_globals *gl)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct xtables_rule_match *matchp;
|
|
Packit Service |
d1fe03 |
struct xtables_match *m;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->target != NULL &&
|
|
Packit Service |
d1fe03 |
(cs->target->parse != NULL || cs->target->x6_parse != NULL) &&
|
|
Packit Service |
d1fe03 |
cs->c >= cs->target->option_offset &&
|
|
Packit Service |
d1fe03 |
cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) {
|
|
Packit Service |
d1fe03 |
xtables_option_tpcall(cs->c, cs->argv, cs->invert,
|
|
Packit Service |
d1fe03 |
cs->target, &cs->fw);
|
|
Packit Service |
d1fe03 |
return 0;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (matchp = cs->matches; matchp; matchp = matchp->next) {
|
|
Packit Service |
d1fe03 |
m = matchp->match;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (matchp->completed ||
|
|
Packit Service |
d1fe03 |
(m->x6_parse == NULL && m->parse == NULL))
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
if (cs->c < matchp->match->option_offset ||
|
|
Packit Service |
d1fe03 |
cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE)
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw);
|
|
Packit Service |
d1fe03 |
return 0;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Try loading protocol */
|
|
Packit Service |
d1fe03 |
m = load_proto(cs);
|
|
Packit Service |
d1fe03 |
if (m != NULL) {
|
|
Packit Service |
d1fe03 |
size_t size;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
cs->proto_used = 1;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
m->m = xtables_calloc(1, size);
|
|
Packit Service |
d1fe03 |
m->m->u.match_size = size;
|
|
Packit Service |
d1fe03 |
strcpy(m->m->u.user.name, m->name);
|
|
Packit Service |
d1fe03 |
m->m->u.user.revision = m->revision;
|
|
Packit Service |
d1fe03 |
xs_init_match(m);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (m->x6_options != NULL)
|
|
Packit Service |
d1fe03 |
gl->opts = xtables_options_xfrm(gl->orig_opts,
|
|
Packit Service |
d1fe03 |
gl->opts,
|
|
Packit Service |
d1fe03 |
m->x6_options,
|
|
Packit Service |
d1fe03 |
&m->option_offset);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
gl->opts = xtables_merge_options(gl->orig_opts,
|
|
Packit Service |
d1fe03 |
gl->opts,
|
|
Packit Service |
d1fe03 |
m->extra_opts,
|
|
Packit Service |
d1fe03 |
&m->option_offset);
|
|
Packit Service |
d1fe03 |
if (gl->opts == NULL)
|
|
Packit Service |
d1fe03 |
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
|
|
Packit Service |
d1fe03 |
optind--;
|
|
Packit Service |
d1fe03 |
/* Indicate to rerun getopt *immediately* */
|
|
Packit Service |
d1fe03 |
return 1;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->c == ':')
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
|
|
Packit Service |
d1fe03 |
"requires an argument", cs->argv[optind-1]);
|
|
Packit Service |
d1fe03 |
if (cs->c == '?')
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "unknown option "
|
|
Packit Service |
d1fe03 |
"\"%s\"", cs->argv[optind-1]);
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
for (; cb->name != NULL; ++cb)
|
|
Packit Service |
d1fe03 |
if (strcmp(cb->name, cmd) == 0)
|
|
Packit Service |
d1fe03 |
return cb->main;
|
|
Packit Service |
d1fe03 |
return NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
int subcmd_main(int argc, char **argv, const struct subcommand *cb)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const char *cmd = basename(*argv);
|
|
Packit Service |
d1fe03 |
mainfunc_t f = subcmd_get(cmd, cb);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (f == NULL && argc > 1) {
|
|
Packit Service |
d1fe03 |
/*
|
|
Packit Service |
d1fe03 |
* Unable to find a main method for our command name?
|
|
Packit Service |
d1fe03 |
* Let's try again with the first argument!
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
++argv;
|
|
Packit Service |
d1fe03 |
--argc;
|
|
Packit Service |
d1fe03 |
f = subcmd_get(*argv, cb);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* now we should have a valid function pointer */
|
|
Packit Service |
d1fe03 |
if (f != NULL)
|
|
Packit Service |
d1fe03 |
return f(argc, argv);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "ERROR: No valid subcommand given.\nValid subcommands:\n");
|
|
Packit Service |
d1fe03 |
for (; cb->name != NULL; ++cb)
|
|
Packit Service |
d1fe03 |
fprintf(stderr, " * %s\n", cb->name);
|
|
Packit Service |
d1fe03 |
exit(EXIT_FAILURE);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void xs_init_target(struct xtables_target *target)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (target->udata_size != 0) {
|
|
Packit Service |
d1fe03 |
free(target->udata);
|
|
Packit Service |
d1fe03 |
target->udata = calloc(1, target->udata_size);
|
|
Packit Service |
d1fe03 |
if (target->udata == NULL)
|
|
Packit Service |
d1fe03 |
xtables_error(RESOURCE_PROBLEM, "malloc");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
if (target->init != NULL)
|
|
Packit Service |
d1fe03 |
target->init(target->t);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void xs_init_match(struct xtables_match *match)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (match->udata_size != 0) {
|
|
Packit Service |
d1fe03 |
/*
|
|
Packit Service |
d1fe03 |
* As soon as a subsequent instance of the same match
|
|
Packit Service |
d1fe03 |
* is used, e.g. "-m time -m time", the first instance
|
|
Packit Service |
d1fe03 |
* is no longer reachable anyway, so we can free udata.
|
|
Packit Service |
d1fe03 |
* Same goes for target.
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
free(match->udata);
|
|
Packit Service |
d1fe03 |
match->udata = calloc(1, match->udata_size);
|
|
Packit Service |
d1fe03 |
if (match->udata == NULL)
|
|
Packit Service |
d1fe03 |
xtables_error(RESOURCE_PROBLEM, "malloc");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
if (match->init != NULL)
|
|
Packit Service |
d1fe03 |
match->init(match->m);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static int xtables_lock(int wait, struct timeval *wait_interval)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct timeval time_left, wait_time;
|
|
Packit Service |
d1fe03 |
int fd, i = 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
time_left.tv_sec = wait;
|
|
Packit Service |
d1fe03 |
time_left.tv_usec = 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fd = open(XT_LOCK_NAME, O_CREAT, 0600);
|
|
Packit Service |
d1fe03 |
if (fd < 0) {
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Fatal: can't open lock file %s: %s\n",
|
|
Packit Service |
d1fe03 |
XT_LOCK_NAME, strerror(errno));
|
|
Packit Service |
d1fe03 |
return XT_LOCK_FAILED;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (wait == -1) {
|
|
Packit Service |
d1fe03 |
if (flock(fd, LOCK_EX) == 0)
|
|
Packit Service |
d1fe03 |
return fd;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME,
|
|
Packit Service |
d1fe03 |
strerror(errno));
|
|
Packit Service |
d1fe03 |
return XT_LOCK_BUSY;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
while (1) {
|
|
Packit Service |
d1fe03 |
if (flock(fd, LOCK_EX | LOCK_NB) == 0)
|
|
Packit Service |
d1fe03 |
return fd;
|
|
Packit Service |
d1fe03 |
else if (timercmp(&time_left, wait_interval, <))
|
|
Packit Service |
d1fe03 |
return XT_LOCK_BUSY;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (++i % 10 == 0) {
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Another app is currently holding the xtables lock; "
|
|
Packit Service |
d1fe03 |
"still %lds %ldus time ahead to have a chance to grab the lock...\n",
|
|
Packit Service |
d1fe03 |
time_left.tv_sec, time_left.tv_usec);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
wait_time = *wait_interval;
|
|
Packit Service |
d1fe03 |
select(0, NULL, NULL, NULL, &wait_time);
|
|
Packit Service |
d1fe03 |
timersub(&time_left, wait_interval, &time_left);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void xtables_unlock(int lock)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (lock >= 0)
|
|
Packit Service |
d1fe03 |
close(lock);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
int xtables_lock_or_exit(int wait, struct timeval *wait_interval)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int lock = xtables_lock(wait, wait_interval);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (lock == XT_LOCK_FAILED) {
|
|
Packit Service |
d1fe03 |
xtables_free_opts(1);
|
|
Packit Service |
d1fe03 |
exit(RESOURCE_PROBLEM);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (lock == XT_LOCK_BUSY) {
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Another app is currently holding the xtables lock. ");
|
|
Packit Service |
d1fe03 |
if (wait == 0)
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Perhaps you want to use the -w option?\n");
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Stopped waiting after %ds.\n", wait);
|
|
Packit Service |
d1fe03 |
xtables_free_opts(1);
|
|
Packit Service |
d1fe03 |
exit(RESOURCE_PROBLEM);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return lock;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
int parse_wait_time(int argc, char *argv[])
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int wait = -1;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (optarg) {
|
|
Packit Service |
d1fe03 |
if (sscanf(optarg, "%i", &wait) != 1)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"wait seconds not numeric");
|
|
Packit Service |
d1fe03 |
} else if (xs_has_arg(argc, argv))
|
|
Packit Service |
d1fe03 |
if (sscanf(argv[optind++], "%i", &wait) != 1)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"wait seconds not numeric");
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return wait;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const char *arg;
|
|
Packit Service |
d1fe03 |
unsigned int usec;
|
|
Packit Service |
d1fe03 |
int ret;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (optarg)
|
|
Packit Service |
d1fe03 |
arg = optarg;
|
|
Packit Service |
d1fe03 |
else if (xs_has_arg(argc, argv))
|
|
Packit Service |
d1fe03 |
arg = argv[optind++];
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "wait interval value required");
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
ret = sscanf(arg, "%u", &usec);
|
|
Packit Service |
d1fe03 |
if (ret == 1) {
|
|
Packit Service |
d1fe03 |
if (usec > 999999)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"too long usec wait %u > 999999 usec",
|
|
Packit Service |
d1fe03 |
usec);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
wait_interval->tv_sec = 0;
|
|
Packit Service |
d1fe03 |
wait_interval->tv_usec = usec;
|
|
Packit Service |
d1fe03 |
return;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "wait interval not numeric");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
int parse_counters(const char *string, struct xt_counters *ctr)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int ret;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!string)
|
|
Packit Service |
d1fe03 |
return 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
ret = sscanf(string, "[%llu:%llu]",
|
|
Packit Service |
d1fe03 |
(unsigned long long *)&ctr->pcnt,
|
|
Packit Service |
d1fe03 |
(unsigned long long *)&ctr->bcnt);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return ret == 2;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Tokenize counters argument of typical iptables-restore format rule.
|
|
Packit Service |
d1fe03 |
*
|
|
Packit Service |
d1fe03 |
* If *bufferp contains counters, update *pcntp and *bcntp to point at them,
|
|
Packit Service |
d1fe03 |
* change bytes after counters in *bufferp to nul-bytes, update *bufferp to
|
|
Packit Service |
d1fe03 |
* point to after the counters and return true.
|
|
Packit Service |
d1fe03 |
* If *bufferp does not contain counters, return false.
|
|
Packit Service |
d1fe03 |
* If syntax is wrong in *bufferp, call xtables_error() and hence exit().
|
|
Packit Service |
d1fe03 |
* */
|
|
Packit Service |
d1fe03 |
bool tokenize_rule_counters(char **bufferp, char **pcntp, char **bcntp, int line)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
char *ptr, *buffer = *bufferp, *pcnt, *bcnt;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (buffer[0] != '[')
|
|
Packit Service |
d1fe03 |
return false;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* we have counters in our input */
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
ptr = strchr(buffer, ']');
|
|
Packit Service |
d1fe03 |
if (!ptr)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
pcnt = strtok(buffer+1, ":");
|
|
Packit Service |
d1fe03 |
if (!pcnt)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need :\n", line);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
bcnt = strtok(NULL, "]");
|
|
Packit Service |
d1fe03 |
if (!bcnt)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
*pcntp = pcnt;
|
|
Packit Service |
d1fe03 |
*bcntp = bcnt;
|
|
Packit Service |
d1fe03 |
/* start command parsing after counter */
|
|
Packit Service |
d1fe03 |
*bufferp = ptr + 1;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return true;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
inline bool xs_has_arg(int argc, char *argv[])
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
return optind < argc &&
|
|
Packit Service |
d1fe03 |
argv[optind][0] != '-' &&
|
|
Packit Service |
d1fe03 |
argv[optind][0] != '!';
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* function adding one argument to store, updating argc
|
|
Packit Service |
d1fe03 |
* returns if argument added, does not return otherwise */
|
|
Packit Service |
d1fe03 |
void add_argv(struct argv_store *store, const char *what, int quoted)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
DEBUGP("add_argv: %s\n", what);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (store->argc + 1 >= MAX_ARGC)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Parser cannot handle more arguments\n");
|
|
Packit Service |
d1fe03 |
if (!what)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Trying to store NULL argument\n");
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
store->argv[store->argc] = strdup(what);
|
|
Packit Service |
d1fe03 |
store->argvattr[store->argc] = quoted;
|
|
Packit Service |
d1fe03 |
store->argv[++store->argc] = NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void free_argv(struct argv_store *store)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
while (store->argc) {
|
|
Packit Service |
d1fe03 |
store->argc--;
|
|
Packit Service |
d1fe03 |
free(store->argv[store->argc]);
|
|
Packit Service |
d1fe03 |
store->argvattr[store->argc] = 0;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Save parsed rule for comparison with next rule to perform action aggregation
|
|
Packit Service |
d1fe03 |
* on duplicate conditions.
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
void save_argv(struct argv_store *dst, struct argv_store *src)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
free_argv(dst);
|
|
Packit Service |
d1fe03 |
for (i = 0; i < src->argc; i++) {
|
|
Packit Service |
d1fe03 |
dst->argvattr[i] = src->argvattr[i];
|
|
Packit Service |
d1fe03 |
dst->argv[i] = src->argv[i];
|
|
Packit Service |
d1fe03 |
src->argv[i] = NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
dst->argc = src->argc;
|
|
Packit Service |
d1fe03 |
src->argc = 0;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
struct xt_param_buf {
|
|
Packit Service |
d1fe03 |
char buffer[1024];
|
|
Packit Service |
d1fe03 |
int len;
|
|
Packit Service |
d1fe03 |
};
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void add_param(struct xt_param_buf *param, const char *curchar)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
param->buffer[param->len++] = *curchar;
|
|
Packit Service |
d1fe03 |
if (param->len >= sizeof(param->buffer))
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Parameter too long!");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void add_param_to_argv(struct argv_store *store, char *parsestart, int line)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int quote_open = 0, escaped = 0, quoted = 0;
|
|
Packit Service |
d1fe03 |
struct xt_param_buf param = {};
|
|
Packit Service |
d1fe03 |
char *curchar;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* After fighting with strtok enough, here's now
|
|
Packit Service |
d1fe03 |
* a 'real' parser. According to Rusty I'm now no
|
|
Packit Service |
d1fe03 |
* longer a real hacker, but I can live with that */
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (curchar = parsestart; *curchar; curchar++) {
|
|
Packit Service |
d1fe03 |
if (quote_open) {
|
|
Packit Service |
d1fe03 |
if (escaped) {
|
|
Packit Service |
d1fe03 |
add_param(¶m, curchar);
|
|
Packit Service |
d1fe03 |
escaped = 0;
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
} else if (*curchar == '\\') {
|
|
Packit Service |
d1fe03 |
escaped = 1;
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
} else if (*curchar == '"') {
|
|
Packit Service |
d1fe03 |
quote_open = 0;
|
|
Packit Service |
d1fe03 |
*curchar = '"';
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
add_param(¶m, curchar);
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
if (*curchar == '"') {
|
|
Packit Service |
d1fe03 |
quote_open = 1;
|
|
Packit Service |
d1fe03 |
quoted = 1;
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
switch (*curchar) {
|
|
Packit Service |
d1fe03 |
case '"':
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
case ' ':
|
|
Packit Service |
d1fe03 |
case '\t':
|
|
Packit Service |
d1fe03 |
case '\n':
|
|
Packit Service |
d1fe03 |
if (!param.len) {
|
|
Packit Service |
d1fe03 |
/* two spaces? */
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
default:
|
|
Packit Service |
d1fe03 |
/* regular character, copy to buffer */
|
|
Packit Service |
d1fe03 |
add_param(¶m, curchar);
|
|
Packit Service |
d1fe03 |
continue;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
param.buffer[param.len] = '\0';
|
|
Packit Service |
d1fe03 |
add_argv(store, param.buffer, quoted);
|
|
Packit Service |
d1fe03 |
param.len = 0;
|
|
Packit Service |
d1fe03 |
quoted = 0;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
if (param.len) {
|
|
Packit Service |
d1fe03 |
param.buffer[param.len] = '\0';
|
|
Packit Service |
d1fe03 |
add_argv(store, param.buffer, 0);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
#ifdef DEBUG
|
|
Packit Service |
d1fe03 |
void debug_print_argv(struct argv_store *store)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; i < store->argc; i++)
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "argv[%d]: %s\n", i, store->argv[i]);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
#endif
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static const char *ipv4_addr_to_string(const struct in_addr *addr,
|
|
Packit Service |
d1fe03 |
const struct in_addr *mask,
|
|
Packit Service |
d1fe03 |
unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
static char buf[BUFSIZ];
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!mask->s_addr && !(format & FMT_NUMERIC))
|
|
Packit Service |
d1fe03 |
return "anywhere";
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC)
|
|
Packit Service |
d1fe03 |
strncpy(buf, xtables_ipaddr_to_numeric(addr), BUFSIZ - 1);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
strncpy(buf, xtables_ipaddr_to_anyname(addr), BUFSIZ - 1);
|
|
Packit Service |
d1fe03 |
buf[BUFSIZ - 1] = '\0';
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
strncat(buf, xtables_ipmask_to_numeric(mask),
|
|
Packit Service |
d1fe03 |
BUFSIZ - strlen(buf) - 1);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return buf;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void print_ipv4_addresses(const struct ipt_entry *fw, unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
|
|
Packit Service |
d1fe03 |
printf(FMT("%-19s ", "%s "),
|
|
Packit Service |
d1fe03 |
ipv4_addr_to_string(&fw->ip.src, &fw->ip.smsk, format));
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
|
|
Packit Service |
d1fe03 |
printf(FMT("%-19s ", "-> %s"),
|
|
Packit Service |
d1fe03 |
ipv4_addr_to_string(&fw->ip.dst, &fw->ip.dmsk, format));
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static const char *ipv6_addr_to_string(const struct in6_addr *addr,
|
|
Packit Service |
d1fe03 |
const struct in6_addr *mask,
|
|
Packit Service |
d1fe03 |
unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
static char buf[BUFSIZ];
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (IN6_IS_ADDR_UNSPECIFIED(addr) && !(format & FMT_NUMERIC))
|
|
Packit Service |
d1fe03 |
return "anywhere";
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC)
|
|
Packit Service |
d1fe03 |
strncpy(buf, xtables_ip6addr_to_numeric(addr), BUFSIZ - 1);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
strncpy(buf, xtables_ip6addr_to_anyname(addr), BUFSIZ - 1);
|
|
Packit Service |
d1fe03 |
buf[BUFSIZ - 1] = '\0';
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
strncat(buf, xtables_ip6mask_to_numeric(mask),
|
|
Packit Service |
d1fe03 |
BUFSIZ - strlen(buf) - 1);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return buf;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void print_ipv6_addresses(const struct ip6t_entry *fw6, unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
fputc(fw6->ipv6.invflags & IP6T_INV_SRCIP ? '!' : ' ', stdout);
|
|
Packit Service |
d1fe03 |
printf(FMT("%-19s ", "%s "),
|
|
Packit Service |
d1fe03 |
ipv6_addr_to_string(&fw6->ipv6.src,
|
|
Packit Service |
d1fe03 |
&fw6->ipv6.smsk, format));
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fputc(fw6->ipv6.invflags & IP6T_INV_DSTIP ? '!' : ' ', stdout);
|
|
Packit Service |
d1fe03 |
printf(FMT("%-19s ", "-> %s"),
|
|
Packit Service |
d1fe03 |
ipv6_addr_to_string(&fw6->ipv6.dst,
|
|
Packit Service |
d1fe03 |
&fw6->ipv6.dmsk, format));
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Luckily, IPT_INV_VIA_IN and IPT_INV_VIA_OUT
|
|
Packit Service |
d1fe03 |
* have the same values as IP6T_INV_VIA_IN and IP6T_INV_VIA_OUT
|
|
Packit Service |
d1fe03 |
* so this function serves for both iptables and ip6tables */
|
|
Packit Service |
d1fe03 |
void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags,
|
|
Packit Service |
d1fe03 |
unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const char *anyname = format & FMT_NUMERIC ? "*" : "any";
|
|
Packit Service |
d1fe03 |
char iface[IFNAMSIZ + 2];
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!(format & FMT_VIA))
|
|
Packit Service |
d1fe03 |
return;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
snprintf(iface, IFNAMSIZ + 2, "%s%s",
|
|
Packit Service |
d1fe03 |
invflags & IPT_INV_VIA_IN ? "!" : "",
|
|
Packit Service |
d1fe03 |
iniface[0] != '\0' ? iniface : anyname);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf(FMT(" %-6s ", "in %s "), iface);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
snprintf(iface, IFNAMSIZ + 2, "%s%s",
|
|
Packit Service |
d1fe03 |
invflags & IPT_INV_VIA_OUT ? "!" : "",
|
|
Packit Service |
d1fe03 |
outiface[0] != '\0' ? outiface : anyname);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf(FMT("%-6s ", "out %s "), iface);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void command_match(struct iptables_command_state *cs)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct option *opts = xt_params->opts;
|
|
Packit Service |
d1fe03 |
struct xtables_match *m;
|
|
Packit Service |
d1fe03 |
size_t size;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->invert)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"unexpected ! flag before --match");
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
|
|
Packit Service |
d1fe03 |
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
|
|
Packit Service |
d1fe03 |
m->m = xtables_calloc(1, size);
|
|
Packit Service |
d1fe03 |
m->m->u.match_size = size;
|
|
Packit Service |
d1fe03 |
if (m->real_name == NULL) {
|
|
Packit Service |
d1fe03 |
strcpy(m->m->u.user.name, m->name);
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
strcpy(m->m->u.user.name, m->real_name);
|
|
Packit Service |
d1fe03 |
if (!(m->ext_flags & XTABLES_EXT_ALIAS))
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Notice: the %s match is converted into %s match "
|
|
Packit Service |
d1fe03 |
"in rule listing and saving.\n", m->name, m->real_name);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
m->m->u.user.revision = m->revision;
|
|
Packit Service |
d1fe03 |
xs_init_match(m);
|
|
Packit Service |
d1fe03 |
if (m == m->next)
|
|
Packit Service |
d1fe03 |
return;
|
|
Packit Service |
d1fe03 |
/* Merge options for non-cloned matches */
|
|
Packit Service |
d1fe03 |
if (m->x6_options != NULL)
|
|
Packit Service |
d1fe03 |
opts = xtables_options_xfrm(xt_params->orig_opts, opts,
|
|
Packit Service |
d1fe03 |
m->x6_options, &m->option_offset);
|
|
Packit Service |
d1fe03 |
else if (m->extra_opts != NULL)
|
|
Packit Service |
d1fe03 |
opts = xtables_merge_options(xt_params->orig_opts, opts,
|
|
Packit Service |
d1fe03 |
m->extra_opts, &m->option_offset);
|
|
Packit Service |
d1fe03 |
if (opts == NULL)
|
|
Packit Service |
d1fe03 |
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
|
|
Packit Service |
d1fe03 |
xt_params->opts = opts;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
const char *xt_parse_target(const char *targetname)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const char *ptr;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (strlen(targetname) < 1)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Invalid target name (too short)");
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Invalid target name `%s' (%u chars max)",
|
|
Packit Service |
d1fe03 |
targetname, XT_EXTENSION_MAXNAMELEN - 1);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (ptr = targetname; *ptr; ptr++)
|
|
Packit Service |
d1fe03 |
if (isspace(*ptr))
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Invalid target name `%s'", targetname);
|
|
Packit Service |
d1fe03 |
return targetname;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void command_jump(struct iptables_command_state *cs, const char *jumpto)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct option *opts = xt_params->opts;
|
|
Packit Service |
d1fe03 |
size_t size;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
cs->jumpto = xt_parse_target(jumpto);
|
|
Packit Service |
d1fe03 |
/* TRY_LOAD (may be chain name) */
|
|
Packit Service |
d1fe03 |
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->target == NULL)
|
|
Packit Service |
d1fe03 |
return;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
cs->target->t = xtables_calloc(1, size);
|
|
Packit Service |
d1fe03 |
cs->target->t->u.target_size = size;
|
|
Packit Service |
d1fe03 |
if (cs->target->real_name == NULL) {
|
|
Packit Service |
d1fe03 |
strcpy(cs->target->t->u.user.name, cs->jumpto);
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
/* Alias support for userspace side */
|
|
Packit Service |
d1fe03 |
strcpy(cs->target->t->u.user.name, cs->target->real_name);
|
|
Packit Service |
d1fe03 |
if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
|
|
Packit Service |
d1fe03 |
fprintf(stderr, "Notice: The %s target is converted into %s target "
|
|
Packit Service |
d1fe03 |
"in rule listing and saving.\n",
|
|
Packit Service |
d1fe03 |
cs->jumpto, cs->target->real_name);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
cs->target->t->u.user.revision = cs->target->revision;
|
|
Packit Service |
d1fe03 |
xs_init_target(cs->target);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->target->x6_options != NULL)
|
|
Packit Service |
d1fe03 |
opts = xtables_options_xfrm(xt_params->orig_opts, opts,
|
|
Packit Service |
d1fe03 |
cs->target->x6_options,
|
|
Packit Service |
d1fe03 |
&cs->target->option_offset);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
opts = xtables_merge_options(xt_params->orig_opts, opts,
|
|
Packit Service |
d1fe03 |
cs->target->extra_opts,
|
|
Packit Service |
d1fe03 |
&cs->target->option_offset);
|
|
Packit Service |
d1fe03 |
if (opts == NULL)
|
|
Packit Service |
d1fe03 |
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
|
|
Packit Service |
d1fe03 |
xt_params->opts = opts;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
char cmd2char(int option)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
/* cmdflags index corresponds with position of bit in CMD_* values */
|
|
Packit Service |
d1fe03 |
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
|
|
Packit Service |
d1fe03 |
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; option > 1; option >>= 1, i++)
|
|
Packit Service |
d1fe03 |
;
|
|
Packit Service |
d1fe03 |
if (i >= ARRAY_SIZE(cmdflags))
|
|
Packit Service |
d1fe03 |
xtables_error(OTHER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"cmd2char(): Invalid command number %u.\n",
|
|
Packit Service |
d1fe03 |
1 << i);
|
|
Packit Service |
d1fe03 |
return cmdflags[i];
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
void add_command(unsigned int *cmd, const int newcmd,
|
|
Packit Service |
d1fe03 |
const int othercmds, int invert)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
if (invert)
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "unexpected '!' flag");
|
|
Packit Service |
d1fe03 |
if (*cmd & (~othercmds))
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
|
|
Packit Service |
d1fe03 |
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
|
|
Packit Service |
d1fe03 |
*cmd |= newcmd;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Can't be zero. */
|
|
Packit Service |
d1fe03 |
int parse_rulenumber(const char *rule)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
unsigned int rulenum;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
|
|
Packit Service |
d1fe03 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit Service |
d1fe03 |
"Invalid rule number `%s'", rule);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return rulenum;
|
|
Packit Service |
d1fe03 |
}
|