home *** CD-ROM | disk | FTP | other *** search
/ Hackers Toolkit v2.0 / Hackers_Toolkit_v2.0.iso / HTML / archive / Unix / libpcap-0_4_tar.tar / libpcap-0_4_tar / libpcap-0.4 / bpf / net / bpf_filter.c next >
C/C++ Source or Header  |  1997-04-26  |  11KB  |  533 lines

  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))
  42. static const char rcsid[] =
  43.     "@(#) $Header: bpf_filter.c,v 1.33 97/04/26 13:37:18 leres Exp $ (LBL)";
  44. #endif
  45.  
  46. #include <sys/param.h>
  47. #include <sys/types.h>
  48. #include <sys/time.h>
  49. #include <net/bpf.h>
  50.  
  51. #ifndef KERNEL
  52. #include <stdlib.h>
  53. #endif
  54.  
  55. #define int32 bpf_int32
  56. #define u_int32 bpf_u_int32
  57.  
  58. #ifndef LBL_ALIGN
  59. #if defined(sparc) || defined(mips) || defined(ibm032) || \
  60.     defined(__alpha) || defined(__hpux)
  61. #define LBL_ALIGN
  62. #endif
  63. #endif
  64.  
  65. #ifndef LBL_ALIGN
  66. #include <netinet/in.h>
  67.  
  68. #define EXTRACT_SHORT(p)    ((u_short)ntohs(*(u_short *)p))
  69. #define EXTRACT_LONG(p)        (ntohl(*(u_int32 *)p))
  70. #else
  71. #define EXTRACT_SHORT(p)\
  72.     ((u_short)\
  73.         ((u_short)*((u_char *)p+0)<<8|\
  74.          (u_short)*((u_char *)p+1)<<0))
  75. #define EXTRACT_LONG(p)\
  76.         ((u_int32)*((u_char *)p+0)<<24|\
  77.          (u_int32)*((u_char *)p+1)<<16|\
  78.          (u_int32)*((u_char *)p+2)<<8|\
  79.          (u_int32)*((u_char *)p+3)<<0)
  80. #endif
  81.  
  82. #ifdef KERNEL
  83. #include <sys/mbuf.h>
  84. #define MINDEX(len, m, k) \
  85. { \
  86.     len = m->m_len; \
  87.     while (k >= len) { \
  88.         k -= len; \
  89.         m = m->m_next; \
  90.         if (m == 0) \
  91.             return 0; \
  92.         len = m->m_len; \
  93.     } \
  94. }
  95.  
  96. static int
  97. m_xword(m, k, err)
  98.     register struct mbuf *m;
  99.     register int k, *err;
  100. {
  101.     register int len;
  102.     register u_char *cp, *np;
  103.     register struct mbuf *m0;
  104.  
  105.     MINDEX(len, m, k);
  106.     cp = mtod(m, u_char *) + k;
  107.     if (len - k >= 4) {
  108.         *err = 0;
  109.         return EXTRACT_LONG(cp);
  110.     }
  111.     m0 = m->m_next;
  112.     if (m0 == 0 || m0->m_len + len - k < 4)
  113.         goto bad;
  114.     *err = 0;
  115.     np = mtod(m0, u_char *);
  116.     switch (len - k) {
  117.  
  118.     case 1:
  119.         return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
  120.  
  121.     case 2:
  122.         return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
  123.  
  124.     default:
  125.         return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
  126.     }
  127.     bad:
  128.     *err = 1;
  129.     return 0;
  130. }
  131.  
  132. static int
  133. m_xhalf(m, k, err)
  134.     register struct mbuf *m;
  135.     register int k, *err;
  136. {
  137.     register int len;
  138.     register u_char *cp;
  139.     register struct mbuf *m0;
  140.  
  141.     MINDEX(len, m, k);
  142.     cp = mtod(m, u_char *) + k;
  143.     if (len - k >= 2) {
  144.         *err = 0;
  145.         return EXTRACT_SHORT(cp);
  146.     }
  147.     m0 = m->m_next;
  148.     if (m0 == 0)
  149.         goto bad;
  150.     *err = 0;
  151.     return (cp[0] << 8) | mtod(m0, u_char *)[0];
  152.  bad:
  153.     *err = 1;
  154.     return 0;
  155. }
  156. #endif
  157.  
  158. /*
  159.  * Execute the filter program starting at pc on the packet p
  160.  * wirelen is the length of the original packet
  161.  * buflen is the amount of data present
  162.  */
  163. u_int
  164. bpf_filter(pc, p, wirelen, buflen)
  165.     register struct bpf_insn *pc;
  166.     register u_char *p;
  167.     u_int wirelen;
  168.     register u_int buflen;
  169. {
  170.     register u_int32 A, X;
  171.     register int k;
  172.     int32 mem[BPF_MEMWORDS];
  173.  
  174.     if (pc == 0)
  175.         /*
  176.          * No filter means accept all.
  177.          */
  178.         return (u_int)-1;
  179.     A = 0;
  180.     X = 0;
  181.     --pc;
  182.     while (1) {
  183.         ++pc;
  184.         switch (pc->code) {
  185.  
  186.         default:
  187. #ifdef KERNEL
  188.             return 0;
  189. #else
  190.             abort();
  191. #endif            
  192.         case BPF_RET|BPF_K:
  193.             return (u_int)pc->k;
  194.  
  195.         case BPF_RET|BPF_A:
  196.             return (u_int)A;
  197.  
  198.         case BPF_LD|BPF_W|BPF_ABS:
  199.             k = pc->k;
  200.             if (k + sizeof(int32) > buflen) {
  201. #ifdef KERNEL
  202.                 int merr;
  203.  
  204.                 if (buflen != 0)
  205.                     return 0;
  206.                 A = m_xword((struct mbuf *)p, k, &merr);
  207.                 if (merr != 0)
  208.                     return 0;
  209.                 continue;
  210. #else
  211.                 return 0;
  212. #endif
  213.             }
  214.             A = EXTRACT_LONG(&p[k]);
  215.             continue;
  216.  
  217.         case BPF_LD|BPF_H|BPF_ABS:
  218.             k = pc->k;
  219.             if (k + sizeof(short) > buflen) {
  220. #ifdef KERNEL
  221.                 int merr;
  222.  
  223.                 if (buflen != 0)
  224.                     return 0;
  225.                 A = m_xhalf((struct mbuf *)p, k, &merr);
  226.                 continue;
  227. #else
  228.                 return 0;
  229. #endif
  230.             }
  231.             A = EXTRACT_SHORT(&p[k]);
  232.             continue;
  233.  
  234.         case BPF_LD|BPF_B|BPF_ABS:
  235.             k = pc->k;
  236.             if (k >= buflen) {
  237. #ifdef KERNEL
  238.                 register struct mbuf *m;
  239.                 register int len;
  240.  
  241.                 if (buflen != 0)
  242.                     return 0;
  243.                 m = (struct mbuf *)p;
  244.                 MINDEX(len, m, k);
  245.                 A = mtod(m, u_char *)[k];
  246.                 continue;
  247. #else
  248.                 return 0;
  249. #endif
  250.             }
  251.             A = p[k];
  252.             continue;
  253.  
  254.         case BPF_LD|BPF_W|BPF_LEN:
  255.             A = wirelen;
  256.             continue;
  257.  
  258.         case BPF_LDX|BPF_W|BPF_LEN:
  259.             X = wirelen;
  260.             continue;
  261.  
  262.         case BPF_LD|BPF_W|BPF_IND:
  263.             k = X + pc->k;
  264.             if (k + sizeof(int32) > buflen) {
  265. #ifdef KERNEL
  266.                 int merr;
  267.  
  268.                 if (buflen != 0)
  269.                     return 0;
  270.                 A = m_xword((struct mbuf *)p, k, &merr);
  271.                 if (merr != 0)
  272.                     return 0;
  273.                 continue;
  274. #else
  275.                 return 0;
  276. #endif
  277.             }
  278.             A = EXTRACT_LONG(&p[k]);
  279.             continue;
  280.  
  281.         case BPF_LD|BPF_H|BPF_IND:
  282.             k = X + pc->k;
  283.             if (k + sizeof(short) > buflen) {
  284. #ifdef KERNEL
  285.                 int merr;
  286.  
  287.                 if (buflen != 0)
  288.                     return 0;
  289.                 A = m_xhalf((struct mbuf *)p, k, &merr);
  290.                 if (merr != 0)
  291.                     return 0;
  292.                 continue;
  293. #else
  294.                 return 0;
  295. #endif
  296.             }
  297.             A = EXTRACT_SHORT(&p[k]);
  298.             continue;
  299.  
  300.         case BPF_LD|BPF_B|BPF_IND:
  301.             k = X + pc->k;
  302.             if (k >= buflen) {
  303. #ifdef KERNEL
  304.                 register struct mbuf *m;
  305.                 register int len;
  306.  
  307.                 if (buflen != 0)
  308.                     return 0;
  309.                 m = (struct mbuf *)p;
  310.                 MINDEX(len, m, k);
  311.                 A = mtod(m, u_char *)[k];
  312.                 continue;
  313. #else
  314.                 return 0;
  315. #endif
  316.             }
  317.             A = p[k];
  318.             continue;
  319.  
  320.         case BPF_LDX|BPF_MSH|BPF_B:
  321.             k = pc->k;
  322.             if (k >= buflen) {
  323. #ifdef KERNEL
  324.                 register struct mbuf *m;
  325.                 register int len;
  326.  
  327.                 if (buflen != 0)
  328.                     return 0;
  329.                 m = (struct mbuf *)p;
  330.                 MINDEX(len, m, k);
  331.                 X = (mtod(m, char *)[k] & 0xf) << 2;
  332.                 continue;
  333. #else
  334.                 return 0;
  335. #endif
  336.             }
  337.             X = (p[pc->k] & 0xf) << 2;
  338.             continue;
  339.  
  340.         case BPF_LD|BPF_IMM:
  341.             A = pc->k;
  342.             continue;
  343.  
  344.         case BPF_LDX|BPF_IMM:
  345.             X = pc->k;
  346.             continue;
  347.  
  348.         case BPF_LD|BPF_MEM:
  349.             A = mem[pc->k];
  350.             continue;
  351.             
  352.         case BPF_LDX|BPF_MEM:
  353.             X = mem[pc->k];
  354.             continue;
  355.  
  356.         case BPF_ST:
  357.             mem[pc->k] = A;
  358.             continue;
  359.  
  360.         case BPF_STX:
  361.             mem[pc->k] = X;
  362.             continue;
  363.  
  364.         case BPF_JMP|BPF_JA:
  365.             pc += pc->k;
  366.             continue;
  367.  
  368.         case BPF_JMP|BPF_JGT|BPF_K:
  369.             pc += (A > pc->k) ? pc->jt : pc->jf;
  370.             continue;
  371.  
  372.         case BPF_JMP|BPF_JGE|BPF_K:
  373.             pc += (A >= pc->k) ? pc->jt : pc->jf;
  374.             continue;
  375.  
  376.         case BPF_JMP|BPF_JEQ|BPF_K:
  377.             pc += (A == pc->k) ? pc->jt : pc->jf;
  378.             continue;
  379.  
  380.         case BPF_JMP|BPF_JSET|BPF_K:
  381.             pc += (A & pc->k) ? pc->jt : pc->jf;
  382.             continue;
  383.  
  384.         case BPF_JMP|BPF_JGT|BPF_X:
  385.             pc += (A > X) ? pc->jt : pc->jf;
  386.             continue;
  387.  
  388.         case BPF_JMP|BPF_JGE|BPF_X:
  389.             pc += (A >= X) ? pc->jt : pc->jf;
  390.             continue;
  391.  
  392.         case BPF_JMP|BPF_JEQ|BPF_X:
  393.             pc += (A == X) ? pc->jt : pc->jf;
  394.             continue;
  395.  
  396.         case BPF_JMP|BPF_JSET|BPF_X:
  397.             pc += (A & X) ? pc->jt : pc->jf;
  398.             continue;
  399.  
  400.         case BPF_ALU|BPF_ADD|BPF_X:
  401.             A += X;
  402.             continue;
  403.             
  404.         case BPF_ALU|BPF_SUB|BPF_X:
  405.             A -= X;
  406.             continue;
  407.             
  408.         case BPF_ALU|BPF_MUL|BPF_X:
  409.             A *= X;
  410.             continue;
  411.             
  412.         case BPF_ALU|BPF_DIV|BPF_X:
  413.             if (X == 0)
  414.                 return 0;
  415.             A /= X;
  416.             continue;
  417.             
  418.         case BPF_ALU|BPF_AND|BPF_X:
  419.             A &= X;
  420.             continue;
  421.             
  422.         case BPF_ALU|BPF_OR|BPF_X:
  423.             A |= X;
  424.             continue;
  425.  
  426.         case BPF_ALU|BPF_LSH|BPF_X:
  427.             A <<= X;
  428.             continue;
  429.  
  430.         case BPF_ALU|BPF_RSH|BPF_X:
  431.             A >>= X;
  432.             continue;
  433.  
  434.         case BPF_ALU|BPF_ADD|BPF_K:
  435.             A += pc->k;
  436.             continue;
  437.             
  438.         case BPF_ALU|BPF_SUB|BPF_K:
  439.             A -= pc->k;
  440.             continue;
  441.             
  442.         case BPF_ALU|BPF_MUL|BPF_K:
  443.             A *= pc->k;
  444.             continue;
  445.             
  446.         case BPF_ALU|BPF_DIV|BPF_K:
  447.             A /= pc->k;
  448.             continue;
  449.             
  450.         case BPF_ALU|BPF_AND|BPF_K:
  451.             A &= pc->k;
  452.             continue;
  453.             
  454.         case BPF_ALU|BPF_OR|BPF_K:
  455.             A |= pc->k;
  456.             continue;
  457.  
  458.         case BPF_ALU|BPF_LSH|BPF_K:
  459.             A <<= pc->k;
  460.             continue;
  461.  
  462.         case BPF_ALU|BPF_RSH|BPF_K:
  463.             A >>= pc->k;
  464.             continue;
  465.  
  466.         case BPF_ALU|BPF_NEG:
  467.             A = -A;
  468.             continue;
  469.  
  470.         case BPF_MISC|BPF_TAX:
  471.             X = A;
  472.             continue;
  473.  
  474.         case BPF_MISC|BPF_TXA:
  475.             A = X;
  476.             continue;
  477.         }
  478.     }
  479. }
  480.  
  481. #ifdef KERNEL
  482. /*
  483.  * Return true if the 'fcode' is a valid filter program.
  484.  * The constraints are that each jump be forward and to a valid
  485.  * code.  The code must terminate with either an accept or reject. 
  486.  * 'valid' is an array for use by the routine (it must be at least
  487.  * 'len' bytes long).  
  488.  *
  489.  * The kernel needs to be able to verify an application's filter code.
  490.  * Otherwise, a bogus program could easily crash the system.
  491.  */
  492. int
  493. bpf_validate(f, len)
  494.     struct bpf_insn *f;
  495.     int len;
  496. {
  497.     register int i;
  498.     register struct bpf_insn *p;
  499.  
  500.     for (i = 0; i < len; ++i) {
  501.         /*
  502.          * Check that that jumps are forward, and within 
  503.          * the code block.
  504.          */
  505.         p = &f[i];
  506.         if (BPF_CLASS(p->code) == BPF_JMP) {
  507.             register int from = i + 1;
  508.  
  509.             if (BPF_OP(p->code) == BPF_JA) {
  510.                 if (from + p->k >= (unsigned)len)
  511.                     return 0;
  512.             }
  513.             else if (from + p->jt >= len || from + p->jf >= len)
  514.                 return 0;
  515.         }
  516.         /*
  517.          * Check that memory operations use valid addresses.
  518.          */
  519.         if ((BPF_CLASS(p->code) == BPF_ST ||
  520.              (BPF_CLASS(p->code) == BPF_LD && 
  521.               (p->code & 0xe0) == BPF_MEM)) &&
  522.             (p->k >= BPF_MEMWORDS || p->k < 0))
  523.             return 0;
  524.         /*
  525.          * Check for constant division by 0.
  526.          */
  527.         if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
  528.             return 0;
  529.     }
  530.     return BPF_CLASS(f[len - 1].code) == BPF_RET;
  531. }
  532. #endif
  533.