/* * Raise an interrupt upon each target skb, so that its contents can * be mangled. * * Copyright(c) 2015 Jason Tang * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include #include #include #include #include #include #include /* defined in arch/x86/kernel/irq.c */ extern int trigger_irq(unsigned); #define FILTER_IRQ 6 static DEFINE_SPINLOCK(payload_lock); static DECLARE_COMPLETION(payload_processed); static char *payload_data; static size_t payload_length; static bool filter_on; /** * filter_enable() - start filtering * * This device will start raising interrupts when packets arrive. */ void filter_enable(void) { filter_on = true; } EXPORT_SYMBOL(filter_enable); /** * filter_disable() - stop filtering * * This device will stop raising interrupts when packets arrive. */ void filter_disable(void) { filter_on = false; } EXPORT_SYMBOL(filter_disable); /** * filter_resume() - reenable interrupt generation on the filter * * Assuming that filtering is enabled, this device will raise an * interrupt the next time a packet arrives. */ void filter_resume(void) { complete(&payload_processed); } EXPORT_SYMBOL(filter_resume); /** * filter_get_payload() - retrieve the most recent payload * * @len: pointer to where to write the payload length * Return: modifiable buffer to payload */ char *filter_get_payload(size_t * len) { *len = payload_length; return payload_data; } EXPORT_SYMBOL(filter_get_payload); /** * filter_tg() - perform packet mangling * * For each skb, if it is a TCP packet then raise an interrupt. */ static unsigned int filter_tg(struct sk_buff *skb, const struct xt_action_param *par) { struct iphdr *iph = ip_hdr(skb); u8 hdr_len; if (!filter_on || !iph || iph->protocol != IPPROTO_TCP) return XT_CONTINUE; hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); if (skb->len > hdr_len) { spin_lock(&payload_lock); payload_length = skb->len - hdr_len; payload_data = skb->data + hdr_len; trigger_irq(FILTER_IRQ); wait_for_completion_interruptible(&payload_processed); reinit_completion(&payload_processed); spin_unlock(&payload_lock); } return XT_CONTINUE; } static struct xt_target filter_tg_reg __read_mostly = { .name = "LOG", .family = NFPROTO_IPV4, .target = filter_tg, .targetsize = sizeof(struct xt_log_info), .table = "mangle", .me = THIS_MODULE, }; static int __init filter_init(void) { return xt_register_target(&filter_tg_reg); } static void __exit filter_exit(void) { xt_unregister_target(&filter_tg_reg); } module_init(filter_init); module_exit(filter_exit); MODULE_DESCRIPTION("CS421 Packet Mangler"); MODULE_LICENSE("GPL");