#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
static const char *hooknames[] = {
- [NF_IP_PRE_ROUTING] = "PREROUTING",
- [NF_IP_LOCAL_IN] = "INPUT",
- [NF_IP_FORWARD] = "FORWARD",
- [NF_IP_LOCAL_OUT] = "OUTPUT",
- [NF_IP_POST_ROUTING] = "POSTROUTING",
+ [NF_INET_PRE_ROUTING] = "PREROUTING",
+ [NF_INET_LOCAL_IN] = "INPUT",
+ [NF_INET_FORWARD] = "FORWARD",
+ [NF_INET_LOCAL_OUT] = "OUTPUT",
+ [NF_INET_POST_ROUTING] = "POSTROUTING",
};
enum nf_ip_trace_comments {
/* No recursion; use packet counter to save back ptrs (reset
to 0 as we leave), and comefrom to save source hook bitmask */
- for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
+ for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
unsigned int pos = newinfo->hook_entry[hook];
struct ipt_entry *e
= (struct ipt_entry *)(entry0 + pos);
= (void *)ipt_get_target(e);
int visited = e->comefrom & (1 << hook);
- if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
+ if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
printk("iptables: loop hook %u pos %u %08X.\n",
hook, pos, e->comefrom);
return 0;
}
e->comefrom
- |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
+ |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
/* Unconditional return/END. */
if ((e->target_offset == sizeof(struct ipt_entry)
/* Return: backtrack through the last
big jump. */
do {
- e->comefrom ^= (1<<NF_IP_NUMHOOKS);
+ e->comefrom ^= (1<<NF_INET_NUMHOOKS);
#ifdef DEBUG_IP_FIREWALL_USER
if (e->comefrom
- & (1 << NF_IP_NUMHOOKS)) {
+ & (1 << NF_INET_NUMHOOKS)) {
duprintf("Back unset "
"on hook %u "
"rule %u\n",
}
/* Check hooks & underflows */
- for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if ((unsigned char *)e - base == hook_entries[h])
newinfo->hook_entry[h] = hook_entries[h];
if ((unsigned char *)e - base == underflows[h])
newinfo->number = number;
/* Init all hooks to impossible value. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
newinfo->hook_entry[i] = 0xFFFFFFFF;
newinfo->underflow[i] = 0xFFFFFFFF;
}
}
/* Check hooks all assigned */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
/* Only hooks which are valid */
if (!(valid_hooks & (1 << i)))
continue;
return 0;
}
-static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
+static int compat_calc_entry(struct ipt_entry *e,
+ const struct xt_table_info *info,
void *base, struct xt_table_info *newinfo)
{
struct ipt_entry_target *t;
if (ret)
return ret;
- for (i = 0; i< NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
if (info->hook_entry[i] && (e < (struct ipt_entry *)
(base + info->hook_entry[i])))
newinfo->hook_entry[i] -= off;
return 0;
}
-static int compat_table_info(struct xt_table_info *info,
+static int compat_table_info(const struct xt_table_info *info,
struct xt_table_info *newinfo)
{
void *loc_cpu_entry;
- int i;
if (!newinfo || !info)
return -EINVAL;
- memset(newinfo, 0, sizeof(struct xt_table_info));
- newinfo->size = info->size;
- newinfo->number = info->number;
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
- newinfo->hook_entry[i] = info->hook_entry[i];
- newinfo->underflow[i] = info->underflow[i];
- }
+ /* we dont care about newinfo->entries[] */
+ memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
+ newinfo->initial_entries = 0;
loc_cpu_entry = info->entries[raw_smp_processor_id()];
return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
compat_calc_entry, info, loc_cpu_entry, newinfo);
return -ENOPROTOOPT;
/* overflow check */
- if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
- SMP_CACHE_BYTES)
- return -ENOMEM;
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
return -ENOMEM;
u32 valid_hooks;
u32 num_entries;
u32 size;
- u32 hook_entry[NF_IP_NUMHOOKS];
- u32 underflow[NF_IP_NUMHOOKS];
+ u32 hook_entry[NF_INET_NUMHOOKS];
+ u32 underflow[NF_INET_NUMHOOKS];
u32 num_counters;
compat_uptr_t counters; /* struct ipt_counters * */
struct compat_ipt_entry entries[0];
};
-static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
- void __user **dstptr, compat_uint_t *size)
-{
- return xt_compat_match_to_user(m, dstptr, size);
-}
-
-static int compat_copy_entry_to_user(struct ipt_entry *e,
- void __user **dstptr, compat_uint_t *size)
+static int
+compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
+ compat_uint_t *size, struct xt_counters *counters,
+ unsigned int *i)
{
struct ipt_entry_target *t;
struct compat_ipt_entry __user *ce;
if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
goto out;
+ if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
+ goto out;
+
*dstptr += sizeof(struct compat_ipt_entry);
- ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
+ ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
target_offset = e->target_offset - (origsize - *size);
if (ret)
goto out;
goto out;
if (put_user(next_offset, &ce->next_offset))
goto out;
+
+ (*i)++;
return 0;
out:
return ret;
goto out;
/* Check hooks & underflows */
- for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if ((unsigned char *)e - base == hook_entries[h])
newinfo->hook_entry[h] = hook_entries[h];
if ((unsigned char *)e - base == underflows[h])
xt_compat_target_from_user(t, dstptr, size);
de->next_offset = e->next_offset - (origsize - *size);
- for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if ((unsigned char *)de - base < newinfo->hook_entry[h])
newinfo->hook_entry[h] -= origsize - *size;
if ((unsigned char *)de - base < newinfo->underflow[h])
info->number = number;
/* Init all hooks to impossible value. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
info->hook_entry[i] = 0xFFFFFFFF;
info->underflow[i] = 0xFFFFFFFF;
}
}
/* Check hooks all assigned */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
/* Only hooks which are valid */
if (!(valid_hooks & (1 << i)))
continue;
goto out_unlock;
newinfo->number = number;
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
newinfo->hook_entry[i] = info->hook_entry[i];
newinfo->underflow[i] = info->underflow[i];
}
return -ENOPROTOOPT;
/* overflow check */
- if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
- SMP_CACHE_BYTES)
+ if (tmp.size >= INT_MAX / num_possible_cpus())
return -ENOMEM;
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
return -ENOMEM;
static int compat_copy_entries_to_user(unsigned int total_size,
struct xt_table *table, void __user *userptr)
{
- unsigned int off, num;
- struct compat_ipt_entry e;
struct xt_counters *counters;
struct xt_table_info *private = table->private;
void __user *pos;
unsigned int size;
int ret = 0;
void *loc_cpu_entry;
+ unsigned int i = 0;
counters = alloc_counters(table);
if (IS_ERR(counters))
pos = userptr;
size = total_size;
ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
- compat_copy_entry_to_user, &pos, &size);
- if (ret)
- goto free_counters;
+ compat_copy_entry_to_user,
+ &pos, &size, counters, &i);
- /* ... then go back and fix counters and names */
- for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
- unsigned int i;
- struct ipt_entry_match m;
- struct ipt_entry_target t;
-
- ret = -EFAULT;
- if (copy_from_user(&e, userptr + off,
- sizeof(struct compat_ipt_entry)))
- goto free_counters;
- if (copy_to_user(userptr + off +
- offsetof(struct compat_ipt_entry, counters),
- &counters[num], sizeof(counters[num])))
- goto free_counters;
-
- for (i = sizeof(struct compat_ipt_entry);
- i < e.target_offset; i += m.u.match_size) {
- if (copy_from_user(&m, userptr + off + i,
- sizeof(struct ipt_entry_match)))
- goto free_counters;
- if (copy_to_user(userptr + off + i +
- offsetof(struct ipt_entry_match, u.user.name),
- m.u.kernel.match->name,
- strlen(m.u.kernel.match->name) + 1))
- goto free_counters;
- }
-
- if (copy_from_user(&t, userptr + off + e.target_offset,
- sizeof(struct ipt_entry_target)))
- goto free_counters;
- if (copy_to_user(userptr + off + e.target_offset +
- offsetof(struct ipt_entry_target, u.user.name),
- t.u.kernel.target->name,
- strlen(t.u.kernel.target->name) + 1))
- goto free_counters;
- }
- ret = 0;
-free_counters:
vfree(counters);
return ret;
}
{
int ret;
struct xt_table_info *newinfo;
- static struct xt_table_info bootstrap
+ struct xt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
void *loc_cpu_entry;