Commit 02f014d8 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: nf_queue: move list_head/skb/id to struct nf_info

Move common fields for queue management to struct nf_info and rename it
to struct nf_queue_entry. The avoids one allocation/free per packet and
simplifies the code a bit.

Alternatively we could add some private room at the tail, but since
all current users use identical structs this seems easier.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7a6c6653
...@@ -270,7 +270,7 @@ extern void nf_invalidate_cache(int pf); ...@@ -270,7 +270,7 @@ extern void nf_invalidate_cache(int pf);
extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);
struct flowi; struct flowi;
struct nf_info; struct nf_queue_entry;
struct nf_afinfo { struct nf_afinfo {
unsigned short family; unsigned short family;
...@@ -278,9 +278,9 @@ struct nf_afinfo { ...@@ -278,9 +278,9 @@ struct nf_afinfo {
unsigned int dataoff, u_int8_t protocol); unsigned int dataoff, u_int8_t protocol);
int (*route)(struct dst_entry **dst, struct flowi *fl); int (*route)(struct dst_entry **dst, struct flowi *fl);
void (*saveroute)(const struct sk_buff *skb, void (*saveroute)(const struct sk_buff *skb,
struct nf_info *info); struct nf_queue_entry *entry);
int (*reroute)(struct sk_buff *skb, int (*reroute)(struct sk_buff *skb,
const struct nf_info *info); const struct nf_queue_entry *entry);
int route_key_size; int route_key_size;
}; };
......
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
#define _NF_QUEUE_H #define _NF_QUEUE_H
/* Each queued (to userspace) skbuff has one of these. */ /* Each queued (to userspace) skbuff has one of these. */
struct nf_info { struct nf_queue_entry {
struct list_head list;
struct sk_buff *skb;
unsigned int id;
struct nf_hook_ops *elem; struct nf_hook_ops *elem;
int pf; int pf;
unsigned int hook; unsigned int hook;
...@@ -11,12 +15,11 @@ struct nf_info { ...@@ -11,12 +15,11 @@ struct nf_info {
int (*okfn)(struct sk_buff *); int (*okfn)(struct sk_buff *);
}; };
#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
/* Packet queuing */ /* Packet queuing */
struct nf_queue_handler { struct nf_queue_handler {
int (*outfn)(struct sk_buff *skb, int (*outfn)(struct nf_queue_entry *entry,
struct nf_info *info,
unsigned int queuenum); unsigned int queuenum);
char *name; char *name;
}; };
...@@ -26,7 +29,6 @@ extern int nf_register_queue_handler(int pf, ...@@ -26,7 +29,6 @@ extern int nf_register_queue_handler(int pf,
extern int nf_unregister_queue_handler(int pf, extern int nf_unregister_queue_handler(int pf,
const struct nf_queue_handler *qh); const struct nf_queue_handler *qh);
extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
extern void nf_reinject(struct sk_buff *skb, struct nf_info *info, extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
unsigned int verdict);
#endif /* _NF_QUEUE_H */ #endif /* _NF_QUEUE_H */
...@@ -123,11 +123,12 @@ struct ip_rt_info { ...@@ -123,11 +123,12 @@ struct ip_rt_info {
u_int8_t tos; u_int8_t tos;
}; };
static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) static void nf_ip_saveroute(const struct sk_buff *skb,
struct nf_queue_entry *entry)
{ {
struct ip_rt_info *rt_info = nf_info_reroute(info); struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (info->hook == NF_INET_LOCAL_OUT) { if (entry->hook == NF_INET_LOCAL_OUT) {
const struct iphdr *iph = ip_hdr(skb); const struct iphdr *iph = ip_hdr(skb);
rt_info->tos = iph->tos; rt_info->tos = iph->tos;
...@@ -136,11 +137,12 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) ...@@ -136,11 +137,12 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
} }
} }
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info) static int nf_ip_reroute(struct sk_buff *skb,
const struct nf_queue_entry *entry)
{ {
const struct ip_rt_info *rt_info = nf_info_reroute(info); const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (info->hook == NF_INET_LOCAL_OUT) { if (entry->hook == NF_INET_LOCAL_OUT) {
const struct iphdr *iph = ip_hdr(skb); const struct iphdr *iph = ip_hdr(skb);
if (!(iph->tos == rt_info->tos if (!(iph->tos == rt_info->tos
......
...@@ -35,13 +35,7 @@ ...@@ -35,13 +35,7 @@
#define NET_IPQ_QMAX 2088 #define NET_IPQ_QMAX 2088
#define NET_IPQ_QMAX_NAME "ip_queue_maxlen" #define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
struct ipq_queue_entry { typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
struct list_head list;
struct nf_info *info;
struct sk_buff *skb;
};
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
...@@ -56,7 +50,7 @@ static LIST_HEAD(queue_list); ...@@ -56,7 +50,7 @@ static LIST_HEAD(queue_list);
static DEFINE_MUTEX(ipqnl_mutex); static DEFINE_MUTEX(ipqnl_mutex);
static void static void
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) ipq_issue_verdict(struct nf_queue_entry *entry, int verdict)
{ {
/* TCP input path (and probably other bits) assume to be called /* TCP input path (and probably other bits) assume to be called
* from softirq context, not from syscall, like ipq_issue_verdict is * from softirq context, not from syscall, like ipq_issue_verdict is
...@@ -64,14 +58,12 @@ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) ...@@ -64,14 +58,12 @@ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
* softirq, e.g. We therefore emulate this by local_bh_disable() */ * softirq, e.g. We therefore emulate this by local_bh_disable() */
local_bh_disable(); local_bh_disable();
nf_reinject(entry->skb, entry->info, verdict); nf_reinject(entry, verdict);
local_bh_enable(); local_bh_enable();
kfree(entry);
} }
static inline void static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry) __ipq_enqueue_entry(struct nf_queue_entry *entry)
{ {
list_add_tail(&entry->list, &queue_list); list_add_tail(&entry->list, &queue_list);
queue_total++; queue_total++;
...@@ -114,10 +106,10 @@ __ipq_reset(void) ...@@ -114,10 +106,10 @@ __ipq_reset(void)
__ipq_flush(NULL, 0); __ipq_flush(NULL, 0);
} }
static struct ipq_queue_entry * static struct nf_queue_entry *
ipq_find_dequeue_entry(unsigned long id) ipq_find_dequeue_entry(unsigned long id)
{ {
struct ipq_queue_entry *entry = NULL, *i; struct nf_queue_entry *entry = NULL, *i;
write_lock_bh(&queue_lock); write_lock_bh(&queue_lock);
...@@ -140,7 +132,7 @@ ipq_find_dequeue_entry(unsigned long id) ...@@ -140,7 +132,7 @@ ipq_find_dequeue_entry(unsigned long id)
static void static void
__ipq_flush(ipq_cmpfn cmpfn, unsigned long data) __ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
{ {
struct ipq_queue_entry *entry, *next; struct nf_queue_entry *entry, *next;
list_for_each_entry_safe(entry, next, &queue_list, list) { list_for_each_entry_safe(entry, next, &queue_list, list) {
if (!cmpfn || cmpfn(entry, data)) { if (!cmpfn || cmpfn(entry, data)) {
...@@ -160,7 +152,7 @@ ipq_flush(ipq_cmpfn cmpfn, unsigned long data) ...@@ -160,7 +152,7 @@ ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
} }
static struct sk_buff * static struct sk_buff *
ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
{ {
sk_buff_data_t old_tail; sk_buff_data_t old_tail;
size_t size = 0; size_t size = 0;
...@@ -217,20 +209,20 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -217,20 +209,20 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->timestamp_sec = tv.tv_sec; pmsg->timestamp_sec = tv.tv_sec;
pmsg->timestamp_usec = tv.tv_usec; pmsg->timestamp_usec = tv.tv_usec;
pmsg->mark = entry->skb->mark; pmsg->mark = entry->skb->mark;
pmsg->hook = entry->info->hook; pmsg->hook = entry->hook;
pmsg->hw_protocol = entry->skb->protocol; pmsg->hw_protocol = entry->skb->protocol;
if (entry->info->indev) if (entry->indev)
strcpy(pmsg->indev_name, entry->info->indev->name); strcpy(pmsg->indev_name, entry->indev->name);
else else
pmsg->indev_name[0] = '\0'; pmsg->indev_name[0] = '\0';
if (entry->info->outdev) if (entry->outdev)
strcpy(pmsg->outdev_name, entry->info->outdev->name); strcpy(pmsg->outdev_name, entry->outdev->name);
else else
pmsg->outdev_name[0] = '\0'; pmsg->outdev_name[0] = '\0';
if (entry->info->indev && entry->skb->dev) { if (entry->indev && entry->skb->dev) {
pmsg->hw_type = entry->skb->dev->type; pmsg->hw_type = entry->skb->dev->type;
pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addrlen = dev_parse_header(entry->skb,
pmsg->hw_addr); pmsg->hw_addr);
...@@ -252,28 +244,17 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -252,28 +244,17 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
} }
static int static int
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
unsigned int queuenum)
{ {
int status = -EINVAL; int status = -EINVAL;
struct sk_buff *nskb; struct sk_buff *nskb;
struct ipq_queue_entry *entry;
if (copy_mode == IPQ_COPY_NONE) if (copy_mode == IPQ_COPY_NONE)
return -EAGAIN; return -EAGAIN;
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL) {
printk(KERN_ERR "ip_queue: OOM in ipq_enqueue_packet()\n");
return -ENOMEM;
}
entry->info = info;
entry->skb = skb;
nskb = ipq_build_packet_message(entry, &status); nskb = ipq_build_packet_message(entry, &status);
if (nskb == NULL) if (nskb == NULL)
goto err_out_free; return status;
write_lock_bh(&queue_lock); write_lock_bh(&queue_lock);
...@@ -307,14 +288,11 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ...@@ -307,14 +288,11 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
err_out_unlock: err_out_unlock:
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
err_out_free:
kfree(entry);
return status; return status;
} }
static int static int
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
{ {
int diff; int diff;
int err; int err;
...@@ -352,7 +330,7 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ...@@ -352,7 +330,7 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
static int static int
ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
{ {
struct ipq_queue_entry *entry; struct nf_queue_entry *entry;
if (vmsg->value > NF_MAX_VERDICT) if (vmsg->value > NF_MAX_VERDICT)
return -EINVAL; return -EINVAL;
...@@ -412,13 +390,13 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg, ...@@ -412,13 +390,13 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg,
} }
static int static int
dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex) dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{ {
if (entry->info->indev) if (entry->indev)
if (entry->info->indev->ifindex == ifindex) if (entry->indev->ifindex == ifindex)
return 1; return 1;
if (entry->info->outdev) if (entry->outdev)
if (entry->info->outdev->ifindex == ifindex) if (entry->outdev->ifindex == ifindex)
return 1; return 1;
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
......
...@@ -57,11 +57,12 @@ struct ip6_rt_info { ...@@ -57,11 +57,12 @@ struct ip6_rt_info {
struct in6_addr saddr; struct in6_addr saddr;
}; };
static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) static void nf_ip6_saveroute(const struct sk_buff *skb,
struct nf_queue_entry *entry)
{ {
struct ip6_rt_info *rt_info = nf_info_reroute(info); struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (info->hook == NF_INET_LOCAL_OUT) { if (entry->hook == NF_INET_LOCAL_OUT) {
struct ipv6hdr *iph = ipv6_hdr(skb); struct ipv6hdr *iph = ipv6_hdr(skb);
rt_info->daddr = iph->daddr; rt_info->daddr = iph->daddr;
...@@ -69,11 +70,12 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) ...@@ -69,11 +70,12 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
} }
} }
static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info) static int nf_ip6_reroute(struct sk_buff *skb,
const struct nf_queue_entry *entry)
{ {
struct ip6_rt_info *rt_info = nf_info_reroute(info); struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (info->hook == NF_INET_LOCAL_OUT) { if (entry->hook == NF_INET_LOCAL_OUT) {
struct ipv6hdr *iph = ipv6_hdr(skb); struct ipv6hdr *iph = ipv6_hdr(skb);
if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
!ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) !ipv6_addr_equal(&iph->saddr, &rt_info->saddr))
......
...@@ -39,13 +39,7 @@ ...@@ -39,13 +39,7 @@
#define NET_IPQ_QMAX 2088 #define NET_IPQ_QMAX 2088
#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
struct ipq_queue_entry { typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
struct list_head list;
struct nf_info *info;
struct sk_buff *skb;
};
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
...@@ -60,16 +54,15 @@ static LIST_HEAD(queue_list); ...@@ -60,16 +54,15 @@ static LIST_HEAD(queue_list);
static DEFINE_MUTEX(ipqnl_mutex); static DEFINE_MUTEX(ipqnl_mutex);
static void static void
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) ipq_issue_verdict(struct nf_queue_entry *entry, int verdict)
{ {
local_bh_disable(); local_bh_disable();
nf_reinject(entry->skb, entry->info, verdict); nf_reinject(entry, verdict);
local_bh_enable(); local_bh_enable();
kfree(entry);
} }
static inline void static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry) __ipq_enqueue_entry(struct nf_queue_entry *entry)
{ {
list_add_tail(&entry->list, &queue_list); list_add_tail(&entry->list, &queue_list);
queue_total++; queue_total++;
...@@ -112,10 +105,10 @@ __ipq_reset(void) ...@@ -112,10 +105,10 @@ __ipq_reset(void)
__ipq_flush(NULL, 0); __ipq_flush(NULL, 0);
} }
static struct ipq_queue_entry * static struct nf_queue_entry *
ipq_find_dequeue_entry(unsigned long id) ipq_find_dequeue_entry(unsigned long id)
{ {
struct ipq_queue_entry *entry = NULL, *i; struct nf_queue_entry *entry = NULL, *i;
write_lock_bh(&queue_lock); write_lock_bh(&queue_lock);
...@@ -138,7 +131,7 @@ ipq_find_dequeue_entry(unsigned long id) ...@@ -138,7 +131,7 @@ ipq_find_dequeue_entry(unsigned long id)
static void static void
__ipq_flush(ipq_cmpfn cmpfn, unsigned long data) __ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
{ {
struct ipq_queue_entry *entry, *next; struct nf_queue_entry *entry, *next;
list_for_each_entry_safe(entry, next, &queue_list, list) { list_for_each_entry_safe(entry, next, &queue_list, list) {
if (!cmpfn || cmpfn(entry, data)) { if (!cmpfn || cmpfn(entry, data)) {
...@@ -158,7 +151,7 @@ ipq_flush(ipq_cmpfn cmpfn, unsigned long data) ...@@ -158,7 +151,7 @@ ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
} }
static struct sk_buff * static struct sk_buff *
ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
{ {
sk_buff_data_t old_tail; sk_buff_data_t old_tail;
size_t size = 0; size_t size = 0;
...@@ -215,20 +208,20 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -215,20 +208,20 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->timestamp_sec = tv.tv_sec; pmsg->timestamp_sec = tv.tv_sec;
pmsg->timestamp_usec = tv.tv_usec; pmsg->timestamp_usec = tv.tv_usec;
pmsg->mark = entry->skb->mark; pmsg->mark = entry->skb->mark;
pmsg->hook = entry->info->hook; pmsg->hook = entry->hook;
pmsg->hw_protocol = entry->skb->protocol; pmsg->hw_protocol = entry->skb->protocol;
if (entry->info->indev) if (entry->indev)
strcpy(pmsg->indev_name, entry->info->indev->name); strcpy(pmsg->indev_name, entry->indev->name);
else else
pmsg->indev_name[0] = '\0'; pmsg->indev_name[0] = '\0';
if (entry->info->outdev) if (entry->outdev)
strcpy(pmsg->outdev_name, entry->info->outdev->name); strcpy(pmsg->outdev_name, entry->outdev->name);
else else
pmsg->outdev_name[0] = '\0'; pmsg->outdev_name[0] = '\0';
if (entry->info->indev && entry->skb->dev) { if (entry->indev && entry->skb->dev) {
pmsg->hw_type = entry->skb->dev->type; pmsg->hw_type = entry->skb->dev->type;
pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr);
} }
...@@ -249,28 +242,17 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) ...@@ -249,28 +242,17 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
} }
static int static int
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
unsigned int queuenum)
{ {
int status = -EINVAL; int status = -EINVAL;
struct sk_buff *nskb; struct sk_buff *nskb;
struct ipq_queue_entry *entry;
if (copy_mode == IPQ_COPY_NONE) if (copy_mode == IPQ_COPY_NONE)
return -EAGAIN; return -EAGAIN;
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL) {
printk(KERN_ERR "ip6_queue: OOM in ipq_enqueue_packet()\n");
return -ENOMEM;
}
entry->info = info;
entry->skb = skb;
nskb = ipq_build_packet_message(entry, &status); nskb = ipq_build_packet_message(entry, &status);
if (nskb == NULL) if (nskb == NULL)
goto err_out_free; return status;
write_lock_bh(&queue_lock); write_lock_bh(&queue_lock);
...@@ -304,14 +286,11 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ...@@ -304,14 +286,11 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
err_out_unlock: err_out_unlock:
write_unlock_bh(&queue_lock); write_unlock_bh(&queue_lock);
err_out_free:
kfree(entry);
return status; return status;
} }
static int static int
ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
{ {
int diff; int diff;
int err; int err;
...@@ -349,7 +328,7 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) ...@@ -349,7 +328,7 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
static int static int
ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
{ {
struct ipq_queue_entry *entry; struct nf_queue_entry *entry;
if (vmsg->value > NF_MAX_VERDICT) if (vmsg->value > NF_MAX_VERDICT)
return -EINVAL; return -EINVAL;
...@@ -409,14 +388,14 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg, ...@@ -409,14 +388,14 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg,
} }
static int static int
dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex) dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{ {
if (entry->info->indev) if (entry->indev)
if (entry->info->indev->ifindex == ifindex) if (entry->indev->ifindex == ifindex)
return 1; return 1;
if (entry->info->outdev) if (entry->outdev)
if (entry->info->outdev->ifindex == ifindex) if (entry->outdev->ifindex == ifindex)
return 1; return 1;
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
......
...@@ -93,7 +93,7 @@ static int __nf_queue(struct sk_buff *skb, ...@@ -93,7 +93,7 @@ static int __nf_queue(struct sk_buff *skb,
unsigned int queuenum) unsigned int queuenum)
{ {
int status; int status;
struct nf_info *info; struct nf_queue_entry *entry;
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
struct net_device *physindev = NULL; struct net_device *physindev = NULL;
struct net_device *physoutdev = NULL; struct net_device *physoutdev = NULL;
...@@ -118,8 +118,8 @@ static int __nf_queue(struct sk_buff *skb, ...@@ -118,8 +118,8 @@ static int __nf_queue(struct sk_buff *skb,
return 1; return 1;
} }
info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC); entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
if (!info) { if (!entry) {
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n", printk(KERN_ERR "OOM queueing packet %p\n",
skb); skb);
...@@ -128,13 +128,20 @@ static int __nf_queue(struct sk_buff *skb, ...@@ -128,13 +128,20 @@ static int __nf_queue(struct sk_buff *skb,
return 1; return 1;
} }
*info = (struct nf_info) { *entry = (struct nf_queue_entry) {
(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn }; .skb = skb,
.elem = list_entry(elem, struct nf_hook_ops, list),
.pf = pf,
.hook = hook,
.indev = indev,
.outdev = outdev,
.okfn = okfn,
};
/* If it's going away, ignore hook. */ /* If it's going away, ignore hook. */
if (!try_module_get(info->elem->owner)) { if (!try_module_get(entry->elem->owner)) {
rcu_read_unlock(); rcu_read_unlock();
kfree(info); kfree(entry);
return 0; return 0;
} }
...@@ -153,8 +160,8 @@ static int __nf_queue(struct sk_buff *skb, ...@@ -153,8 +160,8 @@ static int __nf_queue(struct sk_buff *skb,
dev_hold(physoutdev); dev_hold(physoutdev);
} }
#endif #endif
afinfo->saveroute(skb, info); afinfo->saveroute(skb, entry);
status = qh->outfn(skb, info, queuenum); status = qh->outfn(entry, queuenum);
rcu_read_unlock(); rcu_read_unlock();
...@@ -170,8 +177,8 @@ static int __nf_queue(struct sk_buff *skb, ...@@ -170,8 +177,8 @@ static int __nf_queue(struct sk_buff *skb,
if (physoutdev) if (physoutdev)
dev_put(physoutdev); dev_put(physoutdev);
#endif #endif
module_put(info->elem->owner); module_put(entry->elem->owner);
kfree(info); kfree(entry);
kfree_skb(skb); kfree_skb(skb);
return 1; return 1;
...@@ -220,19 +227,19 @@ int nf_queue(struct sk_buff *skb, ...@@ -220,19 +227,19 @@ int nf_queue(struct sk_buff *skb,
return 1; return 1;
} }
void nf_reinject(struct sk_buff *skb, struct nf_info *info, void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
unsigned int verdict)
{ {
struct list_head *elem = &info->elem->list; struct sk_buff *skb = entry->skb;
struct list_head *elem = &entry->elem->list;
struct nf_afinfo *afinfo; struct nf_afinfo *afinfo;
rcu_read_lock(); rcu_read_lock();
/* Release those devices we held, or Alexey will kill me. */ /* Release those devices we held, or Alexey will kill me. */
if (info->indev) if (entry->indev)
dev_put(info->indev); dev_put(entry->indev);
if (info->outdev) if (entry->outdev)
dev_put(info->outdev); dev_put(entry->outdev);
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge) { if (skb->nf_bridge) {
if (skb->nf_bridge->physindev) if (skb->nf_bridge->physindev)
...@@ -243,7 +250,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, ...@@ -243,7 +250,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
#endif #endif
/* Drop reference to owner of hook which queued us. */ /* Drop reference to owner of hook which queued us. */
module_put(info->elem->owner); module_put(entry->elem->owner);
/* Continue traversal iff userspace said ok... */ /* Continue traversal iff userspace said ok... */
if (verdict == NF_REPEAT) { if (verdict == NF_REPEAT) {
...@@ -252,28 +259,28 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, ...@@ -252,28 +259,28 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
} }
if (verdict == NF_ACCEPT) { if (verdict == NF_ACCEPT) {
afinfo = nf_get_afinfo(info->pf); afinfo = nf_get_afinfo(entry->pf);
if (!afinfo || afinfo->reroute(skb, info) < 0) if (!afinfo || afinfo->reroute(skb, entry) < 0)
verdict = NF_DROP; verdict = NF_DROP;
} }
if (verdict == NF_ACCEPT) { if (verdict == NF_ACCEPT) {
next_hook: next_hook:
verdict = nf_iterate(&nf_hooks[info->pf][info->hook], verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook],
skb, info->hook, skb, entry->hook,
info->indev, info->outdev, &elem, entry->indev, entry->outdev, &elem,
info->okfn, INT_MIN); entry->okfn, INT_MIN);
} }
switch (verdict & NF_VERDICT_MASK) { switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT: case NF_ACCEPT:
case NF_STOP: case NF_STOP:
info->okfn(skb); entry->okfn(skb);
case NF_STOLEN: case NF_STOLEN:
break; break;
case NF_QUEUE: case NF_QUEUE:
if (!__nf_queue(skb, elem, info->pf, info->hook, if (!__nf_queue(skb, elem, entry->pf, entry->hook,
info->indev, info->outdev, info->okfn, entry->indev, entry->outdev, entry->okfn,
verdict >> NF_VERDICT_BITS)) verdict >> NF_VERDICT_BITS))
goto next_hook; goto next_hook;
break; break;
...@@ -281,7 +288,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, ...@@ -281,7 +288,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
kfree_skb(skb); kfree_skb(skb);
} }
rcu_read_unlock(); rcu_read_unlock();
kfree(info); kfree(entry);
return; return;
} }
EXPORT_SYMBOL(nf_reinject); EXPORT_SYMBOL(nf_reinject);
......
...@@ -45,13 +45,6 @@ ...@@ -45,13 +45,6 @@
#define QDEBUG(x, ...) #define QDEBUG(x, ...)
#endif #endif
struct nfqnl_queue_entry {
struct list_head list;
struct nf_info *info;
struct sk_buff *skb;
unsigned int id;
};
struct nfqnl_instance { struct nfqnl_instance {
struct hlist_node hlist; /* global list of queues */ struct hlist_node hlist; /* global list of queues */
atomic_t use; atomic_t use;
...@@ -73,7 +66,7 @@ struct nfqnl_instance { ...@@ -73,7 +66,7 @@ struct nfqnl_instance {
struct list_head queue_list; /* packets in queue */ struct list_head queue_list; /* packets in queue */
}; };
typedef int (*nfqnl_cmpfn)(struct nfqnl_queue_entry *, unsigned long); typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
static DEFINE_RWLOCK(instances_lock); static DEFINE_RWLOCK(instances_lock);
...@@ -212,7 +205,7 @@ instance_destroy(struct nfqnl_instance *inst) ...@@ -212,7 +205,7 @@ instance_destroy(struct nfqnl_instance *inst)
static void static void
issue_verdict(struct nfqnl_queue_entry *entry, int verdict) issue_verdict(struct nf_queue_entry *entry, int verdict)
{ {
QDEBUG("entering for entry %p, verdict %u\n", entry, verdict); QDEBUG("entering for entry %p, verdict %u\n", entry, verdict);
...@@ -222,15 +215,12 @@ issue_verdict(struct nfqnl_queue_entry *entry, int verdict) ...@@ -222,15 +215,12 @@ issue_verdict(struct nfqnl_queue_entry *entry, int verdict)
* softirq, e.g. We therefore emulate this by local_bh_disable() */ * softirq, e.g. We therefore emulate this by local_bh_disable() */
local_bh_disable(); local_bh_disable();
nf_reinject(entry->skb, entry->info, verdict); nf_reinject(entry, verdict);
local_bh_enable(); local_bh_enable();
kfree(entry);
} }
static inline void static inline void
__enqueue_entry(struct nfqnl_instance *queue, __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
struct nfqnl_queue_entry *entry)
{ {
list_add_tail(&entry->list, &queue->queue_list); list_add_tail(&entry->list, &queue->queue_list);
queue->queue_total++; queue->queue_total++;
...@@ -265,10 +255,10 @@ __nfqnl_set_mode(struct nfqnl_instance *queue, ...@@ -265,10 +255,10 @@ __nfqnl_set_mode(struct nfqnl_instance *queue,
return status; return status;
} }
static struct nfqnl_queue_entry * static struct nf_queue_entry *
find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
{ {
struct nfqnl_queue_entry *entry = NULL, *i; struct nf_queue_entry *entry = NULL, *i;
spin_lock_bh(&queue->lock); spin_lock_bh(&queue->lock);
...@@ -292,7 +282,7 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) ...@@ -292,7 +282,7 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
static void static void
nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
{ {
struct nfqnl_queue_entry *entry, *next; struct nf_queue_entry *entry, *next;
spin_lock_bh(&queue->lock); spin_lock_bh(&queue->lock);
list_for_each_entry_safe(entry, next, &queue->queue_list, list) { list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
...@@ -307,7 +297,7 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) ...@@ -307,7 +297,7 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
static struct sk_buff * static struct sk_buff *
nfqnl_build_packet_message(struct nfqnl_instance *queue, nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct nfqnl_queue_entry *entry, int *errp) struct nf_queue_entry *entry, int *errp)
{ {
sk_buff_data_t old_tail; sk_buff_data_t old_tail;
size_t size; size_t size;
...@@ -316,7 +306,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ...@@ -316,7 +306,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct nfqnl_msg_packet_hdr pmsg; struct nfqnl_msg_packet_hdr pmsg;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg; struct nfgenmsg *nfmsg;
struct nf_info *entinf = entry->info;
struct sk_buff *entskb = entry->skb; struct sk_buff *entskb = entry->skb;
struct net_device *indev; struct net_device *indev;
struct net_device *outdev; struct net_device *outdev;
...@@ -336,7 +325,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ...@@ -336,7 +325,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) + nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
outdev = entinf->outdev; outdev = entry->outdev;
spin_lock_bh(&queue->lock); spin_lock_bh(&queue->lock);
...@@ -379,23 +368,23 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ...@@ -379,23 +368,23 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET, NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
sizeof(struct nfgenmsg)); sizeof(struct nfgenmsg));
nfmsg = NLMSG_DATA(nlh); nfmsg = NLMSG_DATA(nlh);
nfmsg->nfgen_family = entinf->pf; nfmsg->nfgen_family = entry->pf;
nfmsg->version = NFNETLINK_V0; nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = htons(queue->queue_num); nfmsg->res_id = htons(queue->queue_num);
pmsg.packet_id = htonl(entry->id); pmsg.packet_id = htonl(entry->id);
pmsg.hw_protocol = entskb->protocol; pmsg.hw_protocol = entskb->protocol;
pmsg.hook = entinf->hook; pmsg.hook = entry->hook;
NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg); NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
indev = entinf->indev; indev = entry->indev;
if (indev) { if (indev) {
tmp_uint = htonl(indev->ifindex); tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER #ifndef CONFIG_BRIDGE_NETFILTER
NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint); NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
#else #else
if (entinf->pf == PF_BRIDGE) { if (entry->pf == PF_BRIDGE) {
/* Case 1: indev is physical input device, we need to /* Case 1: indev is physical input device, we need to
* look for bridge group (when called from * look for bridge group (when called from
* netfilter_bridge) */ * netfilter_bridge) */
...@@ -425,7 +414,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ...@@ -425,7 +414,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
#ifndef CONFIG_BRIDGE_NETFILTER #ifndef CONFIG_BRIDGE_NETFILTER
NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint); NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
#else #else
if (entinf->pf == PF_BRIDGE) { if (entry->pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to /* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from * look for bridge group (when called from
* netfilter_bridge) */ * netfilter_bridge) */
...@@ -504,13 +493,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, ...@@ -504,13 +493,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
} }
static int static int
nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
unsigned int queuenum)
{ {
int status = -EINVAL; int status = -EINVAL;
struct sk_buff *nskb; struct sk_buff *nskb;
struct nfqnl_instance *queue; struct nfqnl_instance *queue;
struct nfqnl_queue_entry *entry;
QDEBUG("entered\n"); QDEBUG("entered\n");
...@@ -526,22 +513,11 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ...@@ -526,22 +513,11 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
goto err_out_put; goto err_out_put;
} }
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL) {
if (net_ratelimit())
printk(KERN_ERR
"nf_queue: OOM in nfqnl_enqueue_packet()\n");
status = -ENOMEM;
goto err_out_put;
}
entry->info = info;
entry->skb = skb;
entry->id = atomic_inc_return(&queue->id_sequence); entry->id = atomic_inc_return(&queue->id_sequence);
nskb = nfqnl_build_packet_message(queue, entry, &status); nskb = nfqnl_build_packet_message(queue, entry, &status);
if (nskb == NULL) if (nskb == NULL)
goto err_out_free; goto err_out_put;
spin_lock_bh(&queue->lock); spin_lock_bh(&queue->lock);
...@@ -577,15 +553,13 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, ...@@ -577,15 +553,13 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
err_out_unlock: err_out_unlock:
spin_unlock_bh(&queue->lock); spin_unlock_bh(&queue->lock);
err_out_free:
kfree(entry);
err_out_put: err_out_put:
instance_put(queue); instance_put(queue);
return status; return status;
} }
static int static int
nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
{ {
int diff; int diff;
int err; int err;
...@@ -630,15 +604,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue, ...@@ -630,15 +604,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
} }
static int static int
dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex) dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{ {
struct nf_info *entinf = entry->info; if (entry->indev)
if (entry->indev->ifindex == ifindex)
if (entinf->indev)
if (entinf->indev->ifindex == ifindex)
return 1; return 1;
if (entinf->outdev) if (entry->outdev)
if (entinf->outdev->ifindex == ifindex) if (entry->outdev->ifindex == ifindex)
return 1; return 1;
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
...@@ -748,7 +720,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, ...@@ -748,7 +720,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
struct nfqnl_msg_verdict_hdr *vhdr; struct nfqnl_msg_verdict_hdr *vhdr;
struct nfqnl_instance *queue; struct nfqnl_instance *queue;
unsigned int verdict; unsigned int verdict;
struct nfqnl_queue_entry *entry; struct nf_queue_entry *entry;
int err; int err;
queue = instance_lookup_get(queue_num); queue = instance_lookup_get(queue_num);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment