Commit 1d1de89b authored by David S. Miller's avatar David S. Miller

netfilter: Use nf_hook_state in nf_queue_entry.

That way we don't have to reinstantiate another nf_hook_state
on the stack of the nf_reinject() path.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cfdfab31
...@@ -12,12 +12,8 @@ struct nf_queue_entry { ...@@ -12,12 +12,8 @@ struct nf_queue_entry {
unsigned int id; unsigned int id;
struct nf_hook_ops *elem; struct nf_hook_ops *elem;
u_int8_t pf; struct nf_hook_state state;
u16 size; /* sizeof(entry) + saved route keys */ u16 size; /* sizeof(entry) + saved route keys */
unsigned int hook;
struct net_device *indev;
struct net_device *outdev;
int (*okfn)(struct sk_buff *);
/* extra space to store route keys */ /* extra space to store route keys */
}; };
......
...@@ -94,7 +94,7 @@ static void nf_ip_saveroute(const struct sk_buff *skb, ...@@ -94,7 +94,7 @@ static void nf_ip_saveroute(const struct sk_buff *skb,
{ {
struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->hook == NF_INET_LOCAL_OUT) { if (entry->state.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;
...@@ -109,7 +109,7 @@ static int nf_ip_reroute(struct sk_buff *skb, ...@@ -109,7 +109,7 @@ static int nf_ip_reroute(struct sk_buff *skb,
{ {
const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->hook == NF_INET_LOCAL_OUT) { if (entry->state.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 &&
......
...@@ -84,7 +84,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, ...@@ -84,7 +84,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb,
{ {
struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->hook == NF_INET_LOCAL_OUT) { if (entry->state.hook == NF_INET_LOCAL_OUT) {
const struct ipv6hdr *iph = ipv6_hdr(skb); const struct ipv6hdr *iph = ipv6_hdr(skb);
rt_info->daddr = iph->daddr; rt_info->daddr = iph->daddr;
...@@ -98,7 +98,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, ...@@ -98,7 +98,7 @@ static int nf_ip6_reroute(struct sk_buff *skb,
{ {
struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->hook == NF_INET_LOCAL_OUT) { if (entry->state.hook == NF_INET_LOCAL_OUT) {
const struct ipv6hdr *iph = ipv6_hdr(skb); const 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) ||
......
...@@ -47,11 +47,13 @@ EXPORT_SYMBOL(nf_unregister_queue_handler); ...@@ -47,11 +47,13 @@ EXPORT_SYMBOL(nf_unregister_queue_handler);
void nf_queue_entry_release_refs(struct nf_queue_entry *entry) void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
{ {
struct nf_hook_state *state = &entry->state;
/* Release those devices we held, or Alexey will kill me. */ /* Release those devices we held, or Alexey will kill me. */
if (entry->indev) if (state->in)
dev_put(entry->indev); dev_put(state->in);
if (entry->outdev) if (state->out)
dev_put(entry->outdev); dev_put(state->out);
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
...@@ -70,13 +72,15 @@ EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); ...@@ -70,13 +72,15 @@ EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
/* Bump dev refs so they don't vanish while packet is out */ /* Bump dev refs so they don't vanish while packet is out */
bool nf_queue_entry_get_refs(struct nf_queue_entry *entry) bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
{ {
struct nf_hook_state *state = &entry->state;
if (!try_module_get(entry->elem->owner)) if (!try_module_get(entry->elem->owner))
return false; return false;
if (entry->indev) if (state->in)
dev_hold(entry->indev); dev_hold(state->in);
if (entry->outdev) if (state->out)
dev_hold(entry->outdev); dev_hold(state->out);
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
...@@ -131,11 +135,7 @@ int nf_queue(struct sk_buff *skb, ...@@ -131,11 +135,7 @@ int nf_queue(struct sk_buff *skb,
*entry = (struct nf_queue_entry) { *entry = (struct nf_queue_entry) {
.skb = skb, .skb = skb,
.elem = elem, .elem = elem,
.pf = state->pf, .state = *state,
.hook = state->hook,
.indev = state->in,
.outdev = state->out,
.okfn = state->okfn,
.size = sizeof(*entry) + afinfo->route_key_size, .size = sizeof(*entry) + afinfo->route_key_size,
}; };
...@@ -168,7 +168,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) ...@@ -168,7 +168,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
struct sk_buff *skb = entry->skb; struct sk_buff *skb = entry->skb;
struct nf_hook_ops *elem = entry->elem; struct nf_hook_ops *elem = entry->elem;
const struct nf_afinfo *afinfo; const struct nf_afinfo *afinfo;
struct nf_hook_state state;
int err; int err;
rcu_read_lock(); rcu_read_lock();
...@@ -182,33 +181,28 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) ...@@ -182,33 +181,28 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
} }
if (verdict == NF_ACCEPT) { if (verdict == NF_ACCEPT) {
afinfo = nf_get_afinfo(entry->pf); afinfo = nf_get_afinfo(entry->state.pf);
if (!afinfo || afinfo->reroute(skb, entry) < 0) if (!afinfo || afinfo->reroute(skb, entry) < 0)
verdict = NF_DROP; verdict = NF_DROP;
} }
state.hook = entry->hook; entry->state.thresh = INT_MIN;
state.thresh = INT_MIN;
state.pf = entry->pf;
state.in = entry->indev;
state.out = entry->outdev;
state.okfn = entry->okfn;
if (verdict == NF_ACCEPT) { if (verdict == NF_ACCEPT) {
next_hook: next_hook:
verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook], verdict = nf_iterate(&nf_hooks[entry->state.pf][entry->state.hook],
skb, &state, &elem); skb, &entry->state, &elem);
} }
switch (verdict & NF_VERDICT_MASK) { switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT: case NF_ACCEPT:
case NF_STOP: case NF_STOP:
local_bh_disable(); local_bh_disable();
entry->okfn(skb); entry->state.okfn(skb);
local_bh_enable(); local_bh_enable();
break; break;
case NF_QUEUE: case NF_QUEUE:
err = nf_queue(skb, elem, &state, err = nf_queue(skb, elem, &entry->state,
verdict >> NF_VERDICT_QBITS); verdict >> NF_VERDICT_QBITS);
if (err < 0) { if (err < 0) {
if (err == -ECANCELED) if (err == -ECANCELED)
......
...@@ -314,13 +314,13 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, ...@@ -314,13 +314,13 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
if (entskb->tstamp.tv64) if (entskb->tstamp.tv64)
size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
if (entry->hook <= NF_INET_FORWARD || if (entry->state.hook <= NF_INET_FORWARD ||
(entry->hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) (entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL))
csum_verify = !skb_csum_unnecessary(entskb); csum_verify = !skb_csum_unnecessary(entskb);
else else
csum_verify = false; csum_verify = false;
outdev = entry->outdev; outdev = entry->state.out;
switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) {
case NFQNL_COPY_META: case NFQNL_COPY_META:
...@@ -368,23 +368,23 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, ...@@ -368,23 +368,23 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
return NULL; return NULL;
} }
nfmsg = nlmsg_data(nlh); nfmsg = nlmsg_data(nlh);
nfmsg->nfgen_family = entry->pf; nfmsg->nfgen_family = entry->state.pf;
nfmsg->version = NFNETLINK_V0; nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = htons(queue->queue_num); nfmsg->res_id = htons(queue->queue_num);
nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg)); nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
pmsg = nla_data(nla); pmsg = nla_data(nla);
pmsg->hw_protocol = entskb->protocol; pmsg->hw_protocol = entskb->protocol;
pmsg->hook = entry->hook; pmsg->hook = entry->state.hook;
*packet_id_ptr = &pmsg->packet_id; *packet_id_ptr = &pmsg->packet_id;
indev = entry->indev; indev = entry->state.in;
if (indev) { if (indev) {
#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex))) if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex)))
goto nla_put_failure; goto nla_put_failure;
#else #else
if (entry->pf == PF_BRIDGE) { if (entry->state.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) */
...@@ -414,7 +414,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, ...@@ -414,7 +414,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex)))
goto nla_put_failure; goto nla_put_failure;
#else #else
if (entry->pf == PF_BRIDGE) { if (entry->state.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) */
...@@ -633,8 +633,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) ...@@ -633,8 +633,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
struct nfqnl_instance *queue; struct nfqnl_instance *queue;
struct sk_buff *skb, *segs; struct sk_buff *skb, *segs;
int err = -ENOBUFS; int err = -ENOBUFS;
struct net *net = dev_net(entry->indev ? struct net *net = dev_net(entry->state.in ?
entry->indev : entry->outdev); entry->state.in : entry->state.out);
struct nfnl_queue_net *q = nfnl_queue_pernet(net); struct nfnl_queue_net *q = nfnl_queue_pernet(net);
/* rcu_read_lock()ed by nf_hook_slow() */ /* rcu_read_lock()ed by nf_hook_slow() */
...@@ -647,7 +647,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) ...@@ -647,7 +647,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
skb = entry->skb; skb = entry->skb;
switch (entry->pf) { switch (entry->state.pf) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
break; break;
...@@ -757,11 +757,11 @@ nfqnl_set_mode(struct nfqnl_instance *queue, ...@@ -757,11 +757,11 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
static int static int
dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{ {
if (entry->indev) if (entry->state.in)
if (entry->indev->ifindex == ifindex) if (entry->state.in->ifindex == ifindex)
return 1; return 1;
if (entry->outdev) if (entry->state.out)
if (entry->outdev->ifindex == ifindex) if (entry->state.out->ifindex == ifindex)
return 1; return 1;
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) { if (entry->skb->nf_bridge) {
......
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