On Mon, Mar 21, 2016 at 11:23:43AM +0000, Yigal Reiss (yreiss) wrote:
> @@ -582,10 +585,17 @@ __nfqnl_enqueue_packet(struct net *net, struct
> nfqnl_instance *queue,
> *packet_id_ptr = htonl(entry->id);
>
> /* nfnetlink_unicast will either free the nskb or add it to a socket */
> - err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT);
> + err = nfnetlink_unicast_nofree(nskb, net, queue->peer_portid,
> MSG_DONTWAIT);
This keeps nskb around, this skbuff contains the netlink message, not
the network packet itself that is located in entry->skb.
> if (err < 0) {
> - queue->queue_user_dropped++;
> - goto err_out_unlock;
> + if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
> + queue->nobuf_failopened++;
> + failopen = 1;
> + err = 0;
In case we couldn't deliver due to socket buffer overrun, if the
NFQA_CFG_F_FAIL_OPEN flag is set, you set failopen to 1.
> + }
> + else {
> + queue->queue_user_dropped++;
> + }
> + goto err_out_free_nskb;
And finally, jump to err_out_free_nskb.
> }
>
> __enqueue_entry(queue, entry);
> @@ -595,7 +605,6 @@ __nfqnl_enqueue_packet(struct net *net, struct
> nfqnl_instance *queue,
>
> err_out_free_nskb:
> kfree_skb(nskb);
Which just releases the netlink skbuff.
> -err_out_unlock:
> spin_unlock_bh(&queue->lock);
> if (failopen)
> nf_reinject(entry, NF_ACCEPT);
And reinjects the packet.
So isn't the more simple patch that I'm attaching achieving what you need?
Let me know, thanks.
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7542999..cb5b630 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -582,7 +582,12 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
/* nfnetlink_unicast will either free the nskb or add it to a socket */
err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT);
if (err < 0) {
- queue->queue_user_dropped++;
+ if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
+ failopen = 1;
+ err = 0;
+ } else {
+ queue->queue_user_dropped++;
+ }
goto err_out_unlock;
}