initialization
iptable_mangle_table_init function by calling ipt_register_table complete mangle table registration and registration function hook function; the same functions and function calls the process iptable_filter, the analysis will not be repeated here, please venue <iptable_filter analysis>;
. 1 static int __net_init iptable_mangle_table_init ( struct NET * NET) 2 { . 3 struct ipt_replace * the repl; . 4 int RET; . 5 . 6 / * initialized * / . 7 IF (NET -> ipv4.iptable_mangle) . 8 return 0 ; . 9 10 / * allocate used to register the following structural initialization * / . 11 the repl = ipt_alloc_initial_table (& packet_mangler); 12 is IF (the repl == NULL) 13 is return -ENOMEM; 14 / * registry and hook function * / 15 RET = ipt_register_table (NET, & packet_mangler, the repl, mangle_ops, 16 & NET -> ipv4.iptable_mangle); . 17 kfree (the repl); 18 is return RET; . 19 }
Hook function
From the following hook function which can be seen in all five hooks distributed points;
1 #define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \ 2 (1 << NF_INET_LOCAL_IN) | \ 3 (1 << NF_INET_FORWARD) | \ 4 (1 << NF_INET_LOCAL_OUT) | \ 5 (1 << NF_INET_POST_ROUTING))
1 static const struct xt_table packet_mangler = { 2 .name = "mangle", 3 .valid_hooks = MANGLE_VALID_HOOKS, 4 .me = THIS_MODULE, 5 .af = NFPROTO_IPV4, 6 .priority = NF_IP_PRI_MANGLE, 7 .table_init = iptable_mangle_table_init, 8 };
iptable_mangle_hook to mangle hook function, if the current is in LOCAL_OUT hook point, you need to call ip_mangle_out function, other shop is called ipt_do_table match is performed; ipt_do_table function analysis is not repeated here, please venue <iptable_filter analysis>;
1 static unsigned int 2 iptable_mangle_hook(void *priv, 3 struct sk_buff *skb, 4 const struct nf_hook_state *state) 5 { 6 /* LOCAL_OUT钩子点,调用mangle_out */ 7 if (state->hook == NF_INET_LOCAL_OUT) 8 return ipt_mangle_out(skb, state); 9 /* 规则匹配 */ 10 return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); 11 }
ipt_mangle_out first save some information about ip header, then call ipt_do_table match is performed, check the ip header after the rule change field is saved, if changes occur, you need to re-check the routing;
1 static unsigned int 2 ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) 3 { 4 unsigned int ret; 5 const struct iphdr *iph; 6 u_int8_t tos; 7 __be32 saddr, daddr; 8 u_int32_t mark; 9 int err; 10 11 /* root is playing with raw sockets. */ 12 /* 原始套接字 */ 13 if (skb->len < sizeof(struct iphdr) || 14 ip_hdrlen(skb) < sizeof(struct iphdr)) 15 return NF_ACCEPT; 16 17 /* Save things which could affect route */ 18 19 mark = skb->mark; 20 iph = ip_hdr(skb); 21 saddr = iph->saddr; 22 daddr = iph->daddr; 23 tos = iph->tos; 24 25 /* 进行规则匹配 */ 26 = ipt_do_table RET (SKB, State, State-> NET -> ipv4.iptable_mangle); 27 / * . Reroute for the ANY Change * / 28 / * After the rule * / 29 IF (!! && NF_DROP causes RET RET = = NF_STOLEN) { 30 IPH = ip_hdr (SKB); 31 is 32 / * is determined whether ip header fields have changed * / 33 is iF ! (iph-> || the saddr the saddr = 34 is ! iph-> DADDR = DADDR || 35 skb-> Mark! = || Mark 36 iph-> TOS! = TOS) { 37 [ / * re-route search * / 38 err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); 39 if (err < 0) 40 ret = NF_DROP_ERR(err); 41 } 42 } 43 44 return ret; 45 }