return 0;
}
- for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
- unsigned long odev;
- memcpy(&odev, outdev + i*sizeof(unsigned long),
- sizeof(unsigned long));
- ret |= (odev
- ^ ((const unsigned long *)arpinfo->outiface)[i])
- & ((const unsigned long *)arpinfo->outiface_mask)[i];
+ for (i = 0, ret = 0; i < IFNAMSIZ; i++) {
+ ret |= (outdev[i] ^ arpinfo->outiface[i])
+ & arpinfo->outiface_mask[i];
}
if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) {
for (;;) {
struct arpt_standard_target *t
= (void *)arpt_get_target(e);
+ int visited = e->comefrom & (1 << hook);
if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
printk("arptables: loop hook %u pos %u %08X.\n",
|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
/* Unconditional return/END. */
- if (e->target_offset == sizeof(struct arpt_entry)
+ if ((e->target_offset == sizeof(struct arpt_entry)
&& (strcmp(t->target.u.user.name,
ARPT_STANDARD_TARGET) == 0)
&& t->verdict < 0
- && unconditional(&e->arp)) {
+ && unconditional(&e->arp)) || visited) {
unsigned int oldpos, size;
+ if (t->verdict < -NF_MAX_VERDICT - 1) {
+ duprintf("mark_source_chains: bad "
+ "negative verdict (%i)\n",
+ t->verdict);
+ return 0;
+ }
+
/* Return: backtrack through the last
* big jump.
*/
if (strcmp(t->target.u.user.name,
ARPT_STANDARD_TARGET) == 0
&& newpos >= 0) {
+ if (newpos > newinfo->size -
+ sizeof(struct arpt_entry)) {
+ duprintf("mark_source_chains: "
+ "bad verdict (%i)\n",
+ newpos);
+ return 0;
+ }
+
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
static inline int standard_check(const struct arpt_entry_target *t,
unsigned int max_offset)
{
- struct arpt_standard_target *targ = (void *)t;
-
/* Check standard info. */
if (t->u.target_size
!= ARPT_ALIGN(sizeof(struct arpt_standard_target))) {
return 0;
}
- if (targ->verdict >= 0
- && targ->verdict > max_offset - sizeof(struct arpt_entry)) {
- duprintf("arpt_standard_check: bad verdict (%i)\n",
- targ->verdict);
- return 0;
- }
-
- if (targ->verdict < -NF_MAX_VERDICT - 1) {
- duprintf("arpt_standard_check: bad negative verdict (%i)\n",
- targ->verdict);
- return 0;
- }
return 1;
}
}
/* FIXME: underflows must be unconditional, standard verdicts
- < 0 (not ARPT_RETURN). --RR */
+ < 0 (not ARPT_RETURN). --RR */
/* Clear counters and comefrom */
e->counters = ((struct xt_counters) { 0, 0 });
}
}
+ if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
+ duprintf("Looping hook\n");
+ return -ELOOP;
+ }
+
/* Finally, each sanity check must pass */
i = 0;
ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0)
- goto cleanup;
-
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
- duprintf("Looping hook\n");
- goto cleanup;
+ if (ret != 0) {
+ ARPT_ENTRY_ITERATE(entry0, newinfo->size,
+ cleanup_entry, &i);
+ return ret;
}
/* And one copy for every other CPU */
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
- return 0;
-cleanup:
- ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
/* Update module usage count based on number of rules */
duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
oldinfo->number, oldinfo->initial_entries, newinfo->number);
- if ((oldinfo->number > oldinfo->initial_entries) ||
- (newinfo->number <= oldinfo->initial_entries))
+ if ((oldinfo->number > oldinfo->initial_entries) ||
+ (newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
if ((oldinfo->number > oldinfo->initial_entries) &&
(newinfo->number <= oldinfo->initial_entries))