#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>

/*
Demonstrates creating a netfilter telnet filter kernel module on Linux (not Mac or Windows).  
Notice it uses printk, not printf!

Author: Tim Pierson, Dartmouth CS60, Fall 2026
		based on an example from "Internet Security: A hands-on approach" by Wenliang Du

Compile:
        make 

Insert module into kernel:
        sudo insmod telnetFilter.ko //module name in Makefile

Check that kernel module is loaded:
        lsmod | grep telnetFilter

Remove module from kernel:
        sudo rmmod telnetFilter
*/

static struct nf_hook_ops telnetFilterHook;


unsigned int telnetFilter(void *priv, struct sk_buff *skb,
                 const struct nf_hook_state *state)
{
  struct iphdr *iph;
  struct tcphdr *tcph;

  iph = ip_hdr(skb);
  tcph = (void *)iph+iph->ihl*4;

  //block TCP on port 23 (telnet)
  if (iph->protocol == IPPROTO_TCP && tcph->dest == htons(23)) {
    printk(KERN_INFO "Dropping telnet packet to %d.%d.%d.%d\n",
        ((unsigned char *)&iph->daddr)[0],
        ((unsigned char *)&iph->daddr)[1],
        ((unsigned char *)&iph->daddr)[2],
        ((unsigned char *)&iph->daddr)[3]);
    return NF_DROP;
  } else {
    return NF_ACCEPT;
  }
}


int setUpFilter(void) {
        printk(KERN_INFO "Registering a Telnet filter.\n");
        telnetFilterHook.hook = telnetFilter; 
        //telnetFilterHook.hooknum = NF_INET_POST_ROUTING;
        telnetFilterHook.hooknum = NF_INET_LOCAL_IN;
        telnetFilterHook.pf = PF_INET;
        telnetFilterHook.priority = NF_IP_PRI_FIRST;

        // Register the hook.
        nf_register_net_hook(&telnetFilterHook); //function is nf_register_hook in Ubuntu 16.04
        return 0;
}

void removeFilter(void) {
        printk(KERN_INFO "Telnet filter is being removed.\n");
        nf_unregister_net_hook(&telnetFilterHook); //function is nf_unregister_hook in Ubuntu 16.04
}

module_init(setUpFilter);
module_exit(removeFilter);

MODULE_LICENSE("GPL");