Linux Kernel Analysis-network [seven]:netfilter__linux

Source: Internet
Author: User
Tags goto prev
Kernel version: 2.6.34

NetFilter is introduced into the 2.4.x kernel, and becomes the main extension of network application under Linux platform, including not only the implementation of firewall, but also the processing of message (such as message encryption, message classification statistics, etc.). netfilter data structure hook struct nf_hook_ops[net\filter\core.c]

struct Nf_hook_ops {
	struct list_head list;
	/* User fills in from. * *
	NF_HOOKFN *hook;
	struct module *owner;
	u_int8_t PF;
	unsigned int hooknum;
	/* Hooks are ordered in ascending priority. *
	/int priority;
The member list is used to link the global hook array nf_hooks, it must be in the first place, to ensure that the value of &nf_hook_ops->list is the same as &nf_hook_ops, which will be used later in the use of this technique;
A member hook is a user-defined hook function; Owner represents the module that registers this hook function, because the netfilter is kernel space, so it is generally a module to complete the hook function registration; The PF is indexed to a specific protocol-specific number of hook functions queue for indexing nf_ Hooks priority determines the order in which the same queue (PF and hooknum) is the same, and the smaller the priority the more forward the arrangement.
struct Nf_hook_ops just store hooks in the data structure, and the real storage of these hooks for the protocol stack call is nf_hooks, from the definition can be seen, it is actually a two-dimensional array of linked lists.
struct List_head nf_hooks[nfproto_numproto][nf_max_hooks]; [NET\FILTER\CORE.C]
Where Nfproto_numproto represents the protocol associated with the hook, which is desirable:
enum {
	Nfproto_unspec =  0,
	nfproto_ipv4   =  2,
	nfproto_arp    =  3,
	Nfproto_bridge =  7,
	Nfproto_ipv6   = ten,
	nfproto_decnet =,
	nfproto_numproto,
};
The nf_max_hooks represents the location where the tick is applied, and the optional values are defined within each protocol module, which represents the location of the hook function to be applied in the protocol process (later in bridge, for example), which generally has the following values:
	Nf_xxx_pre_routing,
	nf_xxx_local_in,
	nf_xxx_forward,
	nf_xxx_local_out,
	nf_xxx_post_routing ,
	Nf_xxx_numhooks

NetFilter Registration
After understanding the Nf_hook_ops and nf_hooks, look at how to manipulate the elements in Nf_hooks.
Nf_register_hook () registers the Nf_hook_ops in the Nf_hooks:
int Nf_register_hook (struct nf_hook_ops *reg)
{struct Nf_hook_ops
	;
	int err;


	Err = mutex_lock_interruptible (&nf_hook_mutex);
	if (Err < 0) return
		err;
	List_for_each_entry (Elem, &nf_hooks[reg->pf][reg->hooknum], list) {
		if (Reg->priority < elem- >priority) break
			;
	List_add_rcu (®->list, elem->list.prev);
	Mutex_unlock (&nf_hook_mutex);
	return 0;
}
This function is very simple, from the specified pf&hooknum nf_hooks queue traversal, press priority from small to large order, the Reg inserted in the appropriate position, complete the registration of the hook function.

Nf_unregister_hook () cancels the nf_hook_ops from the Nf_hooks:
void Nf_unregister_hook (struct nf_hook_ops *reg)
{
	mutex_lock (&nf_hook_mutex);
	List_del_rcu (®->list);
	Mutex_unlock (&nf_hook_mutex);
	Synchronize_net ();
}
This function is simpler and removes Reg from the nf_hooks.
The kernel also provides nf_register_hooks () and Nf_unregister_hooks () to register the Reg n times or unregister the Reg from the nf_hooks n times. When the hook function is registered, the nf_hooks structure is shown in the figure:

NetFilter CallWhen the message is passed in the kernel protocol stack, the NetFilter module is called to filter the message, so the filter can be seen everywhere in the code.
The above mentioned network Bridge for example, for the Network Bridge processing message, Handle_bridge ()->br_handle_frame (), if the port is processed in the learning or forwarding state, and the message destination address is correct, it will call Br_ Handle_frame () for subsequent processing, and this function call is:
Nf_hook (Pf_bridge, nf_br_pre_routing, SKB, Skb->dev, NULL,
Br_handle_frame_finish);
Nf_hook ()->nf_hook_thresh ()->nf_hook_thresh ()->nf_hook_slow ():
int Nf_hook_slow (u_int8_t pf, unsigned int hook, struct sk_buff-*skb, struct net_device *indev, str
	UCT net_device *outdev, int (*OKFN) (struct Sk_buff *), int hook_thresh) {struct list_head;
	unsigned int verdict;


	int ret = 0;


	/* We may already have this, but read-locks nest anyway * * rcu_read_lock ();
Elem = &nf_hooks[pf][hook]; 
	Next_hook:verdict = Nf_iterate (&nf_hooks[pf][hook], SKB, Hook, Indev, Outdev, &elem, OKFN, Hook_thresh);
	if (verdict = = Nf_accept | | verdict = = nf_stop) {ret = 1;
		else if (verdict = = Nf_drop) {KFREE_SKB (SKB);
	ret =-eperm;
			      else if ((Verdict & nf_verdict_mask) = = Nf_queue) {if!nf_queue (SKB, Elem, pf, Hook, Indev, Outdev, OKFN,
	Verdict >> Nf_verdict_bits)) goto Next_hook;
	} rcu_read_unlock ();
return ret; }
Nf_hook_slow () finds the execution hook queue from the Nf_hooks, executes sequentially, and then decides whether to continue (completed by Nf_iterate ()) based on the return value. The PF and hook in the arguments represent the parameters pf and hooknum that are given when registering the hook function, which together determine which queue of nf_hook to insert in the hook function.
The return value of the hook function as a filter message is noteworthy, and the following values are desirable:
#define NF_DROP 0
#define NF_ACCEPT 1
#define Nf_stolen 2
#define NF_QUEUE 3
#define NF_REPEAT 4
# Define Nf_stop 5
First, take the Nf_iterate () function as an example, Elem->hook () indicates that the hook function is executed and the execution structure is verdict.
unsigned int nf_iterate (...)
{
	unsigned int verdict;


	List_for_each_continue_rcu (*i, head) {
		struct nf_hook_ops *elem = (struct nf_hook_ops *) *i;
		if (Hook_thresh > Elem->priority)
			continue;
		Verdict = Elem->hook (Hook, SKB, Indev, Outdev, OKFN);
		if (verdict!= nf_accept) {
			if (verdict!= Nf_repeat) return
				verdict;
			*i = (*i)->prev;
		}
	}
	return nf_accept;
}
Depending on the return of Nf_iterate (), there are the following:
1. If the result is nf_accept, indicates that the hook function allows the message to continue to be processed downward, at which point the next hook function on the queue should continue, because these hook functions are filtered to the same class of messages in the same position, the first pass, and can not return, and all functions are executed, the result is still nf_ Accept, you can return it;
2. If the result is nf_repeat, it means to repeat the hook function once; so the hook function is written properly, otherwise the message executes a hook function that returns NF_REPEAET, and when the return value is nf_repeat, it does not return;
3. If the other result, you do not have to execute other functions on the queue, return it directly, such as nf_stop to stop execution of the hook function on the queue, direct return; Nf_drop to discard the message; Nf_stolen means that messages are no longer passed on, unlike Nf_drop, It does not invoke KFREE_SKB () to release the Skb;nf_queue check whether a given protocol (PF) has a queue handler function, and then to dispose of it or throw it away.
Understanding these values and looking at the processing of the Nf_iterate () return value in Nf_hook_slow () is clear:
if (verdict = = Nf_accept | | verdict = = nf_stop) {
	ret = 1;
} else if (verdict = Nf_drop) {
	kfree_skb (SKB); 
  ret =-eperm;
} else if ((Verdict & nf_verdict_mask) = = Nf_queue) {
	if (!nf_queue (SKB, Elem, pf, Hook, Indev, Outdev, OKFN,
			 ve Rdict >> nf_verdict_bits))
		goto Next_hook;
Finally, bridge to explain the meaning of the next hooks parameter, which has been said, it determines where the hook function is invoked in the protocol process, because the purpose of using NetFilter is to process the message in the kernel state, and where to process the message can only be defined by the kernel. Generally speaking, the kernel will add the hook function processing in the key position of the message sending and receiving, find out the Nf_hook in the code to know. Here's a bridge, for example, to see where it is used and what these values mean:
The existence of netfilter makes it possible and simple to handle the user-defined requirements of a message in kernel space. In general, write good struct nf_hook_ops, where Hook/pf/hook is a required parameter, and then use Nf_register_hook to register on it. The entire filter file can write a kernel module, dynamic loading with insmod.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.