Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux network stack : adding protocols with an LKM and dev_add_pack

I have recently been trying to familiarize myself with the Linux Networking stack and device drivers (have both similarly named O'Reilly books) with the eventual goal of offloading UDP. I have already implemented UDP on the NIC but now the hard part...

Rather than ask for assistance on this larger goal I was hoping someone could clarify for me a particular snippet I found that is part of a LKM which registeres a new protocol (OTP) that acts as a filter between the device driver and network stack.

http://www.phrack.org/archives/55/p55_0x0c_Building%20Into%20The%20Linux%20Network%20Layer_by_lifeline%20&%20kossak.txt

(Note: this Phrack article contains three different modules, code for the OTP is at the bottom of the page)

In the init function of his example he has:

    otp_proto.type = htons(ETH_P_ALL); 
    otp_proto.func = otp_func;
    dev_add_pack(&otp_proto);

which (if I understand correctly) should register otp_proto as a packet sniffer and put it into the ptype_all data structure. My question is about the dev_add_pack.

Is it the case that the protocol being registered as a filter will always be placed at this layer between L2 and the device driver? Or, for instance could I make such a filtering occur between the application and transport layers (analyze socket parameters) using the same process?

I apologize if this is confusing - I am having some trouble wrapping my head around the bigger picture when it comes to modules altering kernel stack functionality.

Thanks

like image 585
Andrew G Avatar asked May 12 '10 20:05

Andrew G


2 Answers

When you register a protocol handler with dev_add_pack, the handler callback function will be called when a packet arrives. This is how the IP protocol handler works. From inet_init:

static int __init inet_init(void)
{
    ...
    rc = proto_register(&tcp_prot, 1);
    ...
    rc = proto_register(&udp_prot, 1);
    ...
    dev_add_pack(&ip_packet_type);
    ....

When an interrupt is raised by the NIC for a packet that arrives, the NIC interrupt handler will run, which will end up calling netif_rx (or __napi_schedule), which will raise softirq net_rx_action. This will end up calling deliver_skb for each protocol handler registered. From __netif_receive_skb_core

static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
    ...
    list_for_each_entry_rcu(ptype, &ptype_all, list) {
        if (pt_prev)
            ret = deliver_skb(skb, pt_prev, orig_dev);
        pt_prev = ptype;
    }

So yes, your protocol handler callback function will be called on L2, together with ip_rcv for the IP protocol handler.

You can register a protocol handler at L3 with 'proto_register', if you want to be called at that layer.

like image 161
Jay Medina Avatar answered Jan 03 '23 00:01

Jay Medina


Is it the case that the protocol being registered as a filter will always be placed at this layer between L2 and the device driver? Or, for instance could I make such a filtering occur between the application and transport layers (analyze socket parameters) using the same process?

Yes. .func() of the package type you registered is called in __netif_receive_skb(), before the rx handler of the device handles it.

like image 28
Cong Wang Avatar answered Jan 03 '23 00:01

Cong Wang