#include <linux/spinlock.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
-#include <linux/mutex.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
static unsigned int queue_user_dropped = 0;
static struct sock *ipqnl;
static LIST_HEAD(queue_list);
-static DEFINE_MUTEX(ipqnl_mutex);
+static DECLARE_MUTEX(ipqnl_sem);
static void
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
struct sk_buff *skb;
unsigned int qlen;
- mutex_lock(&ipqnl_mutex);
+ down(&ipqnl_sem);
for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
skb = skb_dequeue(&sk->sk_receive_queue);
kfree_skb(skb);
}
- mutex_unlock(&ipqnl_mutex);
+ up(&ipqnl_sem);
}
static int
.outfn = &ipq_enqueue_packet,
};
-static int __init ip6_queue_init(void)
+static int
+init_or_cleanup(int init)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
+ if (!init)
+ goto cleanup;
+
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
THIS_MODULE);
}
return status;
+cleanup:
+ nf_unregister_queue_handlers(&nfqh);
+ synchronize_net();
+ ipq_flush(NF_DROP);
+
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
cleanup_ipqnl:
sock_release(ipqnl->sk_socket);
- mutex_lock(&ipqnl_mutex);
- mutex_unlock(&ipqnl_mutex);
+ down(&ipqnl_sem);
+ up(&ipqnl_sem);
cleanup_netlink_notifier:
netlink_unregister_notifier(&ipq_nl_notifier);
return status;
}
-static void __exit ip6_queue_fini(void)
+static int __init init(void)
{
- nf_unregister_queue_handlers(&nfqh);
- synchronize_net();
- ipq_flush(NF_DROP);
-
- unregister_sysctl_table(ipq_sysctl_header);
- unregister_netdevice_notifier(&ipq_dev_notifier);
- proc_net_remove(IPQ_PROC_FS_NAME);
-
- sock_release(ipqnl->sk_socket);
- mutex_lock(&ipqnl_mutex);
- mutex_unlock(&ipqnl_mutex);
+
+ return init_or_cleanup(1);
+}
- netlink_unregister_notifier(&ipq_nl_notifier);
+static void __exit fini(void)
+{
+ init_or_cleanup(0);
}
MODULE_DESCRIPTION("IPv6 packet queue handler");
MODULE_LICENSE("GPL");
-module_init(ip6_queue_init);
-module_exit(ip6_queue_fini);
+module_init(init);
+module_exit(fini);