You can know from the notes in the packet receiving process that, in the netif_receive_skb function of the packet processing function, we will first check whether there is a registered protocol in ptype_all. If yes, we will call the corresponding processing function, then go to ptype_base, find the appropriate protocol, and send the SKB to the processing function of the relevant protocol. for example, IP protocol (ip_rcv) or ARP (arp_rcv. this document describes ptype_all and ptype_base. ptype_base and ptype_all are stored in the kernel. For example, we can see that ptype_base is a hash table and ptype_all is a two-way linked list. each Protocol registered in it is represented by a struct packet_type. struct packet_type {unsigned short type;/* protocol type */struct net_device * dev; int (* func) (struct sk_buf F *, struct net_device *, struct packet_type *); void * data;/* private to the packet type */struct packet_type * Next;}; Note the dev parameter, this parameter indicates that the Protocol only processes data from Dev to device. When Dev = NULL, this Protocol processes data from all devices. in this way, when registering your own protocol, you can specify the device you want to listen to or receive. the function for registering and canceling the protocol is dev_add_pack (...) and dev_remove_pack (...) these two functions are simple: void dev_add_pack (struct packet_type * PT) {int hash; br_write_lock_bh (br_netproto_lock); # ifdef config_n Et_fastroute/* hack to detect PACKET socket */If (Pt-> data) & (INT) (Pt-> data )! = 1) {netdev_fastroute_obstacles ++; dev_clear_fastroute (Pt-> Dev) ;}# endif if (Pt-> type = htons (eth_p_all) {netdev_nit ++; pt-> next = ptype_all; ptype_all = pt;} else {hash = ntohs (Pt-> type) & 15; Pt-> next = ptype_base [hash]; ptype_base [hash] = pt;} br_write_unlock_bh (br_netproto_lock);} This function judges the protocol type and adds it to ptype_base or ptype_all. void dev_remove_pack (struct packet_type * PT) {struct packet_type ** pt1; br_writ E_lock_bh (br_netproto_lock); If (Pt-> type = htons (eth_p_all) {netdev_nit --; pt1 = & ptype_all ;} else {pt1 = & ptype_base [ntohs (Pt-> type) & 15] ;}for (; (* pt1 )! = NULL; pt1 = & (* pt1)-> next) {If (Pt = (* pt1) {* pt1 = Pt-> next; # ifdef config_net_fastroute if (Pt-> data) then --; # endif Merge (br_netproto_lock); Return ;}} Merge (br_netproto_lock); printk (kern_warning "dev_remove_pack: % P not found. \ n ", pt);} this function is also very simple, just remove the protocol from the related linked list. the following uses the IP protocol as an example to see the implementation: the IP protocol struct is defined as follows: static struct packet_type ip_packet_type = {_ constant_htons (eth_p_ip), null,/* all devices */ip_rcv, (void *) 1, null,}; when the IPv4 protocol stack is initialized, ip_init is called. all packets whose protocol type is eth_p_ip will be processed by ip_rcv. code: void _ init ip_init (void) {dev_add_pack (& ip_packet_type); ip_rt_init (); done (); # ifdef config_ip_multicast proc_net_create ("IGMP", 0, done ); # endif} after the system starts, the IP protocol is registered to the ptype_base linked list. The corresponding processing function is ip_rcv.arp and other types of protocols (in ptype_base or ptype_all) the execution process is the same as that. I am a beginner in the Internet, and I am very grateful if I have any errors. PS1: I remember when I first came to the lab, the first method of the packet capture module was to use netfilter, and the second method was mainly to use this knowledge. now, I think it's still simple, but it took a long time for me to think about it. It's really difficult, and it's not difficult to come here. when I was reading a book today, I found another method to meet my requirements, which was recorded on PS2. PS2: another method for packet capture at the data link layer: Use pf_packet socket type. linux can directly intercept or inject data from the link layer using this type of character. send data directly to dev_queue_xmit. the receiving function can be intercepted before the data packet passes the routing. for example, tcpdump and ethereal both use this socket. we can conclude that there are at least three methods to intercept data packets. The first netfilter is to intercept data packets in the protocol stack, the method of using ptype_all or ptype_base and the subsequent character sets is to intercept data packets at the link layer.