The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/bpf_filter.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e41e235b7a3cf6fcac0081c2722ed2ad


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.