zoukankan      html  css  js  c++  java
  • Netfilter 之 iptable_mangle

    初始化

    iptable_mangle_table_init函数通过调用ipt_register_table完成mangle表注册和钩子函数注册的功能;该流程与iptable_filter的函数调用的函数一致,此处不再重复分析,详情请移步<iptable_filter分析>;

     1 static int __net_init iptable_mangle_table_init(struct net *net)
     2 {
     3     struct ipt_replace *repl;
     4     int ret;
     5 
     6     /* 已经初始化 */
     7     if (net->ipv4.iptable_mangle)
     8         return 0;
     9 
    10     /* 分配初始化用于下面注册的结构 */
    11     repl = ipt_alloc_initial_table(&packet_mangler);
    12     if (repl == NULL)
    13         return -ENOMEM;
    14     /* 注册表和钩子函数 */
    15     ret = ipt_register_table(net, &packet_mangler, repl, mangle_ops,
    16                  &net->ipv4.iptable_mangle);
    17     kfree(repl);
    18     return ret;
    19 }
    钩子函数

    从下面的钩子函数可以看到其分布于全部5个钩子点;

    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为mangle钩子函数,如果当前是处于LOCAL_OUT钩子点,则需要调用ip_mangle_out函数,其他店则调用ipt_do_table进行规则匹配;ipt_do_table函数此处不再重复分析,详情请移步<iptable_filter分析>;

     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首先保存ip头部的一些信息,然后调用ipt_do_table进行规则匹配,规则之后检查ip头中的保存字段是否发生变化,如果发生变化,则需要重新查路由;

     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     ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
    27     /* Reroute for ANY change. */
    28     /* 经过规则后 */
    29     if (ret != NF_DROP && ret != NF_STOLEN) {
    30         iph = ip_hdr(skb);
    31 
    32         /* 判断ip头中的字段是否有改变 */
    33         if (iph->saddr != saddr ||
    34             iph->daddr != daddr ||
    35             skb->mark != mark ||
    36             iph->tos != tos) {
    37             /* 重新查路由 */
    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 }
  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11755756.html
Copyright © 2011-2022 走看看