Basic structure of Netfilter

xiaoxiao2021-03-06  22

Basic structure of Netfilter

(1) It can be seen from the transmission and receiving process of the IP package. After the IP packet receiver (IP_RCV) receives the correct IP package, first inject "routing front filter" (NF_IP_PRE_ROUTING), the routing front filter (NF_IP_PRE_ROUTING) Output (IP_RCV_FINISHI) Pack After the binding routing and compiles the IP optionspace, enter the route entry (DST-> INPUT). For local receiving packets, the route entry points to the IP local distributor (IP_LOCAL_DELIVER), and the local distribution is first performed by IP fragmentation. The IP synthetic packet is then injected into the "local input filter" (NF_IP_LOCAL_IN), the output of the local input filter (IP_LOCAL_DELIVER_FINISH) packet is further passed to the IP transport protocol controller (IGMP_RCV, TCP_V4_RCV, UDP_RCV, ICMP_RCV), and the last package is delivered to The receiving queue of each socket. For forwarding packets, the route entry will point to the IP repeater (ip_forward), and the forwarder is injected into the "IP forwarding filter" (NF_IP_FORWARD) after the IP package, and the output of the forward filter (IP_forward_finish) is over-slice Injecting the "IP Routing Filter" (NF_IP_POST_ROUTING) by routing export (NF_IP_POST_ROUTING), the output (IP_FINISH_OUTPUT2) package is created by the neighbor exit (DST-> neighbour-> output) Create a hardware frame head call neigh_resolve_output Output or create a frame header directly from DST-> hh-> hh_output in IP_FINISH_OUTPUT2. Enter the queuing emission in the package scheduler (dev_queue_xmit).

For local send packets, the output package generated by the IP package generator is first injected into the "local output filter" (nf_ip_local_out)

The output of the local filter (OUTPUT_MAYBE_REROUTE) is passed through the excessive piece (IP_Fragment), and then transmits the package from DST-> OUTPUT by routing outlet.

(2) NF_HOOKS_OPS structure description, all network packet filters in the system are registered in the hook chain array (NF_HOOKs) of the network filter, which is a two-dimensional chain head (list_head) indexed with the network protocol number and filter number. The structural array, each element in the array represents a filter chain. The network filter is inserted into the code with NF_HOOK (Family, NUM, SKB, INDEV, OUTDEV, OUTPUT) macro. When executed to NF_HOOK (), if the NF_HOOKS [Family] [NUM] filter chain is non-empty, the system will call NF_HOOK_SLOW (Family, NUM, SKB, INDEV, OUTDEV, OUTPUT) to pass the package sequentially to the filtering function in the filter chain. . On each of the filtration, if the filter function returns NF_ACCEPT, the filter package allows the output. At this time, the filter package will inject the next link filter or call the Output parameter function to output the filter package. If the filter function returns NF_DROP, the filtering process is terminated, the filter package is prohibited from output and released. If the filter function returns NF_STOLEN, the input package has been transferred, and the filter is not output. If the filter function returns NF_REPEAT, the filter package will be refined once. If the filter function returns NF_QUEUE. The current filtering parameters and input packets will be processed in the filter queue of the filter protocol family to perform processing (Queue_Handler).

Include / Linux / Netfilter.h: #define NF_HOOK (PF, HOOK, SKB, INDEV, OUTDEV, OKFN) / (List_empty (& NF_HOOKS [(PF)] [(hook)] /? (OKFN) (SKB) /: nf_hook_slow ((pf), (hook), (skb), (indev), (outdev), (okfn))) # endif / * Largest hook number 1 * / # define NF_MAX_HOOKS 8typedef unsigned int nf_hookfn (unsigned int hooknum, struct sk_buff ** skb, const struct net_device * in, const struct net_device * out, int (* okfn) (struct sk_buff *)); struct nf_hook_ops {struct list_head list; / * User fills in from here down * / nf_hookfn *. Hook; Filter function int Pf; Filter's protocol Int hooknum; filter number / * hooks are orderled in assending priority. * / int priority; filter priority, filter of the same protocol is arranged as a priority value} ;. / * Each queued (to userspace) skbuff has one of these * / struct nf_info {/ * The ops struct which sent us to userspace * / struct nf_hook_ops * elem;. / * If we're sent to userspace, this keeps Housekeeping Info * / INT PF; unsigned int hook; struct net_device * indev, * Outdev; int (* okfn) (Struct SK_Buff *);}; net / core / netf ilter.c: struct list_head nf_hooks [NPROTO] [NF_MAX_HOOKS]; / * * A queue handler may be registered for each protocol Each is protected by * long term mutex The handler must provide an an outfn () to accept packets * for.. queueing and must reinject all packets it receives, no matter what * / static struct nf_queue_handler_t. {nf_queue_outfn_t outfn; void * data;} queue_handler [NPROTO]; typedef int (* nf_queue_outfn_t) (struct sk_buff * skb, struct nf_info * info, void * data) ;; net / core / netfilter.c: int nf_hook_slow (int pf, unsigned int hook, struct sk_buff * skb, struct net_device * indev, struct net_device * outdev, int (* okfn) (struct sk_buff *)) { Struct List_Head * ELEM; unsigned int verdict; int RET = 0;

/ * We may already have this, but read-locks nest anyway * / br_read_lock_bh (BR_NETPROTO_LOCK); # ifdef CONFIG_NETFILTER_DEBUG if (skb-> nf_debug & (1 << hook)) {printk ( "nf_hook: hook% i already set. / N ", hook; nf_dump_skb (pf, skb);} SKB-> nf_debug | = (1 << hook); # endif elem = & nf_hooks [pf] [hook]; verdict = nf_iterate (& nf_hook [pf] [hook ], & SKB, HOOK, INDEV, OUTDEV, & ELEM, OKFN; IF (Verdict == nf_queue) {nfdebug ("nf_hook: verdict = queue./N"); NF_QUEUE (SKB, ELEM, PF, HOOK, INDEV, OUTDEV , okfn);} switch (verdict) {case NF_ACCEPT: ret = okfn (skb); break; case NF_DROP: kfree_skb (skb); ret = -EPERM; break;} br_read_unlock_bh (BR_NETPROTO_LOCK); return ret;} static unsigned int nf_iterate (struct list_head * head, struct sk_buff ** skb, int hook, const struct net_device * indev, const struct net_device * outdev, struct list_head ** i, int (* okfn) (struct sk_buff *)) {for filter iterator (* i = (* i) -> next; * i! = head; * i = (* i) -> Next) {Turpse of the scan filter Struct NF_HOOK _OPS * ELEM = (Struct NF_HOOK_OPS *) * i; Take the filter structure Switch (Elem-> Hook (Hook, SKB, INDEV, OUTDEV, OKFN) {Call Filter Function Case NF_QUEUE: Return NF_QUEUE; Case NF_STOLEN: RETURN NF_STOLEN Case nf_drop: return nf_drop; case nf_repeat: * i = (* i) -> prev; break; #ifdef config_netfilter_debug case nf_accept: break; default: NFDebug ("Evil Return FROM% P (% u) ./ n", ELEM -> hook, hook; # endif}} return nf_accept;

} / * * Any packet that leaves via this function must come back * through nf_reinject (). * / Static void nf_queue (struct sk_buff * skb, struct list_head * elem, int pf, unsigned int hook, struct net_device * indev, struct net_device * OUTDEV, INT (* OKFN)) {int status; struct nf_info * info; if (! queue_handler [pf] .outfn) {kfree_skb (SKB); Return;} info = kmalloc (* info) ), Gfp_atomic); if (! Info) {if (Net_RATELIMIT ()) Printk (kern_err "oom queueing packet% p / n", SKB); kfree_skb (SKB); return;} * info = (Struct nf_info) { Struct nf_hook_ops *) ELEM, PF, HOOK, INDEV, OUTDEV, OKFN}; Save Filter Parameters / * Bump dev REFS SO The Don't Vanish While Packet Is Out * / if (Indev) DEV_HOLD (INDEV); if (Outdev) DEV_HOLD (OUTDEV); status = queue_handler [pf] .outfn (SKB, INFO, Queue_Handler [PF] .data); if (status <0) {/ * james m doesn't Say [censored] enough. * / if ( Indev) DEV_PUT (INDEV); if (Outdev) DEV_PUT (OUTDEV); Kfree (INFO); KFree_SKB (SKB); Return;}} Void NF_R EINJECT (Struct SK_BUFF * SKB, STRUCT NF_INFO * INFO, UNSIGNED INT VERDICT) Re-injects the filter {structure list_head * elem = & info-> elem-> list; struct list_head * i; / * We don 'T HAVE BR_NETPROTO_LOCK Here * / BR_READ_LOCK_BH (BR_NETPROTO_LOCK); for (i = nf_hook [info-> pf] [info-> hook] .next; i! = elem; i = i-> next) {if (i == & nf_hooks [info-> pf] [info-> hook]) {/ * the module which Sent It to userspace is gone. * / nfdebug ("% s: module disappeared, __function__); verdict = NF_Drop; Break;}} / * Continue Traversal iff userspace said ok ... * / if (verdict == nf_repeat) {ELEM = ELEM-> Prev; Verdict = NF_ACCEPT;

} if (verdict == nf_accept) {verdict = nf_iterate (& nf_hook [info-> pf] [info-> hook], & SKB, Info-> Hook, Info-> Indev, Info-> Outdev, & elem, info-> okfn } switch (verdict) {case nf_accept: info-> okfn (SKB); break; case nf_queue: nf_queue (SKB, ELEM, INFO-> PF, Info-> Hook, Info-> Indev, Info-> Outdev, info-> okfn); break; case NF_DROP:. kfree_skb (skb); break;} br_read_unlock_bh (BR_NETPROTO_LOCK); / * Release those devices we held, or Alexey will kill me * / if (info-> indev) dev_put (info -> indev); if (info-> outdev) dev_put (info-> outdev); kfree (info); return;} int nf_register_hook (struct nf_hook_ops * reg) filter registration {struct list_head * i; br_write_lock_bh (BR_NETPROTO_LOCK); For (i = nf_hook [reg-> pf] [reg-> hooknum] .next; i! = & nf_hooks [reg-> pf] [reg-> hooknum]; i = i-> next) {if (reg-> priority <((struct nf_hook_ops *) i) -> priority) break;} list_add (®-> list, i-> prev); br_write_unlock_bh (BR_NETPROTO_LOCK); return 0;} void nf_unregister_hook (struct nf_hook_ops * reg) {br_write_lock_b h (BR_NETPROTO_LOCK); list_del (®-> list); br_write_unlock_bh (BR_NETPROTO_LOCK);} int nf_register_queue_handler (int pf, nf_queue_outfn_t outfn, void * data) registered by filtration queue processor {int ret; br_write_lock_bh (BR_NETPROTO_LOCK); if (queue_handler [ pf] .outfn) ret = -EBUSY; else {queue_handler [pf] .outfn = outfn; queue_handler [pf] .data = data; ret = 0;} br_write_unlock_bh (BR_NETPROTO_LOCK); return ret;} / * The caller must flush THEIR Queue Before THIS * / INT NF_UNREGISTER_QUE_HANDLER (INT PF) {br_write_lock_bh (br_netproto_lock); queue_handler [pf] .outfn = null; queue_handler [pf] .DATA = null;

转载请注明原文地址:https://www.9cbs.com/read-40274.html

New Post(0)