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&a开发者_运维技巧mp;%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
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.
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.
精彩评论