/*
* m_ipt.c iptables based targets
- * utilities mostly ripped from iptables <duh, its the linux way>
+ * utilities mostly ripped from iptables <duh, its the linux way>
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* Authors: J Hadi Salim (hadi@cyberus.ca)
*/
-#include <syslog.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <linux/if.h>
#include <iptables.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_tables.h>
{0, 0, 0, 0}
};
-static struct iptables_target *t_list = NULL;
+static struct xtables_target *t_list;
static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
+static unsigned int global_option_offset;
#define OPTION_OFFSET 256
char *lib_dir;
void
-register_target(struct iptables_target *me)
+xtables_register_target(struct xtables_target *me)
{
-/* fprintf(stderr, "\nDummy register_target %s \n", me->name);
-*/
me->next = t_list;
t_list = me;
}
-void
-xtables_register_target(struct iptables_target *me)
-{
- me->next = t_list;
- t_list = me;
-}
-
-void
-exit_tryhelp(int status)
+static void exit_tryhelp(int status)
{
fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
pname, pname);
exit(status);
}
-void
-exit_error(enum exittype status, char *msg, ...)
+static void exit_error(enum xtables_exittype status, char *msg, ...)
{
va_list args;
Email them next time i remember
*/
-char *
-addr_to_dotted(const struct in_addr *addrp)
-{
- static char buf[20];
- const unsigned char *bytep;
-
- bytep = (const unsigned char *) &(addrp->s_addr);
- sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
- return buf;
-}
-
-int string_to_number_ll(const char *s, unsigned long long min,
- unsigned long long max,
- unsigned long long *ret)
-{
- unsigned long long number;
- char *end;
-
- /* Handle hex, octal, etc. */
- errno = 0;
- number = strtoull(s, &end, 0);
- if (*end == '\0' && end != s) {
- /* we parsed a number, let's see if we want this */
- if (errno != ERANGE && min <= number && (!max || number <= max)) {
- *ret = number;
- return 0;
- }
- }
- return -1;
-}
-
-int string_to_number_l(const char *s, unsigned long min, unsigned long max,
- unsigned long *ret)
-{
- int result;
- unsigned long long number;
-
- result = string_to_number_ll(s, min, max, &number);
- *ret = (unsigned long)number;
-
- return result;
-}
-
-int string_to_number(const char *s, unsigned int min, unsigned int max,
- unsigned int *ret)
-{
- int result;
- unsigned long number;
-
- result = string_to_number_l(s, min, max, &number);
- *ret = (unsigned int)number;
-
- return result;
-}
-
static void free_opts(struct option *local_opts)
{
if (local_opts != original_opts) {
struct option *merge;
unsigned int num_old, num_new, i;
- for (num_old = 0; oldopts[num_old].name; num_old++) ;
- for (num_new = 0; newopts[num_new].name; num_new++) ;
+ for (num_old = 0; oldopts[num_old].name; num_old++);
+ for (num_new = 0; newopts[num_new].name; num_new++);
*option_offset = global_option_offset + OPTION_OFFSET;
- merge = malloc(sizeof (struct option) * (num_new + num_old + 1));
- memcpy(merge, oldopts, num_old * sizeof (struct option));
+ merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
+ memcpy(merge, oldopts, num_old * sizeof(struct option));
for (i = 0; i < num_new; i++) {
merge[num_old + i] = newopts[i];
merge[num_old + i].val += *option_offset;
}
- memset(merge + num_old + num_new, 0, sizeof (struct option));
+ memset(merge + num_old + num_new, 0, sizeof(struct option));
return merge;
}
return p;
}
-static struct iptables_target *
+static struct xtables_target *
find_t(char *name)
{
- struct iptables_target *m;
+ struct xtables_target *m;
+
for (m = t_list; m; m = m->next) {
if (strcmp(m->name, name) == 0)
return m;
return NULL;
}
-static struct iptables_target *
+static struct xtables_target *
get_target_name(const char *name)
{
void *handle;
char *error;
char *new_name, *lname;
- struct iptables_target *m;
- char path[strlen(lib_dir) + sizeof ("/libipt_.so") + strlen(name)];
+ struct xtables_target *m;
+ char path[strlen(lib_dir) + sizeof("/libipt_.so") + strlen(name)];
#ifdef NO_SHARED_LIBS
return NULL;
#endif
- new_name = malloc(strlen(name) + 1);
- lname = malloc(strlen(name) + 1);
- if (new_name)
- memset(new_name, '\0', strlen(name) + 1);
- else
+ new_name = calloc(1, strlen(name) + 1);
+ lname = calloc(1, strlen(name) + 1);
+ if (!new_name)
exit_error(PARAMETER_PROBLEM, "get_target_name");
-
- if (lname)
- memset(lname, '\0', strlen(name) + 1);
- else
+ if (!lname)
exit_error(PARAMETER_PROBLEM, "get_target_name");
strcpy(new_name, name);
if (isupper(lname[0])) {
int i;
+
for (i = 0; i < strlen(name); i++) {
lname[i] = tolower(lname[i]);
}
if (islower(new_name[0])) {
int i;
+
for (i = 0; i < strlen(new_name); i++) {
new_name[i] = toupper(new_name[i]);
}
handle = dlopen(path, RTLD_LAZY);
if (!handle) {
- sprintf(path, "%s/libxt_%s.so", lib_dir , lname);
+ sprintf(path, "%s/libxt_%s.so", lib_dir, lname);
handle = dlopen(path, RTLD_LAZY);
}
if (!handle) {
- sprintf(path, "%s/libipt_%s.so", lib_dir , lname);
+ sprintf(path, "%s/libipt_%s.so", lib_dir, lname);
handle = dlopen(path, RTLD_LAZY);
}
/* ok, lets give up .. */
m = dlsym(handle, new_name);
if ((error = dlerror()) != NULL) {
- m = (struct iptables_target *) dlsym(handle, lname);
+ m = (struct xtables_target *) dlsym(handle, lname);
if ((error = dlerror()) != NULL) {
m = find_t(new_name);
- if (NULL == m) {
+ if (m == NULL) {
m = find_t(lname);
- if (NULL == m) {
+ if (m == NULL) {
fputs(error, stderr);
fprintf(stderr, "\n");
dlclose(handle);
return m;
}
-
-struct in_addr *dotted_to_addr(const char *dotted)
-{
- static struct in_addr addr;
- unsigned char *addrp;
- char *p, *q;
- unsigned int onebyte;
- int i;
- char buf[20];
-
- /* copy dotted string, because we need to modify it */
- strncpy(buf, dotted, sizeof (buf) - 1);
- addrp = (unsigned char *) &(addr.s_addr);
-
- p = buf;
- for (i = 0; i < 3; i++) {
- if ((q = strchr(p, '.')) == NULL)
- return (struct in_addr *) NULL;
-
- *q = '\0';
- if (string_to_number(p, 0, 255, &onebyte) == -1)
- return (struct in_addr *) NULL;
-
- addrp[i] = (unsigned char) onebyte;
- p = q + 1;
- }
-
- /* we've checked 3 bytes, now we check the last one */
- if (string_to_number(p, 0, 255, &onebyte) == -1)
- return (struct in_addr *) NULL;
-
- addrp[3] = (unsigned char) onebyte;
-
- return &addr;
-}
-
static void set_revision(char *name, u_int8_t revision)
{
/* Old kernel sources don't have ".revision" field,
/*
* we may need to check for version mismatch
*/
-int
-build_st(struct iptables_target *target, struct ipt_entry_target *t)
+static int build_st(struct xtables_target *target, struct ipt_entry_target *t)
{
- unsigned int nfcache = 0;
-
if (target) {
size_t size;
size =
- IPT_ALIGN(sizeof (struct ipt_entry_target)) + target->size;
+ XT_ALIGN(sizeof(struct ipt_entry_target)) + target->size;
- if (NULL == t) {
+ if (t == NULL) {
target->t = fw_calloc(1, size);
target->t->u.target_size = size;
if (target->init != NULL)
- target->init(target->t, &nfcache);
+ target->init(target->t);
set_revision(target->t->u.user.name, target->revision);
} else {
target->t = t;
return -1;
}
-static int parse_ipt(struct action_util *a,int *argc_p,
+static int parse_ipt(struct action_util *a, int *argc_p,
char ***argv_p, int tca_id, struct nlmsghdr *n)
{
- struct iptables_target *m = NULL;
+ struct xtables_target *m = NULL;
struct ipt_entry fw;
struct rtattr *tail;
int c;
int rargc = *argc_p;
char **argv = *argv_p;
int argc = 0, iargc = 0;
- char k[16];
- int res = -1;
+ char k[FILTER_NAMESZ];
int size = 0;
int iok = 0, ok = 0;
__u32 hook = 0, index = 0;
- res = 0;
lib_dir = getenv("IPTABLES_LIB_DIR");
if (!lib_dir)
{
int i;
+
for (i = 0; i < rargc; i++) {
- if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
+ if (!argv[i] || strcmp(argv[i], "action") == 0)
break;
- }
}
iargc = argc = i;
}
if (argc <= 2) {
- fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc);
+ fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc);
return -1;
}
switch (c) {
case 'j':
m = get_target_name(optarg);
- if (NULL != m) {
+ if (m != NULL) {
- if (0 > build_st(m, NULL)) {
- printf(" %s error \n", m->name);
+ if (build_st(m, NULL) < 0) {
+ printf(" %s error\n", m->name);
return -1;
}
opts =
merge_options(opts, m->extra_opts,
&m->option_offset);
} else {
- fprintf(stderr," failed to find target %s\n\n", optarg);
+ fprintf(stderr, " failed to find target %s\n\n", optarg);
return -1;
}
ok++;
break;
default:
- memset(&fw, 0, sizeof (fw));
+ memset(&fw, 0, sizeof(fw));
if (m) {
m->parse(c - m->option_offset, argv, 0,
&m->tflags, NULL, &m->t);
} else {
- fprintf(stderr," failed to find target %s\n\n", optarg);
+ fprintf(stderr, " failed to find target %s\n\n", optarg);
return -1;
}
}
if (!ok && !iok) {
- fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv);
+ fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv);
return -1;
}
{
struct tcmsg *t = NLMSG_DATA(n);
+
if (t->tcm_parent != TC_H_ROOT
&& t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
hook = NF_IP_PRE_ROUTING;
}
}
- tail = NLMSG_TAIL(n);
- addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+ tail = addattr_nest(n, MAX_MSG, tca_id);
fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
fprintf(stdout, "\ttarget: ");
addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
if (m)
addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
- tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ addattr_nest_end(n, tail);
argc -= optind;
argv += optind;
optind = 0;
free_opts(opts);
/* Clear flags if target will be used again */
- m->tflags=0;
- m->used=0;
+ m->tflags = 0;
+ m->used = 0;
/* Free allocated memory */
- if (m->t)
- free(m->t);
+ if (m->t)
+ free(m->t);
return 0;
}
static int
-print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
+print_ipt(struct action_util *au, FILE * f, struct rtattr *arg)
{
struct rtattr *tb[TCA_IPT_MAX + 1];
struct ipt_entry_target *t = NULL;
fprintf(f, "[NULL ipt table name ] assuming mangle ");
} else {
fprintf(f, "tablename: %s ",
- (char *) RTA_DATA(tb[TCA_IPT_TABLE]));
+ rta_getattr_str(tb[TCA_IPT_TABLE]));
}
if (tb[TCA_IPT_HOOK] == NULL) {
return -1;
} else {
__u32 hook;
- hook = *(__u32 *) RTA_DATA(tb[TCA_IPT_HOOK]);
- fprintf(f, " hook: %s \n", ipthooks[hook]);
+
+ hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
+ fprintf(f, " hook: %s\n", ipthooks[hook]);
}
if (tb[TCA_IPT_TARG] == NULL) {
- fprintf(f, "\t[NULL ipt target parameters ] \n");
+ fprintf(f, "\t[NULL ipt target parameters ]\n");
return -1;
} else {
- struct iptables_target *m = NULL;
+ struct xtables_target *m = NULL;
+
t = RTA_DATA(tb[TCA_IPT_TARG]);
m = get_target_name(t->u.user.name);
- if (NULL != m) {
- if (0 > build_st(m, t)) {
- fprintf(stderr, " %s error \n", m->name);
+ if (m != NULL) {
+ if (build_st(m, t) < 0) {
+ fprintf(stderr, " %s error\n", m->name);
return -1;
}
fprintf(f, " [NULL ipt target index ]\n");
} else {
__u32 index;
- index = *(__u32 *) RTA_DATA(tb[TCA_IPT_INDEX]);
- fprintf(f, " \n\tindex %d", index);
+
+ index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
+ fprintf(f, "\n\tindex %u", index);
}
if (tb[TCA_IPT_CNT]) {
- struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);;
+ struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);
+
fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
}
if (show_stats) {
if (tb[TCA_IPT_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
- print_tm(f,tm);
+
+ print_tm(f, tm);
}
}
- fprintf(f, " \n");
+ fprintf(f, "\n");
}
free_opts(opts);
}
struct action_util ipt_action_util = {
- .id = "ipt",
- .parse_aopt = parse_ipt,
- .print_aopt = print_ipt,
+ .id = "ipt",
+ .parse_aopt = parse_ipt,
+ .print_aopt = print_ipt,
};
-