BPF (berkeley packet filter)....libpcap

Тема в разделе "WASM.BEGINNERS", создана пользователем featurelles, 26 окт 2009.

  1. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Вопрос относится вобщем-то к Linux , но кто знает может и в win одни и теже методы используются.
    BPF фильтрует трафик приходящий на сетевой адаптер,
    библиотека libpcap использует BPF для установки фильтров, снифров..и тд ( )

    Вобщем, вопрос прост.
    Каким образом этот BPF ставит перехватчик сетевых пакетов??!!??
    В Linux есть свои фильтры (LSF) , я думал что это одно и тоже, что принцип действия один и тотже. Зарегистрировать перехватчик через функцию ядра nf_register_hook.
    Но когда запускаю одно из приложений использующее libpcap, nf_register_hook не используется а фильтры ставятся и действуют.
    Так как действуют приложения написанные на libpcap (как действует этот BPF)??

    (просьба не посылать изучать исходники libpcap )
     
  2. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    featurelles
    Ни у кого никаких догадок нет?
    Как-то не верится, что никто с этой библиотекой не сталкивался.
     
  3. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Чё за чушь?
    я спросил, вдруг кто сталкивался с его работой и знает , как происходит установка фильтров.
     
  4. featurelles

    featurelles New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2009
    Сообщения:
    562
    Я их просмотрел, там какая-то жопа. Кода уйма, всё на define.
    Яб сам справился, еслиб знал в какой из тамошних файлов смотреть.
    например смотрю libpcap-0.8.1/bpf/net/bpf_filter.c логично предполагая, что это то что нужно.
    Код (Text):
    1. /*-
    2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
    3.  *    The Regents of the University of California.  All rights reserved.
    4.  *
    5.  * This code is derived from the Stanford/CMU enet packet filter,
    6.  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
    7.  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
    8.  * Berkeley Laboratory.
    9.  *
    10.  * Redistribution and use in source and binary forms, with or without
    11.  * modification, are permitted provided that the following conditions
    12.  * are met:
    13.  * 1. Redistributions of source code must retain the above copyright
    14.  *    notice, this list of conditions and the following disclaimer.
    15.  * 2. Redistributions in binary form must reproduce the above copyright
    16.  *    notice, this list of conditions and the following disclaimer in the
    17.  *    documentation and/or other materials provided with the distribution.
    18.  * 3. All advertising materials mentioning features or use of this software
    19.  *    must display the following acknowledgement:
    20.  *    This product includes software developed by the University of
    21.  *    California, Berkeley and its contributors.
    22.  * 4. Neither the name of the University nor the names of its contributors
    23.  *    may be used to endorse or promote products derived from this software
    24.  *    without specific prior written permission.
    25.  *
    26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    36.  * SUCH DAMAGE.
    37.  *
    38.  *    @(#)bpf.c    7.5 (Berkeley) 7/15/91
    39.  */
    40.  
    41. #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
    42. static const char rcsid[] _U_ =
    43.     "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.43.2.1 2003/11/15 23:26:49 guy Exp $ (LBL)";
    44. #endif
    45.  
    46. #ifdef HAVE_CONFIG_H
    47. #include "config.h"
    48. #endif
    49.  
    50. #ifdef WIN32
    51.  
    52. #include <pcap-stdinc.h>
    53.  
    54. #else /* WIN32 */
    55.  
    56. #include <sys/param.h>
    57. #include <sys/types.h>
    58. #include <sys/time.h>
    59.  
    60. #define    SOLARIS    (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
    61. #if defined(__hpux) || SOLARIS
    62. # include <sys/sysmacros.h>
    63. # include <sys/stream.h>
    64. # define    mbuf    msgb
    65. # define    m_next    b_cont
    66. # define    MLEN(m)    ((m)->b_wptr - (m)->b_rptr)
    67. # define    mtod(m,t)    ((t)(m)->b_rptr)
    68. #else
    69. # define    MLEN(m)    ((m)->m_len)
    70. #endif
    71.  
    72. #endif /* WIN32 */
    73.  
    74. #include <pcap-bpf.h>
    75.  
    76. #if !defined(KERNEL) && !defined(_KERNEL)
    77. #include <stdlib.h>
    78. #endif
    79.  
    80. #define int32 bpf_int32
    81. #define u_int32 bpf_u_int32
    82.  
    83. #ifndef LBL_ALIGN
    84. /*
    85.  * XXX - IA-64?  If not, this probably won't work on Win64 IA-64
    86.  * systems, unless LBL_ALIGN is defined elsewhere for them.
    87.  * XXX - SuperH?  If not, this probably won't work on WinCE SuperH
    88.  * systems, unless LBL_ALIGN is defined elsewhere for them.
    89.  */
    90. #if defined(sparc) || defined(__sparc__) || defined(mips) || \
    91.     defined(ibm032) || defined(__alpha) || defined(__hpux) || \
    92.     defined(__arm__)
    93. #define LBL_ALIGN
    94. #endif
    95. #endif
    96.  
    97. #ifndef LBL_ALIGN
    98. #ifndef WIN32
    99. #include <netinet/in.h>
    100. #endif
    101.  
    102. #define EXTRACT_SHORT(p)    ((u_short)ntohs(*(u_short *)p))
    103. #define EXTRACT_LONG(p)        (ntohl(*(u_int32 *)p))
    104. #else
    105. #define EXTRACT_SHORT(p)\
    106.     ((u_short)\
    107.         ((u_short)*((u_char *)p+0)<<8|\
    108.          (u_short)*((u_char *)p+1)<<0))
    109. #define EXTRACT_LONG(p)\
    110.         ((u_int32)*((u_char *)p+0)<<24|\
    111.          (u_int32)*((u_char *)p+1)<<16|\
    112.          (u_int32)*((u_char *)p+2)<<8|\
    113.          (u_int32)*((u_char *)p+3)<<0)
    114. #endif
    115.  
    116. #if defined(KERNEL) || defined(_KERNEL)
    117. # if !defined(__hpux) && !SOLARIS
    118. #include <sys/mbuf.h>
    119. # endif
    120. #define MINDEX(len, _m, _k) \
    121. { \
    122.     len = MLEN(m); \
    123.     while ((_k) >= len) { \
    124.         (_k) -= len; \
    125.         (_m) = (_m)->m_next; \
    126.         if ((_m) == 0) \
    127.             return 0; \
    128.         len = MLEN(m); \
    129.     } \
    130. }
    131.  
    132. static int
    133. m_xword(m, k, err)
    134.     register struct mbuf *m;
    135.     register int k, *err;
    136. {
    137.     register int len;
    138.     register u_char *cp, *np;
    139.     register struct mbuf *m0;
    140.  
    141.     MINDEX(len, m, k);
    142.     cp = mtod(m, u_char *) + k;
    143.     if (len - k >= 4) {
    144.         *err = 0;
    145.         return EXTRACT_LONG(cp);
    146.     }
    147.     m0 = m->m_next;
    148.     if (m0 == 0 || MLEN(m0) + len - k < 4)
    149.         goto bad;
    150.     *err = 0;
    151.     np = mtod(m0, u_char *);
    152.     switch (len - k) {
    153.  
    154.     case 1:
    155.         return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
    156.  
    157.     case 2:
    158.         return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
    159.  
    160.     default:
    161.         return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
    162.     }
    163.     bad:
    164.     *err = 1;
    165.     return 0;
    166. }
    167.  
    168. static int
    169. m_xhalf(m, k, err)
    170.     register struct mbuf *m;
    171.     register int k, *err;
    172. {
    173.     register int len;
    174.     register u_char *cp;
    175.     register struct mbuf *m0;
    176.  
    177.     MINDEX(len, m, k);
    178.     cp = mtod(m, u_char *) + k;
    179.     if (len - k >= 2) {
    180.         *err = 0;
    181.         return EXTRACT_SHORT(cp);
    182.     }
    183.     m0 = m->m_next;
    184.     if (m0 == 0)
    185.         goto bad;
    186.     *err = 0;
    187.     return (cp[0] << 8) | mtod(m0, u_char *)[0];
    188.  bad:
    189.     *err = 1;
    190.     return 0;
    191. }
    192. #endif
    193.  
    194. /*
    195.  * Execute the filter program starting at pc on the packet p
    196.  * wirelen is the length of the original packet
    197.  * buflen is the amount of data present
    198.  * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
    199.  * in all other cases, p is a pointer to a buffer and buflen is its size.
    200.  */
    201. u_int
    202. bpf_filter(pc, p, wirelen, buflen)
    203.     register struct bpf_insn *pc;
    204.     register u_char *p;
    205.     u_int wirelen;
    206.     register u_int buflen;
    207. {
    208.     register u_int32 A, X;
    209.     register int k;
    210.     int32 mem[BPF_MEMWORDS];
    211. #if defined(KERNEL) || defined(_KERNEL)
    212.     struct mbuf *m, *n;
    213.     int merr, len;
    214.  
    215.     if (buflen == 0) {
    216.         m = (struct mbuf *)p;
    217.         p = mtod(m, u_char *);
    218.         buflen = MLEN(m);
    219.     } else
    220.         m = NULL;
    221. #endif
    222.  
    223.     if (pc == 0)
    224.         /*
    225.          * No filter means accept all.
    226.          */
    227.         return (u_int)-1;
    228.     A = 0;
    229.     X = 0;
    230.     --pc;
    231.     while (1) {
    232.         ++pc;
    233.         switch (pc->code) {
    234.  
    235.         default:
    236. #if defined(KERNEL) || defined(_KERNEL)
    237.             return 0;
    238. #else
    239.             abort();
    240. #endif
    241.         case BPF_RET|BPF_K:
    242.             return (u_int)pc->k;
    243.  
    244.         case BPF_RET|BPF_A:
    245.             return (u_int)A;
    246.  
    247.         case BPF_LD|BPF_W|BPF_ABS:
    248.             k = pc->k;
    249.             if (k + sizeof(int32) > buflen) {
    250. #if defined(KERNEL) || defined(_KERNEL)
    251.                 if (m == NULL)
    252.                     return 0;
    253.                 A = m_xword(m, k, &merr);
    254.                 if (merr != 0)
    255.                     return 0;
    256.                 continue;
    257. #else
    258.                 return 0;
    259. #endif
    260.             }
    261.             A = EXTRACT_LONG(&p[k]);
    262.             continue;
    263.  
    264.         case BPF_LD|BPF_H|BPF_ABS:
    265.             k = pc->k;
    266.             if (k + sizeof(short) > buflen) {
    267. #if defined(KERNEL) || defined(_KERNEL)
    268.                 if (m == NULL)
    269.                     return 0;
    270.                 A = m_xhalf(m, k, &merr);
    271.                 if (merr != 0)
    272.                     return 0;
    273.                 continue;
    274. #else
    275.                 return 0;
    276. #endif
    277.             }
    278.             A = EXTRACT_SHORT(&p[k]);
    279.             continue;
    280.  
    281.         case BPF_LD|BPF_B|BPF_ABS:
    282.             k = pc->k;
    283.             if (k >= buflen) {
    284. #if defined(KERNEL) || defined(_KERNEL)
    285.                 if (m == NULL)
    286.                     return 0;
    287.                 n = m;
    288.                 MINDEX(len, n, k);
    289.                 A = mtod(n, u_char *)[k];
    290.                 continue;
    291. #else
    292.                 return 0;
    293. #endif
    294.             }
    295.             A = p[k];
    296.             continue;
    297.  
    298.         case BPF_LD|BPF_W|BPF_LEN:
    299.             A = wirelen;
    300.             continue;
    301.  
    302.         case BPF_LDX|BPF_W|BPF_LEN:
    303.             X = wirelen;
    304.             continue;
    305.  
    306.         case BPF_LD|BPF_W|BPF_IND:
    307.             k = X + pc->k;
    308.             if (k + sizeof(int32) > buflen) {
    309. #if defined(KERNEL) || defined(_KERNEL)
    310.                 if (m == NULL)
    311.                     return 0;
    312.                 A = m_xword(m, k, &merr);
    313.                 if (merr != 0)
    314.                     return 0;
    315.                 continue;
    316. #else
    317.                 return 0;
    318. #endif
    319.             }
    320.             A = EXTRACT_LONG(&p[k]);
    321.             continue;
    322.  
    323.         case BPF_LD|BPF_H|BPF_IND:
    324.             k = X + pc->k;
    325.             if (k + sizeof(short) > buflen) {
    326. #if defined(KERNEL) || defined(_KERNEL)
    327.                 if (m == NULL)
    328.                     return 0;
    329.                 A = m_xhalf(m, k, &merr);
    330.                 if (merr != 0)
    331.                     return 0;
    332.                 continue;
    333. #else
    334.                 return 0;
    335. #endif
    336.             }
    337.             A = EXTRACT_SHORT(&p[k]);
    338.             continue;
    339.  
    340.         case BPF_LD|BPF_B|BPF_IND:
    341.             k = X + pc->k;
    342.             if (k >= buflen) {
    343. #if defined(KERNEL) || defined(_KERNEL)
    344.                 if (m == NULL)
    345.                     return 0;
    346.                 n = m;
    347.                 MINDEX(len, n, k);
    348.                 A = mtod(n, u_char *)[k];
    349.                 continue;
    350. #else
    351.                 return 0;
    352. #endif
    353.             }
    354.             A = p[k];
    355.             continue;
    356.  
    357.         case BPF_LDX|BPF_MSH|BPF_B:
    358.             k = pc->k;
    359.             if (k >= buflen) {
    360. #if defined(KERNEL) || defined(_KERNEL)
    361.                 if (m == NULL)
    362.                     return 0;
    363.                 n = m;
    364.                 MINDEX(len, n, k);
    365.                 X = (mtod(n, char *)[k] & 0xf) << 2;
    366.                 continue;
    367. #else
    368.                 return 0;
    369. #endif
    370.             }
    371.             X = (p[pc->k] & 0xf) << 2;
    372.             continue;
    373.  
    374.         case BPF_LD|BPF_IMM:
    375.             A = pc->k;
    376.             continue;
    377.  
    378.         case BPF_LDX|BPF_IMM:
    379.             X = pc->k;
    380.             continue;
    381.  
    382.         case BPF_LD|BPF_MEM:
    383.             A = mem[pc->k];
    384.             continue;
    385.  
    386.         case BPF_LDX|BPF_MEM:
    387.             X = mem[pc->k];
    388.             continue;
    389.  
    390.         case BPF_ST:
    391.             mem[pc->k] = A;
    392.             continue;
    393.  
    394.         case BPF_STX:
    395.             mem[pc->k] = X;
    396.             continue;
    397.  
    398.         case BPF_JMP|BPF_JA:
    399.             pc += pc->k;
    400.             continue;
    401.  
    402.         case BPF_JMP|BPF_JGT|BPF_K:
    403.             pc += (A > pc->k) ? pc->jt : pc->jf;
    404.             continue;
    405.  
    406.         case BPF_JMP|BPF_JGE|BPF_K:
    407.             pc += (A >= pc->k) ? pc->jt : pc->jf;
    408.             continue;
    409.  
    410.         case BPF_JMP|BPF_JEQ|BPF_K:
    411.             pc += (A == pc->k) ? pc->jt : pc->jf;
    412.             continue;
    413.  
    414.         case BPF_JMP|BPF_JSET|BPF_K:
    415.             pc += (A & pc->k) ? pc->jt : pc->jf;
    416.             continue;
    417.  
    418.         case BPF_JMP|BPF_JGT|BPF_X:
    419.             pc += (A > X) ? pc->jt : pc->jf;
    420.             continue;
    421.  
    422.         case BPF_JMP|BPF_JGE|BPF_X:
    423.             pc += (A >= X) ? pc->jt : pc->jf;
    424.             continue;
    425.  
    426.         case BPF_JMP|BPF_JEQ|BPF_X:
    427.             pc += (A == X) ? pc->jt : pc->jf;
    428.             continue;
    429.  
    430.         case BPF_JMP|BPF_JSET|BPF_X:
    431.             pc += (A & X) ? pc->jt : pc->jf;
    432.             continue;
    433.  
    434.         case BPF_ALU|BPF_ADD|BPF_X:
    435.             A += X;
    436.             continue;
    437.  
    438.         case BPF_ALU|BPF_SUB|BPF_X:
    439.             A -= X;
    440.             continue;
    441.  
    442.         case BPF_ALU|BPF_MUL|BPF_X:
    443.             A *= X;
    444.             continue;
    445.  
    446.         case BPF_ALU|BPF_DIV|BPF_X:
    447.             if (X == 0)
    448.                 return 0;
    449.             A /= X;
    450.             continue;
    451.  
    452.         case BPF_ALU|BPF_AND|BPF_X:
    453.             A &= X;
    454.             continue;
    455.  
    456.         case BPF_ALU|BPF_OR|BPF_X:
    457.             A |= X;
    458.             continue;
    459.  
    460.         case BPF_ALU|BPF_LSH|BPF_X:
    461.             A <<= X;
    462.             continue;
    463.  
    464.         case BPF_ALU|BPF_RSH|BPF_X:
    465.             A >>= X;
    466.             continue;
    467.  
    468.         case BPF_ALU|BPF_ADD|BPF_K:
    469.             A += pc->k;
    470.             continue;
    471.  
    472.         case BPF_ALU|BPF_SUB|BPF_K:
    473.             A -= pc->k;
    474.             continue;
    475.  
    476.         case BPF_ALU|BPF_MUL|BPF_K:
    477.             A *= pc->k;
    478.             continue;
    479.  
    480.         case BPF_ALU|BPF_DIV|BPF_K:
    481.             A /= pc->k;
    482.             continue;
    483.  
    484.         case BPF_ALU|BPF_AND|BPF_K:
    485.             A &= pc->k;
    486.             continue;
    487.  
    488.         case BPF_ALU|BPF_OR|BPF_K:
    489.             A |= pc->k;
    490.             continue;
    491.  
    492.         case BPF_ALU|BPF_LSH|BPF_K:
    493.             A <<= pc->k;
    494.             continue;
    495.  
    496.         case BPF_ALU|BPF_RSH|BPF_K:
    497.             A >>= pc->k;
    498.             continue;
    499.  
    500.         case BPF_ALU|BPF_NEG:
    501.             A = -A;
    502.             continue;
    503.  
    504.         case BPF_MISC|BPF_TAX:
    505.             X = A;
    506.             continue;
    507.  
    508.         case BPF_MISC|BPF_TXA:
    509.             A = X;
    510.             continue;
    511.         }
    512.     }
    513. }
    514.  
    515.  
    516. /*
    517.  * Return true if the 'fcode' is a valid filter program.
    518.  * The constraints are that each jump be forward and to a valid
    519.  * code.  The code must terminate with either an accept or reject.
    520.  * 'valid' is an array for use by the routine (it must be at least
    521.  * 'len' bytes long).
    522.  *
    523.  * The kernel needs to be able to verify an application's filter code.
    524.  * Otherwise, a bogus program could easily crash the system.
    525.  */
    526. int
    527. bpf_validate(f, len)
    528.     struct bpf_insn *f;
    529.     int len;
    530. {
    531.     register int i;
    532.     register struct bpf_insn *p;
    533.  
    534.     for (i = 0; i < len; ++i) {
    535.         /*
    536.          * Check that that jumps are forward, and within
    537.          * the code block.
    538.          */
    539.         p = &f[i];
    540.         if (BPF_CLASS(p->code) == BPF_JMP) {
    541.             register int from = i + 1;
    542.  
    543.             if (BPF_OP(p->code) == BPF_JA) {
    544.                 if (from + p->k >= (unsigned)len)
    545.                     return 0;
    546.             }
    547.             else if (from + p->jt >= len || from + p->jf >= len)
    548.                 return 0;
    549.         }
    550.         /*
    551.          * Check that memory operations use valid addresses.
    552.          */
    553.         if ((BPF_CLASS(p->code) == BPF_ST ||
    554.              (BPF_CLASS(p->code) == BPF_LD &&
    555.               (p->code & 0xe0) == BPF_MEM)) &&
    556.             (p->k >= BPF_MEMWORDS || p->k < 0))
    557.             return 0;
    558.         /*
    559.          * Check for constant division by 0.
    560.          */
    561.         if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
    562.             return 0;
    563.     }
    564.     return BPF_CLASS(f[len - 1].code) == BPF_RET;
    565. }
    Но почемуто мне кажется это не то (я ничего не понимаю что там понаписано)



    Уверен что нужный мне код, находится в файле pcap-linux.c
    так как она подключает "нужные файлы"
    #include <linux/filter.h>
    #include <net/if.h>
    #include <netinet/in.h>
    #include <linux/if_ether.h>
    #include <net/if_arp.h>

    да и функции, "правильные"

    static void map_arphrd_to_dlt(pcap_t *, int, int);
    static int live_open_old(pcap_t *, const char *, int, int, char *);
    static int live_open_new(pcap_t *, const char *, int, int, char *);
    static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
    static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
    static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
    static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
    static void pcap_close_linux(pcap_t *);

    Вот код функции регистрации фильтра
    Код (Text):
    1. static int
    2. pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
    3. {
    4. #ifdef SO_ATTACH_FILTER
    5.     struct sock_fprog    fcode;
    6.     int            can_filter_in_kernel;
    7.     int            err = 0;
    8. #endif
    9.  
    10.     if (!handle)
    11.         return -1;
    12.     if (!filter) {
    13.             strncpy(handle->errbuf, "setfilter: No filter specified",
    14.             sizeof(handle->errbuf));
    15.         return -1;
    16.     }
    17.  
    18.     /* Make our private copy of the filter */
    19.  
    20.     if (install_bpf_program(handle, filter) < 0)
    21.         /* install_bpf_program() filled in errbuf */
    22.         return -1;
    23.  
    24.     /*
    25.      * Run user level packet filter by default. Will be overriden if
    26.      * installing a kernel filter succeeds.
    27.      */
    28.     handle->md.use_bpf = 0;
    29.  
    30.     /* Install kernel level filter if possible */
    31.  
    32. #ifdef SO_ATTACH_FILTER
    33. #ifdef USHRT_MAX
    34.     if (handle->fcode.bf_len > USHRT_MAX) {
    35.         /*
    36.          * fcode.len is an unsigned short for current kernel.
    37.          * I have yet to see BPF-Code with that much
    38.          * instructions but still it is possible. So for the
    39.          * sake of correctness I added this check.
    40.          */
    41.         fprintf(stderr, "Warning: Filter too complex for kernel\n");
    42.         fcode.filter = NULL;
    43.         can_filter_in_kernel = 0;
    44.     } else
    45. #endif /* USHRT_MAX */
    46.     {
    47.         /*
    48.          * Oh joy, the Linux kernel uses struct sock_fprog instead
    49.          * of struct bpf_program and of course the length field is
    50.          * of different size. Pointed out by Sebastian
    51.          *
    52.          * Oh, and we also need to fix it up so that all "ret"
    53.          * instructions with non-zero operands have 65535 as the
    54.          * operand, and so that, if we're in cooked mode, all
    55.          * memory-reference instructions use special magic offsets
    56.          * in references to the link-layer header and assume that
    57.          * the link-layer payload begins at 0; "fix_program()"
    58.          * will do that.
    59.          */
    60.         switch (fix_program(handle, &fcode)) {
    61.  
    62.         case -1:
    63.         default:
    64.             /*
    65.              * Fatal error; just quit.
    66.              * (The "default" case shouldn't happen; we
    67.              * return -1 for that reason.)
    68.              */
    69.             return -1;
    70.  
    71.         case 0:
    72.             /*
    73.              * The program performed checks that we can't make
    74.              * work in the kernel.
    75.              */
    76.             can_filter_in_kernel = 0;
    77.             break;
    78.  
    79.         case 1:
    80.             /*
    81.              * We have a filter that'll work in the kernel.
    82.              */
    83.             can_filter_in_kernel = 1;
    84.             break;
    85.         }
    86.     }
    87.  
    88.     if (can_filter_in_kernel) {
    89.         if ((err = set_kernel_filter(handle, &fcode)) == 0)
    90.         {
    91.             /* Installation succeded - using kernel filter. */
    92.             handle->md.use_bpf = 1;
    93.         }
    94.         else if (err == -1)    /* Non-fatal error */
    95.         {
    96.             /*
    97.              * Print a warning if we weren't able to install
    98.              * the filter for a reason other than "this kernel
    99.              * isn't configured to support socket filters.
    100.              */
    101.             if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
    102.                 fprintf(stderr,
    103.                     "Warning: Kernel filter failed: %s\n",
    104.                     pcap_strerror(errno));
    105.             }
    106.         }
    107.     }
    108.  
    109.     /*
    110.      * If we're not using the kernel filter, get rid of any kernel
    111.      * filter that might've been there before, e.g. because the
    112.      * previous filter could work in the kernel, or because some other
    113.      * code attached a filter to the socket by some means other than
    114.      * calling "pcap_setfilter()".  Otherwise, the kernel filter may
    115.      * filter out packets that would pass the new userland filter.
    116.      */
    117.     if (!handle->md.use_bpf)
    118.         reset_kernel_filter(handle);
    119.  
    120.     /*
    121.      * Free up the copy of the filter that was made by "fix_program()".
    122.      */
    123.     if (fcode.filter != NULL)
    124.         free(fcode.filter);
    125.  
    126.     if (err == -2)
    127.         /* Fatal error */
    128.         return -1;
    129. #endif /* SO_ATTACH_FILTER */
    130.  
    131.     return 0;
    132. }
    Из этой функции вызывается set_kernel_filter
    смотрю эту функцию.
    И не вижу ничего.
    Код (Text):
    1. static int
    2. set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
    3. {
    4.     int total_filter_on = 0;
    5.     int save_mode;
    6.     int ret;
    7.     int save_errno;
    8.  
    9.     /*
    10.      * The socket filter code doesn't discard all packets queued
    11.      * up on the socket when the filter is changed; this means
    12.      * that packets that don't match the new filter may show up
    13.      * after the new filter is put onto the socket, if those
    14.      * packets haven't yet been read.
    15.      *
    16.      * This means, for example, that if you do a tcpdump capture
    17.      * with a filter, the first few packets in the capture might
    18.      * be packets that wouldn't have passed the filter.
    19.      *
    20.      * We therefore discard all packets queued up on the socket
    21.      * when setting a kernel filter.  (This isn't an issue for
    22.      * userland filters, as the userland filtering is done after
    23.      * packets are queued up.)
    24.      *
    25.      * To flush those packets, we put the socket in read-only mode,
    26.      * and read packets from the socket until there are no more to
    27.      * read.
    28.      *
    29.      * In order to keep that from being an infinite loop - i.e.,
    30.      * to keep more packets from arriving while we're draining
    31.      * the queue - we put the "total filter", which is a filter
    32.      * that rejects all packets, onto the socket before draining
    33.      * the queue.
    34.      *
    35.      * This code deliberately ignores any errors, so that you may
    36.      * get bogus packets if an error occurs, rather than having
    37.      * the filtering done in userland even if it could have been
    38.      * done in the kernel.
    39.      */
    40.     if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
    41.                &total_fcode, sizeof(total_fcode)) == 0) {
    42.         char drain[1];
    43.  
    44.         /*
    45.          * Note that we've put the total filter onto the socket.
    46.          */
    47.         total_filter_on = 1;
    48.  
    49.         /*
    50.          * Save the socket's current mode, and put it in
    51.          * non-blocking mode; we drain it by reading packets
    52.          * until we get an error (which is normally a
    53.          * "nothing more to be read" error).
    54.          */
    55.         save_mode = fcntl(handle->fd, F_GETFL, 0);
    56.         if (save_mode != -1 &&
    57.             fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) {
    58.             while (recv(handle->fd, &drain, sizeof drain,
    59.                    MSG_TRUNC) >= 0)
    60.                 ;
    61.             save_errno = errno;
    62.             fcntl(handle->fd, F_SETFL, save_mode);
    63.             if (save_errno != EAGAIN) {
    64.                 /* Fatal error */
    65.                 reset_kernel_filter(handle);
    66.                 snprintf(handle->errbuf, sizeof(handle->errbuf),
    67.                  "recv: %s", pcap_strerror(save_errno));
    68.                 return -2;
    69.             }
    70.         }
    71.     }
    72.  
    73.     /*
    74.      * Now attach the new filter.
    75.      */
    76.     ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
    77.              fcode, sizeof(*fcode));
    78.     if (ret == -1 && total_filter_on) {
    79.         /*
    80.          * Well, we couldn't set that filter on the socket,
    81.          * but we could set the total filter on the socket.
    82.          *
    83.          * This could, for example, mean that the filter was
    84.          * too big to put into the kernel, so we'll have to
    85.          * filter in userland; in any case, we'll be doing
    86.          * filtering in userland, so we need to remove the
    87.          * total filter so we see packets.
    88.          */
    89.         save_errno = errno;
    90.  
    91.         /*
    92.          * XXX - if this fails, we're really screwed;
    93.          * we have the total filter on the socket,
    94.          * and it won't come off.  What do we do then?
    95.          */
    96.         reset_kernel_filter(handle);
    97.  
    98.         errno = save_errno;
    99.     }
    100.     return ret;
    101. }
    просмотрел функцию
    pcap_read_packet
    Там есть такой участок
    if (!handle->md.use_bpf && handle->fcode.bf_insns) {
    if (bpf_filter(handle->fcode.bf_insns, bp,
    packet_len, caplen) == 0)
    {
    /* rejected by filter */
    return 0;
    }

    направляюсь к функции bpf_filter она находится в
    /libpcap-0.8.1/bpf/net/bpf_filter.c

    И нихрена не понимаю..что происходит дальше????
    Никак не могу разобраться как этот bpf действует!
     
  5. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Судя по всему, там парсер, разбирающий мини-программу, которая
    описывает, как фильтровать пакеты.
     
  6. Voodoo

    Voodoo New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2003
    Сообщения:
    297
    Адрес:
    Новосибирск
    featurelles
    в приведенном тобой коде - ищи описания struct sock_fprog и setsockopt(... SOL_SOCKET, SO_ATTACH_FILTER...), они должны прояснить ситуацию.
     
  7. Shadovv13

    Shadovv13 Андрей

    Публикаций:
    0
    Регистрация:
    27 июл 2008
    Сообщения:
    65
    Адрес:
    Украина
    Привет!
    Я столкнулся с подобной ситуацыей, толко в Packet.dll (из состава WinPcap).

    Вот что извесно!!

    A single BPF pseudo-instruction.

    bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
    '
    TYPE bpf_insn
    code AS WORD '< Instruction Type And addressing mode.
    jt AS BYTE '< Jump If true
    jf AS BYTE '< Jump If false
    k AS LONG '< Generic field used For various purposes.
    END TYPE

    A BPF pseudo-assembly program.

    The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.

    TYPE bpf_program
    bf_len AS DWORD '< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.

    bf_insns AS bpf_insn PTR '< A pointer to the first instruction of the program.
    END TYPE

    Но самих команд ненашол!
    Итересно как у тебя обстоят дела!?