#endif
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
-/* Mutex protects lists (only traversed in user context). */
static DECLARE_MUTEX(ipt_mutex);
/* Must have mutex */
{
void *ret;
-#if 0
+#if 0
duprintf("find_inlist: searching for `%s' in %s.\n",
name, head == &ipt_target ? "ipt_target"
: head == &ipt_match ? "ipt_match"
#endif
static inline struct ipt_table *
-find_table_lock(const char *name, int *error, struct semaphore *mutex)
+ipt_find_table_lock(const char *name, int *error, struct semaphore *mutex)
{
return find_inlist_lock(&ipt_tables, name, "iptable_", error, mutex);
}
return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex);
}
-static inline struct ipt_target *
-find_target_lock(const char *name, int *error, struct semaphore *mutex)
+struct ipt_target *
+ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
{
return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
}
goto cleanup_matches;
t = ipt_get_target(e);
- target = find_target_lock(t->u.user.name, &ret, &ipt_mutex);
+ target = ipt_find_target_lock(t->u.user.name, &ret, &ipt_mutex);
if (!target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
goto cleanup_matches;
static int
copy_entries_to_user(unsigned int total_size,
struct ipt_table *table,
- void *userptr)
+ void __user *userptr)
{
unsigned int off, num, countersize;
struct ipt_entry *e;
static int
get_entries(const struct ipt_get_entries *entries,
- struct ipt_get_entries *uptr)
+ struct ipt_get_entries __user *uptr)
{
int ret;
struct ipt_table *t;
- t = find_table_lock(entries->name, &ret, &ipt_mutex);
+ t = ipt_find_table_lock(entries->name, &ret, &ipt_mutex);
if (t) {
duprintf("t->private->number = %u\n",
t->private->number);
}
static int
-do_replace(void *user, unsigned int len)
+do_replace(void __user *user, unsigned int len)
{
int ret;
struct ipt_replace tmp;
duprintf("ip_tables: Translated table\n");
- t = find_table_lock(tmp.name, &ret, &ipt_mutex);
+ t = ipt_find_table_lock(tmp.name, &ret, &ipt_mutex);
if (!t)
goto free_newinfo_counters_untrans;
}
static int
-do_add_counters(void *user, unsigned int len)
+do_add_counters(void __user *user, unsigned int len)
{
unsigned int i;
struct ipt_counters_info tmp, *paddc;
goto free;
}
- t = find_table_lock(tmp.name, &ret, &ipt_mutex);
+ t = ipt_find_table_lock(tmp.name, &ret, &ipt_mutex);
if (!t)
goto free;
}
static int
-do_ipt_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len)
+do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
int ret;
}
static int
-do_ipt_get_ctl(struct sock *sk, int cmd, void *user, int *len)
+do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
break;
}
name[IPT_TABLE_MAXNAMELEN-1] = '\0';
- t = find_table_lock(name, &ret, &ipt_mutex);
+ t = ipt_find_table_lock(name, &ret, &ipt_mutex);
if (t) {
struct ipt_getinfo info;
int *hotdrop)
{
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- char opt[60 - sizeof(struct tcphdr)];
+ u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
unsigned int i;
duprintf("tcp_match: finding option\n");
+
+ if (!optlen)
+ return invert;
+
/* If we don't have the whole header, drop packet. */
- if (skb_copy_bits(skb, skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
- opt, optlen) < 0) {
+ op = skb_header_pointer(skb,
+ skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
+ optlen, _opt);
+ if (op == NULL) {
*hotdrop = 1;
return 0;
}
for (i = 0; i < optlen; ) {
- if (opt[i] == option) return !invert;
- if (opt[i] < 2) i++;
- else i += opt[i+1]?:1;
+ if (op[i] == option) return !invert;
+ if (op[i] < 2) i++;
+ else i += op[i+1]?:1;
}
return invert;
int offset,
int *hotdrop)
{
- struct tcphdr tcph;
+ struct tcphdr _tcph, *th;
const struct ipt_tcp *tcpinfo = matchinfo;
if (offset) {
#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
- if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+ th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+ sizeof(_tcph), &_tcph);
+ if (th == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil TCP offset=0 tinygram.\n");
}
if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
- ntohs(tcph.source),
+ ntohs(th->source),
!!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
return 0;
if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
- ntohs(tcph.dest),
+ ntohs(th->dest),
!!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
return 0;
- if (!FWINVTCP((((unsigned char *)&tcph)[13] & tcpinfo->flg_mask)
+ if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
== tcpinfo->flg_cmp,
IPT_TCP_INV_FLAGS))
return 0;
if (tcpinfo->option) {
- if (tcph.doff * 4 < sizeof(tcph)) {
+ if (th->doff * 4 < sizeof(_tcph)) {
*hotdrop = 1;
return 0;
}
- if (!tcp_find_option(tcpinfo->option, skb, tcph.doff*4 - sizeof(tcph),
+ if (!tcp_find_option(tcpinfo->option, skb,
+ th->doff*4 - sizeof(_tcph),
tcpinfo->invflags & IPT_TCP_INV_OPTION,
hotdrop))
return 0;
int offset,
int *hotdrop)
{
- struct udphdr udph;
+ struct udphdr _udph, *uh;
const struct ipt_udp *udpinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
return 0;
- if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+ uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+ sizeof(_udph), &_udph);
+ if (uh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil UDP tinygram.\n");
}
return port_match(udpinfo->spts[0], udpinfo->spts[1],
- ntohs(udph.source),
+ ntohs(uh->source),
!!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
- ntohs(udph.dest),
+ ntohs(uh->dest),
!!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
}
int offset,
int *hotdrop)
{
- struct icmphdr icmph;
+ struct icmphdr _icmph, *ic;
const struct ipt_icmp *icmpinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
return 0;
- if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph)) < 0){
+ ic = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+ sizeof(_icmph), &_icmph);
+ if (ic == NULL) {
/* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
+ * can't. Hence, no choice but to drop.
+ */
duprintf("Dropping evil ICMP tinygram.\n");
*hotdrop = 1;
return 0;
return icmp_type_code_match(icmpinfo->type,
icmpinfo->code[0],
icmpinfo->code[1],
- icmph.type, icmph.code,
+ ic->type, ic->code,
!!(icmpinfo->invflags&IPT_ICMP_INV));
}
return 0;
}
+static inline int print_target(const struct ipt_target *t,
+ off_t start_offset, char *buffer, int length,
+ off_t *pos, unsigned int *count)
+{
+ if (t == &ipt_standard_target || t == &ipt_error_target)
+ return 0;
+ return print_name((char *)t, start_offset, buffer, length, pos, count);
+}
+
static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
{
off_t pos = 0;
if (down_interruptible(&ipt_mutex) != 0)
return 0;
- LIST_FIND(&ipt_target, print_name, void *,
+ LIST_FIND(&ipt_target, print_target, struct ipt_target *,
offset, buffer, length, &pos, &count);
up(&ipt_mutex);
EXPORT_SYMBOL(ipt_do_table);
EXPORT_SYMBOL(ipt_register_target);
EXPORT_SYMBOL(ipt_unregister_target);
+EXPORT_SYMBOL(ipt_find_target_lock);
module_init(init);
module_exit(fini);