Question

I am writing a kernel module which registers a hook with netfilter. The handler is not being called if I ssh/telnet into the machine where the module is loaded.

struct nf_hook_ops my_hook_ops;
my_hook_ops.hook = hook_handler;
my_hook_ops.pf = PF_INET;
my_hook_ops.hooknum = NF_INET_PRE_ROUTING;
my_hook_ops.priority =  NF_IP_PRI_FIRST;
nf_register_hook(&my_hook_ops);

The handler function:

unsigned int hook_handler(unsigned int hooknum,
                   struct sk_buff *skb,
                   const struct net_device *in,
                   const struct net_device *out,
                   int (*okfn)(struct sk_buff *))
{


    if(!skb)
        return NF_ACCEPT;

    struct iphdr* ip_header;
    struct tcphdr* tcp_header;
    union  ip_address ipaddr;

    printk(KERN_INFO "Entered handler\n");

    if(skb->protocol == 8)
        return NF_ACCEPT;

    // Log the received packet
    ip_header  = ip_hdr(skb);
    tcp_header = tcp_hdr(skb);
    ipaddr.saddr = ip_header->saddr;
    printk(KERN_INFO "Received packet:\nIP Address: %u.%u.%u.%u\nProtocol: %d\nSource port: %d\nDestination port: %d\n",
            ipaddr.a[0],ipaddr.a[1],ipaddr.a[2],ipaddr.a[3],
            skb->protocol,
            tcp_header->source,
            tcp_header->dest);

    return NF_ACCEPT;
}

The hook is being called for protocol 8 (Exterior Gateway Protocol). The second printk never gets printed. Am I missing anything?

Was it helpful?

Solution

The protocol used here is different from the IP protocol number as assigned by IANA, for which 8 is for EGP and EGP has been outdated.

The protocol field for sk_buff is defined in , for which 8 is for ETH_P_IP. As your data is allways IP traffic,the first conditional check is always true. So the second part of code never get executed.

OTHER TIPS

A couple of thoughts:

  • a hook handler takes a (struct skbuff **), not a (struct skbuff *)
  • following on from the above, skb->protocol doesn't exist. You want either (*skb)->protocol or you want the following idiom:
struct sk_buff *sock_buf =  *skb;
if(sock_buff->protocol)
  • If the packet is an EGP packet, you should not be expecting output from the second printk, because you return before it.

You need to study how sk_buff works, the protocol field initialized by the function `eth_type_trans' which takes on ETH_P_* values. All ETH_P_* values are defined in if_ether. Here are some of these values.

#define ETH_P_LOOP      0x0060          /* Ethernet Loopback packet     */
#define ETH_P_PUP       0x0200          /* Xerox PUP packet             */
#define ETH_P_PUPAT     0x0201          /* Xerox PUP Addr Trans packet  */
#define ETH_P_IP        0x0800          /* Internet Protocol packet     */

You clearly see that 0x08 is defined for Internet Protocol packet. And your code clearly return in case of 8 (which is IP packet)

 if(skb->protocol == 8)
    return NF_ACCEPT;

Your ssh/telnet clearly IP packet(s) and rejected by above code. Please use proper protocol defined values defined in if_ethr

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top