一樣看 ipv4 的部份,hook 資訊在 ~/net/ipv4/netfilter/nf_contrack_l3proto_ipv4.c
static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
{
.hook= ipv4_conntrack_in,
.owner= THIS_MODULE,
.pf= NFPROTO_IPV4,
.hooknum= NF_INET_PRE_ROUTING, PRE_ROUTING 會呼叫 ipv4_conntrack_in()
.priority= NF_IP_PRI_CONNTRACK,
},{
NF_INET_LOCAL_OUT 對應 ipv4_conntrack_local
},{
NF_INET_POST_ROUTING 對應 ipv4_confirm
},{
NF_INET_LOCAL_IN 對應 ipv4_confirm
}
{
.hook= ipv4_conntrack_in,
.owner= THIS_MODULE,
.pf= NFPROTO_IPV4,
.hooknum= NF_INET_PRE_ROUTING, PRE_ROUTING 會呼叫 ipv4_conntrack_in()
.priority= NF_IP_PRI_CONNTRACK,
},{
NF_INET_LOCAL_OUT 對應 ipv4_conntrack_local
},{
NF_INET_POST_ROUTING 對應 ipv4_confirm
},{
NF_INET_LOCAL_IN 對應 ipv4_confirm
}
ipv4_conntrack_in() {
return nf_conntrack_in(); ~/net/netfilter/nf_conntrack_core.c
}
return nf_conntrack_in(); ~/net/netfilter/nf_conntrack_core.c
}
nf_conntrack_in() {
if (skb->nfct) { 封包的 conntrack 存在表示這個封包是 loopbak 或是 (untarcked?),直接略過
}
l3proto = __nf_ct_l3proto_find(); ipv4 傳入 PF_INET,ipv6 傳入 PF_INET6,這樣作以後就可以支援更多的第三層協議
ret = l3proto->get_l4proto(); 取得第四層協議編號
if (ret <= 0) {} 不認識的第四層協議就回報錯誤
l4proto = __nf_ct_l4proto_find(); l4 協議實作程式在 ~/net/netfilter/nf_conntrack_proto_XXX.c
例如:nf_conntrack_proto_tcp.c
其 ipv4 的相關資料定義在 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4
其 ipv6 的相關資料定義在 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6
if (l4proto->error != NULL) { 有宣告說要檢查錯誤的協議,->error 指向錯誤檢查 function
ret = l4proto->error(); 檢查封包是不是正常
if (ret <= 0) {} 檢查出錯誤就回報錯誤
}
ct = resolve_normal_ct(); 依據 l3 跟 l4 的協議資料獲取 conntrack
ret = l4proto->packet(); 進行 l4 的 packet
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
nf_conntrack_event_cache(IPCT_REPLY, ct); 設置 contrack event
}
if (skb->nfct) { 封包的 conntrack 存在表示這個封包是 loopbak 或是 (untarcked?),直接略過
}
l3proto = __nf_ct_l3proto_find(); ipv4 傳入 PF_INET,ipv6 傳入 PF_INET6,這樣作以後就可以支援更多的第三層協議
ret = l3proto->get_l4proto(); 取得第四層協議編號
if (ret <= 0) {} 不認識的第四層協議就回報錯誤
l4proto = __nf_ct_l4proto_find(); l4 協議實作程式在 ~/net/netfilter/nf_conntrack_proto_XXX.c
例如:nf_conntrack_proto_tcp.c
其 ipv4 的相關資料定義在 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4
其 ipv6 的相關資料定義在 struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6
if (l4proto->error != NULL) { 有宣告說要檢查錯誤的協議,->error 指向錯誤檢查 function
ret = l4proto->error(); 檢查封包是不是正常
if (ret <= 0) {} 檢查出錯誤就回報錯誤
}
ct = resolve_normal_ct(); 依據 l3 跟 l4 的協議資料獲取 conntrack
ret = l4proto->packet(); 進行 l4 的 packet
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
nf_conntrack_event_cache(IPCT_REPLY, ct); 設置 contrack event
}
resolve_normal_ct() {
if (!nf_ct_get_tuple() {} 先把 tuple 找出來 hash = hash_conntrack_raw() 這兩行再把 hash 找出來
h = __nf_conntrack_find_get()
if (!h) {
h = init_conntrack() 如果沒有找到 hash 就建立一個新的 hash
}
ct = nf_ct_tuplehash_to_ctrack(h); 把 hash 轉成 conntrack
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
方向是 Rep
} else {
方向是 Org,依據 ct->status 區分成三種狀態,ESTABLISHED、RELATED、NEW
} skb->nfct = &ct->ct_general; 這兩行將 ct 訊息回填 skb
skb->nfctinfo = *ctinfo;
}
if (!nf_ct_get_tuple() {} 先把 tuple 找出來 hash = hash_conntrack_raw() 這兩行再把 hash 找出來
h = __nf_conntrack_find_get()
if (!h) {
h = init_conntrack() 如果沒有找到 hash 就建立一個新的 hash
}
ct = nf_ct_tuplehash_to_ctrack(h); 把 hash 轉成 conntrack
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
方向是 Rep
} else {
方向是 Org,依據 ct->status 區分成三種狀態,ESTABLISHED、RELATED、NEW
} skb->nfct = &ct->ct_general; 這兩行將 ct 訊息回填 skb
skb->nfctinfo = *ctinfo;
}
ipv4_conntrack_local() { /* root is playing with raw sockets. */
如果封包長度不符合 ip 的規定,那一定是 root 作 raw sockets 產生的
return nf_conntrack_in() 呼叫 nf_conntrack_in
}
如果封包長度不符合 ip 的規定,那一定是 root 作 raw sockets 產生的
return nf_conntrack_in() 呼叫 nf_conntrack_in
}
ipv4_confirm() { ct = nf_ct_get(skb, &ctinfo); 取得 conntrack
help = nfct_help(ct);
}
help = nfct_help(ct);
}
沒有留言:
張貼留言