2007年3月28日 星期三

wiki 語法

== 大標題 ==

前面會多*
*
**

編號
#
## 第二層

內部連結
[[名稱]] 新開一個空白頁
[[image:圖片名稱]] 可上傳一個直接顯示的圖片 (需用帳號login)
[[media:檔案名稱]] 可上傳檔案(如ppt檔) (需用帳號login)

外部連結
[URL 說明]

不想被排版可以用
....

不想用wiki語法可以用....

其他詳細請參閱
http://meta.wikimedia.org/wiki/Help:Contents

2007年3月20日 星期二

Netfilter Hooks in the Linux Kernel

Netfilter Hooks in the Linux Kernel
http://hmyblog.vmmatrix.net/lna/0131777203_ch19lev1sec3.html

想要徹底了解 Netfilter NAT的 kernel data structure, 看這幾篇文章就對了

http://hmyblog.vmmatrix.net/lna/0131777203_ch21.html
http://hmyblog.vmmatrix.net/lna/0131777203_ch21.html
http://hmyblog.vmmatrix.net/lna/0131777203_ch21.html

packet flow in the linux kernel
http://imagestream.com/~josh/PacketFlow-new.png
http://xkr47.outerspace.dyndns.org/netfilter/packet_flow/packet_flow9.png
http://en.wikipedia.org/wiki/Image:Iptables_packet_traversal.pdf
http://www.shorewall.net/images/Netfilter.png
http://dmiessler.com/images/DM_NF.PNG
http://linux-ip.net/nf/nfk-traversal.pdf

Programmer Need to know

The Linux Programmer's Guide
http://www.tldp.org/LDP/lpg/node1.html


C Programming Notes
http://www.eskimo.com/~scs/cclass/int/top.html

Programming in C
UNIX System Calls and Subroutines using C.
http://www.cs.cf.ac.uk/Dave/C/

Various program examples
http://www.londoncomputing.com/linux.html


Free Linux Books
http://www.techbooksforfree.com/linux.shtml

CLDP
http://www.techbooksforfree.com/linux.shtml


一篇介紹 C Programming 很完整的且清楚的文章
How C Programming Works
http://computer.howstuffworks.com/c.htm/printable

一堆 C Programming 教學檔案 (slides, pdf...)
Teachers' Guide to
Practical C++ Programming
http://www.oualline.com/teach/index.html

Pointers
http://www.cplusplus.com/doc/tutorial/pointers.html
http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html

kernel timer_list usage

include/linux/timer.h
struct timer_list {
struct list_head entry;
unsigned long expires;

spinlock_t lock;
unsigned long magic;

void (*function)(unsigned long);
unsigned long data;

struct tvec_t_base_s *base;
};


kernel/timer.c
struct tvec_t_base_s {
spinlock_t lock;
unsigned long timer_jiffies;
struct timer_list *running_timer;
tvec_root_t tv1;
tvec_t tv2;
tvec_t tv3;
tvec_t tv4;
tvec_t tv5;
} ____cacheline_aligned_in_smp;

typedef struct tvec_t_base_s tvec_base_t;




The processing of timer_list

1. Init

init_timer(apptimeout)

/***
* init_timer - initialize a timer.
* @timer: the timer to be initialized
*
* init_timer() must be done to a timer prior calling *any* of the
* other timer functions.
*/
static inline void init_timer(struct timer_list * timer)
{
timer->base = NULL;
timer->magic = TIMER_MAGIC;
spin_lock_init(&timer->lock);
}

2. setup the independent field of timer_list (include data, function, expires..)
apptimeout.data = (unsigned long)master_conntrack;
apptimeout.function = free_appdata_by_timeout;
apptimeout.expires = jiffies + layer7_appdata_timeout;

3. add the timer_list
add_timer(apptimeout);

static inline void add_timer(struct timer_list * timer)
{
__mod_timer(timer, timer->expires);
}

int __mod_timer(struct timer_list *timer, unsigned long expires)

4. delete the timer_list
del_timer

/***
* del_timer - deactive a timer.
* @timer: the timer to be deactivated
*
* del_timer() deactivates a timer - this works on both active and inactive
* timers.
*
* The function returns whether it has deactivated a pending timer or not.
* (ie. del_timer() of an inactive timer returns 0, del_timer() of an
* active timer returns 1.)
*/
int del_timer(struct timer_list *timer)
{
unsigned long flags;
tvec_base_t *base;

check_timer(timer);

repeat:
base = timer->base;
if (!base)
return 0;
spin_lock_irqsave(&base->lock, flags);
if (base != timer->base) {
spin_unlock_irqrestore(&base->lock, flags);
goto repeat;
}
list_del(&timer->entry);
/* Need to make sure that anybody who sees a NULL base also sees the list ops */
smp_wmb();
timer->base = NULL;
spin_unlock_irqrestore(&base->lock, flags);

return 1;
}

Understand the Linux Makefile system

Makefile 的組成 (compoments)
1. explicit rules
2. implicit rules
3. variable definitions
4. directives
5. comments


1. 利用 origin function 可以知道某一個變數是從何處來的

Example:
ifdef V
ifeq ("$(origin V)", "command line")



The result of this function is a string telling you how the variable variable was defined:

`undefined'
if variable was never defined.
`default'
if variable has a default definition, as is usual with CC and so on. See Variables Used by Implicit Rules. Note that if you have redefined a default variable, the origin function will return the origin of the later definition.
`environment'
if variable was defined as an environment variable and the `-e' option is not turned on (see Summary of Options).
`environment override'
if variable was defined as an environment variable and the `-e' option is turned on (see Summary of Options).
`file'
if variable was defined in a makefile.
`command line'
if variable was defined on the command line.
`override'
if variable was defined with an override directive in a makefile (see The override Directive).
`automatic'
if variable is an automatic variable defined for the execution of the commands for each rule (see Automatic Variables).

C example codes

http://samba.org/junkcode/

http://samba.org/ftp/unpacked/junkcode/

要抓這些檔案, 可以利用 CuteFTP 之類的軟體, 到
ftp.samba.org
account: anonymous

抓 pub/unpacked/junkcode 下面的檔案

pub/ 下面也有很多其他的project

這邊有很多的project 可以參考
http://samba.org/~tridge/

# Samba a SMB file/printer server for Unix.
# rsync a fast file transfer program
# rproxy a neat way to speed up HTTP.
# JitterBug a web based bug tracking system
# KnightCap a learning chess program with a 3D interface
# AP/Linux a port of Linux to the AP1000+ multicomputer. The web pages are way out of date though.
# Various TiVo hacks
# tserver - A simple embedded web server with bourne shell server side scripting
# dbench - A simulation of the Ziff-Davis netbench benchmark
# EVACS - An electronic voting system used in the 2001 ACT elections
# parsort - A parallel sorting algoritm designed for large distributed memory systems
# junkcode - Various bits of random code that haven't found a good home
# PIDL - A perl based IDL compiler (not completed yet)
# mail_scripts - A shell script hack to send/recv email using rsync over ssh
# build_farm - A simple build farm system
# tdb - A fast small db style database with shared access and locking
# picturebook - Sony VAIO picturebook video utilities
# rzip - A very slow but effective large file compressor
# ubench - A simple high-load UDP benchmarker
# wbench - A simple web benchmarker
# ccache - A compiler cache
# fstest - A filesystem corruption test tool
# iprint - possibly the smallest C program that anyone has bothered to package for Debian?

Linux Command - screen

Create a new screen socket (-S 可以輸入這個screen socket 的名稱)
# screen -S screen-socket-name

Show screen socket
# screen -ls
There are screens on:
22161.ttyp9.www (Detached)
24317.ttyph.www (Attached)
24507.ttyph.www (Detached)
3 Sockets in /tmp/screens/S-root.

Enter a detach socket
# screen -dr 22161.ttyp9.www


In the screen window

Edit the title
Ctrl+A A

Enter copy mode (利用copy mode 可以看上面之前秀的資料, 利用keyboard 來 scroll up)
Ctrl + A, [
Copy mode - Column 15 Line 35(+100) (103,35)

要copy 之前, 先利用 [space] 來做copy starting point 定位,
然後再利用 [space] 來做copy ending point 定位

當離開copy mode 之後, 可以利用
ctrl+A, ] 來 貼上剛才所存的 screen buffer (利用space 定位所存的screen buffer)


show all the available screen windows
Ctrl + A "

On-Line Help
Ctrl + A ?



另外有一個重點就是, 當 screen 與 linux/bsd minicom 共用時,
原先 minicom 的 Ctrl+A P 組合鍵要改成 Ctrl+A A P
亦即原先的組合鍵

Ctrl+A X
都要改成
Ctrl+A A X

才可以work

// Change screen cut-paste mode scrollback buffer size
1. Enter scrollback command mode: Ctrl+A :
2. change scrollback buffer size: scrollback num

Regions/ Multiple Windows in Screen

ctrl a S  //split current window. Leaves bottom screen empty
ctrl a //tab between regions/split screens
ctrl a Q //unsplit all windows from screen

Set the screen status bar

vi $HOME/.screenrc

caption string "%w"
hardstatus on
hardstatus alwayslastline
hardstatus string "%w%=%m/%d %c"

一堆好用的 network applications

整理的很詳細, 包括各種適用平台, 以及該軟體的介紹(包含一些常用的 network library)

http://www.stearns.org/doc/pcap-apps.html


packetfactory 所出產的也很豐富
http://www.packetfactory.net/projects/index.html

The following tool can use to detect the current bandwidth of all connected interfaces
http://ibmonitor.sourceforge.net/

Command usage experience as following
./ibmonitor --avg --max --data --bits --bytes --interval 1

iptables 和 ebtables 的關係與封包流程整理一下

PREROUTING
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_FIRST ip_sabotage_in (INT_MIN)
ip_conntrack_standalone.c ip_conntrack_defrag_ops NF_IP_PRI_CONNTRACK_DEFRAG ip_conntrack_defrag (-400)
iptable_raw.c ipt_ops NF_IP_PRI_RAW ipt_hook (-300)
ip_conntrack_standalone.c ip_conntrack_in_ops NF_IP_PRI_CONNTRACK ip_conntrack_in (-200)
iptable_mangle.c ipt_ops NF_IP_PRI_MANGLE ipt_route_hook (-150)
iptable_tproxy.c ip_tproxy_pre_ops -130 ip_tproxy_fn (-130)
ip_nat_standalone.c ip_nat_in_ops NF_IP_PRI_NAT_DST ip_nat_fn (-100)

INPUT
iptable_mangle.c ipt_ops NF_IP_PRI_MANGLE ipt_route_hook (-150)
iptable_filter.c ipt_ops NF_IP_PRI_FILTER ipt_hook (0)
ip_nat_standalone.c ip_nat_local_in_ops NF_IP_PRI_NAT_SRC ip_nat_fn (100)
ip_conntrack_standalone.c ip_conntrack_local_in_ops NF_IP_PRI_LAST-1 ip_confirm (INT_MAX-1)

FORWARD
net/bridge/br_netfilter.c br_nf_ops NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD ip_sabotage_out (-175)
iptable_mangle.c ipt_ops NF_IP_PRI_MANGLE ipt_route_hook (-150)
iptable_filter.c ipt_ops NF_IP_PRI_FILTER ipt_hook (0)

OUTPUT
ip_conntrack_standalone.c ip_conntrack_defrag_local_out_ops NF_IP_PRI_CONNTRACK_DEFRAG ip_conntrack_defrag (-400)
iptable_raw.c ipt_ops NF_IP_PRI_RAW ipt_hook (-300)
ip_conntrack_standalone.c ip_conntrack_local_out_ops NF_IP_PRI_CONNTRACK ip_conntrack_local (-200)
iptable_mangle.c ipt_ops NF_IP_PRI_MANGLE ipt_local_hook (-150)
iptable_tproxy.c ip_tproxy_local_out_ops -130 ip_tproxy_fn (-130)
ip_nat_standalone.c ip_nat_local_out_ops NF_IP_PRI_NAT_DST ip_nat_local_fn (-100)
net/bridge/br_netfilter.c br_nf_ops NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT ip_sabotage_out (-50)
iptable_filter.c ipt_ops NF_IP_PRI_FILTER ipt_hook (0)

POSTROUTING
net/bridge/br_netfilter.c br_nf_ops NF_IP_PRI_FIRST ip_sabotage_out
iptable_tproxy.c ip_tproxy_post_ops -130 ip_tproxy_fn (-130)
iptable_mangle.c ipt_ops NF_IP_PRI_MANGLE ipt_route_hook (-150)
ip_nat_standalone.c ip_nat_out_ops NF_IP_PRI_NAT_SRC ip_nat_out (100)
ip_conntrack_standalone.c ip_conntrack_out_ops NF_IP_PRI_LAST ip_refrag (INT_MAX)

Please refer to the diagram on the http://l7-filter.sourceforge.net/PacketFlow.png

enum nf_ip_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK_DEFRAG = -400,
NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225,
NF_IP_PRI_CONNTRACK = -200,
NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
NF_IP_PRI_LAST = INT_MAX,
}; 作者: vincent 時間: 2006-8-4 09:17 PM

bridge path ==> [ebtables|iptables]/table-name HOOK-name

net/core/dev.c
netif_receive_skb
net/bridge/br_input.c:
br_handle_frame
net/bridge/netfilter/ebtable_broute.c
ebt_broute
ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, &broute_table); ==> ebtables/BROUTE BROUTING

net/bridge/br_input.c:
br_handle_frame
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish); ==> ebtables/NAT PREROUTING

net/bridge/br_netfilter.c:
br_nf_pre_routing
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/CONNTRACK-DEFRAG PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/RAW PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/CONNTRACK PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/MANGLE PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/TPROXY PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/NAT PREROUTING

net/bridge/br_input.c:
br_flood_forward
net/bridge/br_forward.c:
br_flood_forward
net/bridge/br_forward.c:
br_flood
net/bridge/br_forward.c:
__br_forward
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, br_forward_finish); ==> ebtables/FILTER FORWARD

net/bridge/br_netfilter.c:
br_nf_forward_ip
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), bridge_parent(out), br_nf_forward_finish); ==. iptables/MANGLE FORWARD
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), bridge_parent(out), br_nf_forward_finish); ==. iptables/FILTER FORWARD

NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, skb->dev, br_forward_finish, 1); 作者: vincent 時間: 2006-8-5 10:42 PM


PREROUTING
net/bridge/netfilter/ebtable_nat.c NF_BR_PRI_NAT_DST_BRIDGED ebt_nat_dst (-300)
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_BRNF br_nf_pre_routing (0)


INPUT
net/bridge/netfilter/ebtable_filter.c ebt_ops_filter NF_BR_PRI_FILTER_BRIDGED ebt_hook (-200)
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_BRNF br_nf_local_in (0)


FORWARD
net/bridge/netfilter/ebtable_filter.c ebt_ops_filter NF_BR_PRI_FILTER_BRIDGED ebt_hook (-200)
net/bridge/br_netfilter.c br_nf_ops (NF_BR_PRI_BRN - 1) br_nf_forward_ip (-1)
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_BRN br_nf_forward_arp (0)

OUTPUT
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_FIRST br_nf_local_out (INT_MIN)
net/bridge/netfilter/ebtable_nat.c NF_BR_PRI_NAT_DST_OTHER ebt_nat_dst (100)
net/bridge/netfilter/ebtable_filter.c ebt_ops_filter NF_BR_PRI_FILTER_OTHER ebt_hook (200)

POSTROUTING
net/bridge/netfilter/ebtable_nat.c NF_BR_PRI_NAT_SRC ebt_nat_src (300)
net/bridge/br_netfilter.c br_nf_ops NF_BR_PRI_LAST br_nf_post_routing (INT_MAX)

BROUTING


enum nf_br_hook_priorities {
NF_BR_PRI_FIRST = INT_MIN,
NF_BR_PRI_NAT_DST_BRIDGED = -300,
NF_BR_PRI_FILTER_BRIDGED = -200,
NF_BR_PRI_BRNF = 0,
NF_BR_PRI_NAT_DST_OTHER = 100,
NF_BR_PRI_FILTER_OTHER = 200,
NF_BR_PRI_NAT_SRC = 300,
NF_BR_PRI_LAST = INT_MAX,
}; 作者: vincent 時間: 2006-8-15 10:11 PM

bridge path ==> [ebtables|iptables]/table-name HOOK-name

## BROUTE Chain
net/core/dev.c
netif_receive_skb

net/core/dev.c
handle_bridge

net/core/dev.c
br_handle_frame_hook

/* Here br_handle_frame_hook is a callback function pointer
net/bridge/br.c
br_init
br_handle_frame_hook = br_handle_frame;
include/linux/if_bridge.h:extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
*/

net/bridge/br_input.c:
br_handle_frame

# br_handle_frame will return 1 and terminate terminate the packet traversal travel

net/bridge/netfilter/ebtable_broute.c
ebt_broute
ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, &broute_table); ==> ebtables/BROUTE BROUTING

## PREROUTING Chain
net/bridge/br_input.c:
br_handle_frame
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish); ==> ebtables/NAT PREROUTING
ebt_nat_dst
br_nf_pre_routing

ebtables will traversal Netfilter/Prerouting in the ebtables/PREROUTING after traversal (ebtables/NAT PREROUTING) as follows

// Due to ebtables (PF_BRIDGE) prerouting hook function : br_nf_pre_routing
net/bridge/br_netfilter.c:
br_nf_pre_routing
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/CONNTRACK-DEFRAG PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/RAW PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/CONNTRACK PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/MANGLE PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/TPROXY PREROUTING
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish); ==> iptables/NAT PREROUTING

# (br_nf_pre_routing will always return NF_STOLEN, so the br_handle_frame_finish function doesn;t need to run again!)

net/bridge/br_netfilter.c:
br_nf_pre_routing_finish
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish_bridge, 1);
or
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish, 1);
// No hook currently less than thresh 1

So either run
net/bridge/br_netfilter.c:
br_nf_pre_routing_finish_bridge
or
net/bridge/br_input.c:
br_handle_frame_finish

# This is the final(finished) function of the ebtables / PREROUTING chain
# Because the br_nf_pre_routing return the NF_STOLEN verdict, so we will not run the br_handle_frame_finish function again
net/bridge/br_input.c:
br_handle_frame_finish

//FORWARD path


net/bridge/br_forward.c:
br_flood_forward
net/bridge/br_forward.c:
br_flood
br_flood will call callback function (__packet_hook)
net/bridge/br_forward.c:
__br_forward
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, br_forward_finish); ==> ebtables/FILTER FORWARD
ebt_hook
br_nf_forward_ip
br_nf_forward_arp


net/bridge/br_netfilter.c:
br_nf_forward_ip
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), bridge_parent(out), br_nf_forward_finish);
## it will return NF_STOLEN verdict

net/bridge/br_netfilter.c:
br_nf_forward_arp
NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in, (struct net_device *)out, br_nf_forward_finish);
## it will return NF_STOLEN verdict


net/bridge/br_netfilter.c:
br_nf_forward_ip
ip_sabotage_out
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), bridge_parent(out), br_nf_forward_finish); ==> iptables/MANGLE FORWARD
NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), bridge_parent(out), br_nf_forward_finish); ==> iptables/FILTER FORWARD

# br_nf_forward_ip will return NF_STOLEN verdict

net/bridge/br_netfilter.c:
br_nf_forward_finish
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, skb->dev, br_forward_finish, 1);
// No hook currently less than thresh 1

net/bridge/br_forward.c:
br_forward_finish
NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, br_dev_queue_push_xmit);

ebt_nat_src
br_nf_post_routing

net/bridge/br_netfilter.c:
br_nf_post_routing
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit);
## it will return NF_STOLEN verdict

net/bridge/br_netfilter.c:
br_nf_post_routing
ip_sabotage_out
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit); ==> iptables/TPROXY POSTROUTING
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit); ==> iptables/MANGLE POSTROUTING
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit); ==> iptables/NAT POSTROUTING
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit); ==> iptables/CONNTRACK POSTROUTING

net/bridge/br_forward.c:
br_dev_queue_push_xmit
## return 0