亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 4550 | 回復(fù): 0
打印 上一主題 下一主題

netfilter之規(guī)則執(zhí)行ipt_do_table [復(fù)制鏈接]

論壇徽章:
1
天蝎座
日期:2014-02-28 16:08:53
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2009-11-03 15:01 |只看該作者 |倒序瀏覽

                                                               
前面說到了netfilter的規(guī)則表的保存,是由struct xt_table中的鏈表來鏈接的。而具體數(shù)據(jù)則是在struct xt_table_info結(jié)構(gòu)體中,而struct xt_table_info結(jié)構(gòu)中又有struct ipt_ip結(jié)構(gòu)保存相關(guān)的規(guī)則的ip地址信息。struct ipt_entry結(jié)構(gòu)體的作用則要在下面的代碼中找出作用。
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
    301 unsigned int
    302 ipt_do_table(struct sk_buff *skb,
    303          unsigned int hook,
    304          const struct net_device *in,
    305          const struct net_device *out,
    306          struct xt_table *table)
    307 {
    308     static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
    309     const struct iphdr *ip;
    310     u_int16_t datalen;
    311     bool hotdrop = false;
    312     /* Initializing verdict to NF_DROP keeps gcc happy. */
    313     unsigned int verdict = NF_DROP;
    314     const char *indev, *outdev;
    315     void *table_base;
    316     struct ipt_entry *e, *back;
    317     struct xt_table_info *private;
    318     struct xt_match_param mtpar;
    319     struct xt_target_param tgpar;
    320
    321     /* Initialization */
    322     ip = ip_hdr(skb);
    323     datalen = skb->len - ip->ihl * 4;
    324     indev = in ? in->name : nulldevname;
    325     outdev = out ? out->name : nulldevname;
    326     /* We handle fragments by dealing with the first fragment as
    327      * if it was a normal packet.  All other fragments are treated
    328      * normally, except that they will NEVER match rules that ask
    329      * things we don't know, ie. tcp syn flag or ports).  If the
    330      * rule is also a fragment-specific rule, non-fragments won't
    331      * match it. */
    332     mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
    333     mtpar.thoff   = ip_hdrlen(skb);
    334     mtpar.hotdrop = &hotdrop;
    335     mtpar.in      = tgpar.in  = in;
    336     mtpar.out     = tgpar.out = out;
    337     mtpar.family  = tgpar.family = NFPROTO_IPV4;
    338     tgpar.hooknum = hook;
    339
    340     IP_NF_ASSERT(table->valid_hooks & (1  hook));
    341     xt_info_rdlock_bh();
    342     private = table->private;
    343     table_base = private->entries[smp_processor_id()];
    344
    345     e = get_entry(table_base, private->hook_entry[hook]);
    346
    347     /* For return from builtin chain */
    348     back = get_entry(table_base, private->underflow[hook]);
    349
    350     do {
    351         IP_NF_ASSERT(e);
    352         IP_NF_ASSERT(back);
    353         if (ip_packet_match(ip, indev, outdev,
    354             &e->ip, mtpar.fragoff)) {
    355             struct ipt_entry_target *t;
    356
    357             if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
    358                 goto no_match;
    359
    360             ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
    361
    362             t = ipt_get_target(e);
    363             IP_NF_ASSERT(t->u.kernel.target);
    364
    365 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
    366     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
    367             /* The packet is traced: log it */
    368             if (unlikely(skb->nf_trace))
    369                 trace_packet(skb, hook, in, out,
    370                          table->name, private, e);
    371 #endif
    372             /* Standard target? */
    373             if (!t->u.kernel.target->target) {
    374                 int v;
    375
    376                 v = ((struct ipt_standard_target *)t)->verdict;
    377                 if (v  0) {
    378                     /* Pop from stack? */
    379                     if (v != IPT_RETURN) {
    380                         verdict = (unsigned)(-v) - 1;
    381                         break;
    382                     }
    383                     e = back;
    384                     back = get_entry(table_base,
    385                              back->comefrom);
    386                     continue;
    387                 }
    388                 if (table_base + v != (void *)e + e->next_offset
    389                     && !(e->ip.flags & IPT_F_GOTO)) {
    390                     /* Save old back ptr in next entry */
    391                     struct ipt_entry *next
    392                         = (void *)e + e->next_offset;
    393                     next->comefrom
    394                         = (void *)back - table_base;
    395                     /* set back pointer to next entry */
    396                     back = next;
    397                 }
    398
    399                 e = get_entry(table_base, v);
    400             } else {
    401                 /* Targets which reenter must return
    402                    abs. verdicts */
    403                 tgpar.target   = t->u.kernel.target;
    404                 tgpar.targinfo = t->data;
    405 #ifdef CONFIG_NETFILTER_DEBUG
    406                 ((struct ipt_entry *)table_base)->comefrom
    407                     = 0xeeeeeeec;
    408 #endif
    409                 verdict = t->u.kernel.target->target(skb,
    410                                      &tgpar);
    411 #ifdef CONFIG_NETFILTER_DEBUG
    412                 if (((struct ipt_entry *)table_base)->comefrom
    413                     != 0xeeeeeeec
    414                     && verdict == IPT_CONTINUE) {
    415                     printk("Target %s reentered!\n",
    416                            t->u.kernel.target->name);
    417                     verdict = NF_DROP;
    418                 }
    419                 ((struct ipt_entry *)table_base)->comefrom
    420                     = 0x57acc001;
    421 #endif
    422                 /* Target might have changed stuff. */
    423                 ip = ip_hdr(skb);
    424                 datalen = skb->len - ip->ihl * 4;
    425
    426                 if (verdict == IPT_CONTINUE)
    427                     e = (void *)e + e->next_offset;
    428                 else
    429                     /* Verdict */
    430                     break;
    431             }
    432         } else {
    433
    434         no_match:
    435             e = (void *)e + e->next_offset;
    436         }
    437     } while (!hotdrop);
    438     xt_info_rdunlock_bh();
    439
    440 #ifdef DEBUG_ALLOW_ALL
    441     return NF_ACCEPT;
    442 #else
    443     if (hotdrop)
    444         return NF_DROP;
    445     else return verdict;
    446 #endif
    447 }
首先在
               
               
               
    316         struct ipt_entry *e, *back;
      317         struct xt_table_info *private;
      341     xt_info_rdlock_bh();
    342     private = table->private;
    343     table_base = private->entries[smp_processor_id()];
    344
    345     e = get_entry(table_base, private->hook_entry[hook]);
    346
    347     /* For return from builtin chain */
    348     back = get_entry(table_base, private->underflow[hook]);
get_entry():
185 static inline struct ipt_entry *
    186 get_entry(void *base, unsigned int offset)
    187 {
    188     return (struct ipt_entry *)(base + offset);
    189 }
上面的代碼基本是就是從取出struct ipt_entry的地址,而struct xt_table_info中的hook_entry[]數(shù)組存放的就是struct ipt_entry的偏移量。
然后再往下:進(jìn)入死循環(huán)然后進(jìn)入函數(shù)
if (ip_packet_match(ip, indev, outdev,
    354             &e->ip, mtpar.fragoff)) {
這個函數(shù)的功能有詳細(xì)說明:
  68 /*
     69    We keep a set of rules for each CPU, so we can avoid write-locking
     70    them in the softirq when updating the counters and therefore
     71    only need to read-lock in the softirq; doing a write_lock_bh() in user
     72    context stops packets coming through and allows user context to read
     73    the counters or update the rules.
     74
     75    Hence the start of any table is given by get_table() below.  */
     76
     77 /* Returns whether matches rule or not. */
     78 /* Performance critical - called for every packet */
     79 static inline bool
     80 ip_packet_match(const struct iphdr *ip,
     81         const char *indev,
     82         const char *outdev,
     83         const struct ipt_ip *ipinfo,
     84         int isfrag)
     85 {
     86     unsigned long ret;
     87
     88 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
     89
     90     if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
     91           IPT_INV_SRCIP)
     92         || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
     93              IPT_INV_DSTIP)) {
     94         dprintf("Source or dest mismatch.\n");
     95
     96         dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
     97             &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
     98             ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
     99         dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
    100             &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
    101             ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
    102         return false;
    103     }
    104
    105     ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
    106
    107     if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
    108         dprintf("VIA in mismatch (%s vs %s).%s\n",
    109             indev, ipinfo->iniface,
    110             ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
    111         return false;
    112     }
    113
    114     ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
    115
    116     if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
    117         dprintf("VIA out mismatch (%s vs %s).%s\n",
    118             outdev, ipinfo->outiface,
    119             ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
    120         return false;
    121     }
    122
    123     /* Check specific protocol */
    124     if (ipinfo->proto
    125         && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
    126         dprintf("Packet protocol %hi does not match %hi.%s\n",
    127             ip->protocol, ipinfo->proto,
    128             ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
    129         return false;
    130     }
    131
    132     /* If we have a fragment rule but the packet is not a fragment
    133      * then we return zero */
    134     if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
    135         dprintf("Fragment rule but not fragment.%s\n",
    136             ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
    137         return false;
    138     }
    139
    140     return true;
    141 }
說說這個宏:#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
看看這個些宏先:

     61 /* Values for "flag" field in struct ipt_ip (general ip structure). */
     62 #define IPT_F_FRAG        0x01    /* Set if rule is a fragment rule */
     63 #define IPT_F_GOTO        0x02    /* Set if jump is a goto */
     64 #define IPT_F_MASK        0x03    /* All possible flag bits mask. */
     65
     66 /* Values for "inv" field in struct ipt_ip. */
     67 #define IPT_INV_VIA_IN        0x01    /* Invert the sense of IN IFACE. */
     68 #define IPT_INV_VIA_OUT        0x02    /* Invert the sense of OUT IFACE */
     69 #define IPT_INV_TOS        0x04    /* Invert the sense of TOS. */
     70 #define IPT_INV_SRCIP        0x08    /* Invert the sense of SRC IP. */
     71 #define IPT_INV_DSTIP        0x10    /* Invert the sense of DST OP. */
     72 #define IPT_INV_FRAG        0x20    /* Invert the sense of FRAG. */
     73 #define IPT_INV_PROTO        XT_INV_PROTO
     74 #define IPT_INV_MASK        0x7F    /* All possible flag bits mask. */
      75
               
將ipinfo->invflags與上面的宏中的一個相與。相與判斷了值是否相等,相=則為1,不=則為0,取反兩次,值不變,然后再與一個bool值想異或。當(dāng)bool和invflg的是一真一假的情況時,返回真。同時為真時,返回0,然后if語句不成立。
然后處理源和目標(biāo)ip地址,if語句的意義是:到達(dá)分組的源ip地址經(jīng)過掩碼處理后與規(guī)則中的ip不匹配并且規(guī)則中沒有包含某個宏定義,或者規(guī)則中包含了某個宏定義,但到達(dá)分組的源ip與規(guī)則中的ip地址匹配,if的第一部分返回真,同樣道理處理到達(dá)分組的目的ip地址。這兩部分任意部分為真時,源或者目標(biāo)地址不匹配。
然后下面
    ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
    106
    107     if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
    108         dprintf("VIA in mismatch (%s vs %s).%s\n",
    109             indev, ipinfo->iniface,
    110             ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
    111         return false;
    112     }
    113
    114     ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
    115
比較出口和入口。再下面就是協(xié)議的比較。
好,現(xiàn)在回到ipt_do_table,若ip_packet_match返回為假,即規(guī)則不匹配,則跳到
no_match:
      e = (void *)e + e->next_offset;
即下一條規(guī)則處。若匹配,則
    356        struct ipt_entry_target *t; 
    357        if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
    358                 goto no_match;
                t = ipt_get_target(e);
IPT_MATCH_ITERATE 實際執(zhí)行了do_match,進(jìn)行match的匹配;
看看do_match():
    169 /* Performance critical - called for every packet */
    170 static inline bool
    171 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
    172      struct xt_match_param *par)
    173 {
    174     par->match     = m->u.kernel.match;
    175     par->matchinfo = m->data;
    176
    177     /* Stop iteration if it doesn't match */
    178     if (!m->u.kernel.match->match(skb, par))
    179         return true;
    180     else
    181         return false;
    182 }
繼續(xù):
    9 struct xt_entry_match
     10 {
     11     union {
     12         struct {
     13             __u16 match_size;
     14
     15             /* Used by userspace */
     16             char name[XT_FUNCTION_MAXNAMELEN-1];
     17
     18             __u8 revision;
     19         } user;
     20         struct {
     21             __u16 match_size;
     22
     23             /* Used inside the kernel */
     24             struct xt_match *match;
     25         } kernel;
     26
     27         /* Total length */
     28         __u16 match_size;
     29     } u;
     30
     31     unsigned char data[0];
     32 };
     33
  269
    270 struct xt_match
    271 {
    272     struct list_head list;
    273
    274     const char name[XT_FUNCTION_MAXNAMELEN-1];
    275     u_int8_t revision;
    276
    277     /* Return true or false: return FALSE and set *hotdrop = 1 to
    278            force immediate packet drop. */
    279     /* Arguments changed since 2.6.9, as this must now handle
    280        non-linear skb, using skb_header_pointer and
    281        skb_ip_make_writable. */
    282     bool (*match)(const struct sk_buff *skb,
    283               const struct xt_match_param *);
    284
    285     /* Called when user tries to insert an entry of this type. */
    286     bool (*checkentry)(const struct xt_mtchk_param *);
    287
    288     /* Called when entry of this type deleted. */
    289     void (*destroy)(const struct xt_mtdtor_param *);
    290
    291     /* Called when userspace align differs from kernel space one */
    292     void (*compat_from_user)(void *dst, void *src);
    293     int (*compat_to_user)(void __user *dst, void *src);
    294
    295     /* Set this to THIS_MODULE if you are a module, otherwise NULL */
    296     struct module *me;
    297
    298     /* Free to use by each match */
    299     unsigned long data;
    300
    301     const char *table;
    302     unsigned int matchsize;
    303     unsigned int compatsize;
    304     unsigned int hooks;
    305     unsigned short proto;
    306
    307     unsigned short family;
    308 };
    309
若不匹配,則no_match,匹配的話,然后,獲取target的地址。   
    226 ipt_get_target(struct ipt_entry *e)
    227 {
    228     return (void *)e + e->target_offset;
    229 }
現(xiàn)在target_offset的作用于是明顯了,保存了struct ipt_entry_target 結(jié)構(gòu)。再回想下struct ipt_entry結(jié)構(gòu)中的定義:
   86         /* Size of ipt_entry + matches */
     87         u_int16_t target_offset;
     88         /* Size of ipt_entry + matches + target */
     89         u_int16_t next_offset;
struct xt_entry_target結(jié)構(gòu)如下:
  34 struct xt_entry_target
     35 {
     36     union {
     37         struct {
     38             __u16 target_size;
     39
     40             /* Used by userspace */
     41             char name[XT_FUNCTION_MAXNAMELEN-1];
     42
     43             __u8 revision;
     44         } user;
     45         struct {
     46             __u16 target_size;
     47
     48             /* Used inside the kernel */
     49             struct xt_target *target;
     50         } kernel;
     51
     52         /* Total length */
     53         __u16 target_size;
     54     } u;
     55
     56     unsigned char data[0];
     57 };   
又是一個結(jié)構(gòu)體strcut_target
   311 struct xt_target
    312 {
    313     struct list_head list;
    314
    315     const char name[XT_FUNCTION_MAXNAMELEN-1];
    316
    317     /* Returns verdict. Argument order changed since 2.6.9, as this
    318        must now handle non-linear skbs, using skb_copy_bits and
    319        skb_ip_make_writable. */
    320     unsigned int (*target)(struct sk_buff *skb,
    321                    const struct xt_target_param *);
    322
    323     /* Called when user tries to insert an entry of this type:
    324            hook_mask is a bitmask of hooks from which it can be
    325            called. */
    326     /* Should return true or false. */
    327     bool (*checkentry)(const struct xt_tgchk_param *);
    328
    329     /* Called when entry of this type deleted. */
    330     void (*destroy)(const struct xt_tgdtor_param *);
    331
    332     /* Called when userspace align differs from kernel space one */
    333     void (*compat_from_user)(void *dst, void *src);
    334     int (*compat_to_user)(void __user *dst, void *src);
    335
    336     /* Set this to THIS_MODULE if you are a module, otherwise NULL */
    337     struct module *me;
    338
    339     const char *table;
    340     unsigned int targetsize;
    341     unsigned int compatsize;
    342     unsigned int hooks;
    343     unsigned short proto;
    344
    345     unsigned short family;
    346     u_int8_t revision;
    347 };
    348
暈菜,現(xiàn)在為止,了解了struct ipt_entry中的struct ipt_ip用于了規(guī)則的保存,target_offset用于保存了一個指向struct xt_entry_match的偏移量,它里面的成員結(jié)構(gòu)體struct xt_match;然后next_offset 指向了下一個ipt_entry,
如果對ipt_ip匹配ok,則執(zhí)行ipt_entry_match匹配,若ok,則執(zhí)行xt_entry_target
不過到這里,問題來了,什么是match,什么又是target ,暈菜了。。。
               
               
               
               
               
               

本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u3/102292/showart_2085413.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP