Linux核心Bridge程式碼
阿新 • • 發佈:2018-12-18
註冊
module_init(br_init)
static int __init br_init(void)
{
...
err = br_netfilter_init();
...
br_handle_frame_hook = br_handle_frame; // 設定br_handle_frame_hook為br_handle_frame
...
}
int __init br_netfilter_init(void)
{
...
ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
...
}
static struct nf_hook_ops br_nf_ops[] __read_mostly = {
{
.hook = br_nf_pre_routing,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_PRE_ROUTING,
.priority = NF_BR_PRI_BRNF,
},
{
.hook = br_nf_local_in,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_LOCAL_IN,
.priority = NF_BR_PRI_BRNF,
},
{
.hook = br_nf_forward_ip,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_BRNF - 1,
},
{
.hook = br_nf_forward_arp,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_BRNF,
},
{
.hook = br_nf_local_out,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_LOCAL_OUT,
.priority = NF_BR_PRI_FIRST,
},
{
.hook = br_nf_post_routing,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_POST_ROUTING,
.priority = NF_BR_PRI_LAST,
},
{
.hook = ip_sabotage_in,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
},
{
.hook = ip_sabotage_in,
.owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP6_PRI_FIRST,
},
};
資料流
以rx為例,eth0收到skb後通過netif_receive_skb()上送協議棧,netif_receive_skb()呼叫handle_bridge(),handle_bridge()判斷skb->dev->br_port是否非空(eth0是否橋接),若是,呼叫br_handle_frame_hook()即br_handle_frame(),經過ebtables的NF_BR_PRE_ROUTING鏈時呼叫br_nf_pre_routing(),經過iptables的NF_INET_PRE_ROUTING鏈後呼叫br_nf_pre_routing_finish(),再次經過ebtables的NF_BR_PRE_ROUTING鏈,由於NF_BR_PRI_BRNF = 0 < 1,因此不呼叫br_nf_pre_routing(),直接呼叫br_handle_frame_finish() 在br_handle_frame_finish()中分兩種情況: 1、skb的dmac地址是本機地址:在br_pass_frame_up()中修改skb->dev為網橋,重新交給netif_receive_skb(),此時skb->dev->br_port為空,不走橋接邏輯,直接上送ip_rcv() 2、其它:在br_forward()中轉發
int netif_receive_skb(struct sk_buff *skb)
{
...
skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
...
}
static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
struct packet_type **pt_prev, int *ret,
struct net_device *orig_dev)
{
...
return br_handle_frame_hook(port, skb);
}
struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
{
...
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish);
...
}
static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
...
if (!setup_pre_routing(skb)) // 標記BRNF_NF_BRIDGE_PREROUTING
return NF_DROP;
...
NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
br_nf_pre_routing_finish);
return NF_STOLEN;
...
}
static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
if (skb->nf_bridge &&
!(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { // 檢查標記NF_BR_PRE_ROUTING
return NF_STOP;
}
return NF_ACCEPT;
}
static int br_nf_pre_routing_finish(struct sk_buff *skb)
{
...
nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; // 取消標記NF_BR_PRE_ROUTING
...
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish, 1);
...
}
int br_handle_frame_finish(struct sk_buff *skb)
{
...
br_pass_frame_up(br, skb2); // 本地
...
br_forward(dst->dst, skb); // 轉發
...
}
static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
{
...
// 修改skb->dev為網橋
skb->dev = brdev;
...
// 重新交給netif_receive_skb()
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
netif_receive_skb);
}
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
...
__br_forward(to, skb);
...
}
static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
...
// 修改skb->dev為出裝置
skb->dev = to->dev;
...
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
br_forward_finish);
}