#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
+#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define XT_MATCH_ITERATE(type, e, fn, args...) \
({ \
__ret; \
})
-#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
({ \
(pos) < (typeof(pos))((char *)(ehead) + (esize)); \
(pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
+/* can only be xt_entry_match, so no use of typeof here */
+#define xt_ematch_foreach(pos, entry) \
+ for ((pos) = (struct xt_entry_match *)entry->elems; \
+ (pos) < (struct xt_entry_match *)((char *)(entry) + \
+ (entry)->target_offset); \
+ (pos) = (struct xt_entry_match *)((char *)(pos) + \
+ (pos)->u.match_size))
+
#ifdef __KERNEL__
#include <linux/netdevice.h>
return (void *)e + e->target_offset;
}
+#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define IPT_MATCH_ITERATE(e, fn, args...) \
XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
-#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
-/* fn returns 0 to continue iteration */
-#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \
- XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)
-
#endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/
#endif /* _IPTABLES_H */
return (void *)e + e->target_offset;
}
+#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define IP6T_MATCH_ITERATE(e, fn, args...) \
XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
-#ifndef __KERNEL__
/* fn returns 0 to continue iteration */
#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s)
-/* fn returns 0 to continue iteration */
-#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \
- XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args)
-
#endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/
#endif /* _IP6_TABLES_H */
do {
const struct ipt_entry_target *t;
+ const struct xt_entry_match *ematch;
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
if (!ip_packet_match(ip, indev, outdev,
- &e->ip, mtpar.fragoff) ||
- IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
+ &e->ip, mtpar.fragoff)) {
+ no_match:
e = ipt_next_entry(e);
continue;
}
+ xt_ematch_foreach(ematch, e)
+ if (do_match(ematch, skb, &mtpar) != 0)
+ goto no_match;
+
ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
t = ipt_get_target(e);
int ret;
unsigned int j;
struct xt_mtchk_param mtpar;
+ struct xt_entry_match *ematch;
ret = check_entry(e, name);
if (ret)
mtpar.entryinfo = &e->ip;
mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV4;
- ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = find_check_match(ematch, &mtpar, &j);
+ if (ret != 0)
+ break;
+ }
if (ret != 0)
goto cleanup_matches;
err:
module_put(t->u.kernel.target->me);
cleanup_matches:
- IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, &j) != 0)
+ break;
return ret;
}
{
struct xt_tgdtor_param par;
struct ipt_entry_target *t;
+ struct xt_entry_match *ematch;
/* Cleanup all matches */
- IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, NULL) != 0)
+ break;
t = ipt_get_target(e);
par.net = net;
const struct xt_table_info *info,
const void *base, struct xt_table_info *newinfo)
{
+ const struct xt_entry_match *ematch;
const struct ipt_entry_target *t;
unsigned int entry_offset;
int off, i, ret;
off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
entry_offset = (void *)e - base;
- IPT_MATCH_ITERATE(e, compat_calc_match, &off);
+ xt_ematch_foreach(ematch, e)
+ if (compat_calc_match(ematch, &off) != 0)
+ break;
t = ipt_get_target_c(e);
off += xt_compat_target_offset(t->u.kernel.target);
newinfo->size -= off;
struct compat_ipt_entry __user *ce;
u_int16_t target_offset, next_offset;
compat_uint_t origsize;
- int ret;
+ const struct xt_entry_match *ematch;
+ int ret = 0;
origsize = *size;
ce = (struct compat_ipt_entry __user *)*dstptr;
*dstptr += sizeof(struct compat_ipt_entry);
*size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
- ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
+ xt_ematch_foreach(ematch, e) {
+ ret = xt_compat_match_to_user(ematch, dstptr, size);
+ if (ret != 0)
+ break;
+ }
target_offset = e->target_offset - (origsize - *size);
if (ret)
return ret;
static void compat_release_entry(struct compat_ipt_entry *e)
{
struct ipt_entry_target *t;
+ struct xt_entry_match *ematch;
/* Cleanup all matches */
- COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
+ xt_ematch_foreach(ematch, e)
+ if (compat_release_match(ematch, NULL) != 0)
+ break;
t = compat_ipt_get_target(e);
module_put(t->u.kernel.target->me);
}
const unsigned int *underflows,
const char *name)
{
+ struct xt_entry_match *ematch;
struct ipt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
entry_offset = (void *)e - (void *)base;
j = 0;
- ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
- &e->ip, e->comefrom, &off, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = compat_find_calc_match(ematch, name,
+ &e->ip, e->comefrom, &off, &j);
+ if (ret != 0)
+ break;
+ }
if (ret != 0)
goto release_matches;
out:
module_put(t->u.kernel.target->me);
release_matches:
- IPT_MATCH_ITERATE(e, compat_release_match, &j);
+ xt_ematch_foreach(ematch, e)
+ if (compat_release_match(ematch, &j) != 0)
+ break;
return ret;
}
struct ipt_entry *de;
unsigned int origsize;
int ret, h;
+ struct xt_entry_match *ematch;
ret = 0;
origsize = *size;
*dstptr += sizeof(struct ipt_entry);
*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
- ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
- dstptr, size);
+ xt_ematch_foreach(ematch, e) {
+ ret = xt_compat_match_from_user(ematch, dstptr, size);
+ if (ret != 0)
+ break;
+ }
if (ret)
return ret;
de->target_offset = e->target_offset - (origsize - *size);
static int
compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
{
+ struct xt_entry_match *ematch;
struct xt_mtchk_param mtpar;
unsigned int j;
- int ret;
+ int ret = 0;
j = 0;
mtpar.net = net;
mtpar.entryinfo = &e->ip;
mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV4;
- ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = check_match(ematch, &mtpar, &j);
+ if (ret != 0)
+ break;
+ }
if (ret)
goto cleanup_matches;
return 0;
cleanup_matches:
- IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, &j) != 0)
+ break;
return ret;
}
do {
const struct ip6t_entry_target *t;
+ const struct xt_entry_match *ematch;
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
- &mtpar.thoff, &mtpar.fragoff, &hotdrop) ||
- IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
+ &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {
+ no_match:
e = ip6t_next_entry(e);
continue;
}
+ xt_ematch_foreach(ematch, e)
+ if (do_match(ematch, skb, &mtpar) != 0)
+ goto no_match;
+
ADD_COUNTER(e->counters,
ntohs(ipv6_hdr(skb)->payload_len) +
sizeof(struct ipv6hdr), 1);
int ret;
unsigned int j;
struct xt_mtchk_param mtpar;
+ struct xt_entry_match *ematch;
ret = check_entry(e, name);
if (ret)
mtpar.entryinfo = &e->ipv6;
mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV6;
- ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = find_check_match(ematch, &mtpar, &j);
+ if (ret != 0)
+ break;
+ }
if (ret != 0)
goto cleanup_matches;
err:
module_put(t->u.kernel.target->me);
cleanup_matches:
- IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, &j) != 0)
+ break;
return ret;
}
{
struct xt_tgdtor_param par;
struct ip6t_entry_target *t;
+ struct xt_entry_match *ematch;
/* Cleanup all matches */
- IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, NULL) != 0)
+ break;
t = ip6t_get_target(e);
par.net = net;
const struct xt_table_info *info,
const void *base, struct xt_table_info *newinfo)
{
+ const struct xt_entry_match *ematch;
const struct ip6t_entry_target *t;
unsigned int entry_offset;
int off, i, ret;
off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
entry_offset = (void *)e - base;
- IP6T_MATCH_ITERATE(e, compat_calc_match, &off);
+ xt_ematch_foreach(ematch, e)
+ if (compat_calc_match(ematch, &off) != 0)
+ break;
t = ip6t_get_target_c(e);
off += xt_compat_target_offset(t->u.kernel.target);
newinfo->size -= off;
struct compat_ip6t_entry __user *ce;
u_int16_t target_offset, next_offset;
compat_uint_t origsize;
- int ret;
+ const struct xt_entry_match *ematch;
+ int ret = 0;
origsize = *size;
ce = (struct compat_ip6t_entry __user *)*dstptr;
*dstptr += sizeof(struct compat_ip6t_entry);
*size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
- ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
+ xt_ematch_foreach(ematch, e) {
+ ret = xt_compat_match_to_user(ematch, dstptr, size);
+ if (ret != 0)
+ break;
+ }
target_offset = e->target_offset - (origsize - *size);
if (ret)
return ret;
static void compat_release_entry(struct compat_ip6t_entry *e)
{
struct ip6t_entry_target *t;
+ struct xt_entry_match *ematch;
/* Cleanup all matches */
- COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL);
+ xt_ematch_foreach(ematch, e)
+ if (compat_release_match(ematch, NULL) != 0)
+ break;
t = compat_ip6t_get_target(e);
module_put(t->u.kernel.target->me);
}
const unsigned int *underflows,
const char *name)
{
+ struct xt_entry_match *ematch;
struct ip6t_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
entry_offset = (void *)e - (void *)base;
j = 0;
- ret = COMPAT_IP6T_MATCH_ITERATE(e, compat_find_calc_match, name,
- &e->ipv6, e->comefrom, &off, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = compat_find_calc_match(ematch, name,
+ &e->ipv6, e->comefrom, &off, &j);
+ if (ret != 0)
+ break;
+ }
if (ret != 0)
goto release_matches;
out:
module_put(t->u.kernel.target->me);
release_matches:
- IP6T_MATCH_ITERATE(e, compat_release_match, &j);
+ xt_ematch_foreach(ematch, e)
+ if (compat_release_match(ematch, &j) != 0)
+ break;
return ret;
}
struct ip6t_entry *de;
unsigned int origsize;
int ret, h;
+ struct xt_entry_match *ematch;
ret = 0;
origsize = *size;
*dstptr += sizeof(struct ip6t_entry);
*size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
- ret = COMPAT_IP6T_MATCH_ITERATE(e, xt_compat_match_from_user,
- dstptr, size);
+ xt_ematch_foreach(ematch, e) {
+ ret = xt_compat_match_from_user(ematch, dstptr, size);
+ if (ret != 0)
+ break;
+ }
if (ret)
return ret;
de->target_offset = e->target_offset - (origsize - *size);
const char *name)
{
unsigned int j;
- int ret;
+ int ret = 0;
struct xt_mtchk_param mtpar;
+ struct xt_entry_match *ematch;
j = 0;
mtpar.net = net;
mtpar.entryinfo = &e->ipv6;
mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV6;
- ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j);
+ xt_ematch_foreach(ematch, e) {
+ ret = check_match(ematch, &mtpar, &j);
+ if (ret != 0)
+ break;
+ }
if (ret)
goto cleanup_matches;
return 0;
cleanup_matches:
- IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);
+ xt_ematch_foreach(ematch, e)
+ if (cleanup_match(ematch, net, &j) != 0)
+ break;
return ret;
}
{
const struct xt_tcpmss_info *info = par->targinfo;
const struct ipt_entry *e = par->entryinfo;
+ const struct xt_entry_match *ematch;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
"FORWARD, OUTPUT and POSTROUTING hooks\n");
return false;
}
- if (IPT_MATCH_ITERATE(e, find_syn_match))
- return true;
+ xt_ematch_foreach(ematch, e)
+ if (find_syn_match(ematch))
+ return true;
printk("xt_TCPMSS: Only works on TCP SYN packets\n");
return false;
}
{
const struct xt_tcpmss_info *info = par->targinfo;
const struct ip6t_entry *e = par->entryinfo;
+ const struct xt_entry_match *ematch;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
"FORWARD, OUTPUT and POSTROUTING hooks\n");
return false;
}
- if (IP6T_MATCH_ITERATE(e, find_syn_match))
- return true;
+ xt_ematch_foreach(ematch, e)
+ if (find_syn_match(ematch))
+ return true;
printk("xt_TCPMSS: Only works on TCP SYN packets\n");
return false;
}